关于OneBot的QQ机器人探索2

关于OneBot的QQ机器人探索(第二期)

这是我去年编写的一个QQ聊天机器人,按照OneBot v11协议进行开发
当时刚入门,编写的代码耦合性较高,因此该代码仅能作为探索记录
代码太乱了,无法过多解释,有需要者自己看看吧(悲)


目前实现的主要功能有:

  • echo 消息回显
  • 搜索歌曲并发送音乐卡片
  • AI聊天,概率性主动回复,支持在QQ中使用指令切换AI模型和提示词
  • bing每日一图获取并发送
  • 群聊管理之敏感词检测并禁言

入口函数:

import asyncio
from bot import Bot, Command
from msgProcFunctions import *

async def main():
    cmd = Command("")
    # bot = Bot("ws://localhost:3001", cmd)
    # bot = Bot("ws://www.lyxyz5223.com:3001", cmd)
    bot = Bot("ws://localhost:5223", cmd)
    # bot = Bot("ws://localhost:3001", cmd)
    cmd.cmds.append(msgProc)
    await bot.connect()
    await bot.run()
    print("aa")

if __name__=='__main__':
    asyncio.run(main())

聊天机器人聊天消息分发


  • 由于代码开源方面问题,源OneBotv11接口的QQ消息数据处理相关类 暂不公开
wyyyyAPI = "https://docs-neteasecloudmusicapi.vercel.app/search?keywords="
wyyyyAPI = "https://music.163.com/api/search/get/web?csrf_token=hlpretag=&hlposttag=&type=1&offset=0&total=true&limit=10&s="
wyyyySearchList = []
wyyyySearch_Music_ID_List = []

import base64
import os
import time
from bot import Bot,Message_Type
from event import Event
from message import MessageList
import requests as req
import asyncio
import threading
import AIAPI#,AIollama
import random
import threading

# 全局读取敏感词列表
def is_base64(s):
    try:
        # 空字符串不是合法base64
        if not s or len(s) % 4 != 0:
            return False
        base64.b64decode(s, validate=True)
        return True
    except Exception:
        return False

# 1. 读取敏感词时记录来源文件
def load_badwords():
    badwords = []
    folder_path = os.path.join(os.path.dirname(__file__), "BadWords")
    if not os.path.exists(folder_path):
        print("敏感词文件夹不存在:", folder_path)
        return badwords
    for filename in os.listdir(folder_path):
        if filename.endswith(".txt"):
            file_path = os.path.join(folder_path, filename)
            try:
                with open(file_path, "r", encoding="utf-8") as f:
                    for line in f:
                        word = line.strip()
                        if word and is_base64(word):
                            try:
                                decoded = base64.b64decode(word).decode("utf-8")
                                badwords.append((decoded, filename))
                            except Exception as e:
                                print(f"敏感词解码失败(文件{filename}):", word, e)
                                badwords.append((word, filename))
                        elif word:
                            badwords.append((word, filename))
            except Exception as e:
                print(f"敏感词文件读取失败:{file_path}", e)
    return badwords

BADWORDS = load_badwords()
print("敏感词列表加载完成,共", len(BADWORDS), "个敏感词")
print("敏感词列表:", BADWORDS[:10])  # 打印前10个敏感词

# 2. 检查敏感词时返回命中词和文件名,并打印
def check_badwords(message: str):
    """
    检查消息是否包含敏感词
    :param message: 消息内容
    :return: 命中的敏感词及其文件名列表
    """
    hit_words = []
    for word, filename in BADWORDS:
        if word and word in message:
            print(f"命中敏感词:{word},文件:{filename}")
            hit_words.append((word, filename))
    return hit_words


async def echoProc(bot: Bot, m:Event, id:str, msg_type: Message_Type):
    msg = m.check().get_msg()
    
    f = 0
    send_msg = []
    for i in msg:
        if f == 0 and i["type"] == "at" and str(i["data"]["qq"]) == str(m.check().raw["self_id"]):
            f = 1
            continue
        else:
            send_msg.append(i)
    if send_msg[0]["type"] == "text":
        send_msg[0]["data"]["text"] = str(send_msg[0]["data"]["text"]).strip()[6:]
    await bot.send_msg(id,msg_type,send_msg)

async def bingProc(bot: Bot, zhiling:str, id:str,msg_type: Message_Type):
    zhiling = req.request(
        "get",
        "https://cn.bing.com/HPImageArchive.aspx",
        params={"format": "js", "idx": 0, "n": 1}
    )
    print(zhiling.text)
    zhiling = zhiling.json()
    zhiling = "https://cn.bing.com" + zhiling["images"][0]["url"]
    
    #"https://cn.bing.com/HPImageArchive.aspx?format=js&idx=0&n=1"
    await bot.send_msg(id,msg_type,[MessageList.image(str(zhiling))])

async def musicProc(bot: Bot, zhiling:str, id:str, msg_type: Message_Type):
    if(zhiling == "/music"):
        await bot.send_msg(id,msg_type,[MessageList.text("点歌格式(4种):\n首选:/music search 关键字,然后再/music select 列表数字序号 \n/music type id\n/music 1 title url\n/music 2 title openUrl audioUrl")])
        # await bot.send_msg(id,[MessageList.text("点歌格式:\n/music type id\n/music 1 title url\n/music 2 title openUrl audioUrl")])
        # await bot.send_msg(id,[MessageList.text("type:\n1:普通点歌\n2:普通点歌\n163:网易云点歌\nxm:虾米点歌\nqq:QQ音乐点歌")])
        # await bot.send_msg(id,[MessageList.text("id:\n1:普通点歌:歌曲名\n2:普通点歌:歌曲名\n163:网易云id\nxm:虾米id\nqq:QQ音乐id")])
        # await bot.send_msg(id,[MessageList.text("url:\n普通点歌:歌曲url")])
        # await bot.send_msg(id,[MessageList.text("openUrl:\n普通点歌:点击打开的url")])
        # await bot.send_msg(id,[MessageList.text("audioUrl:\n普通点歌:歌曲url")])
        # await bot.send_msg(id,[MessageList.text("示例:\n/music 1 歌曲名 歌曲url\n/music 2 歌曲名 点击打开的url 歌曲url\n/music 163 网易云id\n/music xm 虾米id\n/music qq QQ音乐id")])
        # await bot.send_msg(id,[MessageList.text("注意:\n/music 1 2 163 xm qq 后面必须跟空格")])
        await bot.send_msg(id,msg_type,[{
        "type": "music",
        "data": {
        "type": "custom",
        "url": "https://lw-sycdn.kuwo.cn/87898d2bfa406816e7a24dee4434e67c/66b3a70e/resource/30106/trackmedia/M5000004J5Dg2Aifkc.mp3?bitrate$128&from=vip",
        "audio": "https://lw-sycdn.kuwo.cn/87898d2bfa406816e7a24dee4434e67c/66b3a70e/resource/30106/trackmedia/M5000004J5Dg2Aifkc.mp3?bitrate$128&from=vip",
        "title": "Aurora - Hoaprox/Dang Minh"
        }
        }])
        pass
    musicNameAndUrl = zhiling.replace("/music", "").split()
    print("musicNameAndUrl",musicNameAndUrl)
    if musicNameAndUrl[0] == "163" or musicNameAndUrl[0] == "xm" or musicNameAndUrl[0] == "qq":
        await bot.send_msg(id,msg_type,[MessageList.Music(musicNameAndUrl[0], musicNameAndUrl[1])])# id点歌 /music type id
    musicTitle = " ".join(musicNameAndUrl[1:len(musicNameAndUrl)-1])
    musicNameAndUrl[0] = musicNameAndUrl[0].lower()#指令小写字母化
    match musicNameAndUrl[0]:
        case "1":
            await bot.send_msg(id,msg_type,[MessageList.CustomMusic(url=musicNameAndUrl.pop(), audio=musicNameAndUrl.pop(),title=musicTitle)])# 普通点歌 /music 1 title Url
        case "2":
            await bot.send_msg(id,msg_type,[MessageList.CustomMusic(url=musicNameAndUrl[len(musicNameAndUrl)-2], audio=musicNameAndUrl.pop(),title=musicTitle)])# 普通点歌 /music 2 title OpenUrl AudioUrl
        case "search":
            cont = req.request("get",wyyyyAPI + " ".join(musicNameAndUrl[1:])).json()
            #cont = json.dumps(cont)
            #print(cont)
            global wyyyySearchList,wyyyySearch_Music_ID_List
            wyyyySearchList = []
            wyyyySearch_Music_ID_List = []
            countNum = 1
            for i in cont["result"]["songs"]:
                    artists = ""
                    for ii in i["artists"]:
                        artists += ii["name"]
                        artists += "/"
                    artists = artists[:-1]
                    wyyyySearchList.append(str(countNum) +"." + i["name"]+" - "+ artists)
                    wyyyySearch_Music_ID_List.append(i["id"])
                    countNum += 1
                    print(i["name"])
            await bot.send_msg(id,msg_type,[MessageList.text("\n".join(wyyyySearchList))])
            pass
        case "select":
            Ordinal = int(musicNameAndUrl[1])-1
            await bot.send_msg(id,msg_type,[MessageList.text("已为您点歌:"+wyyyySearchList[Ordinal])])
            await bot.send_msg(id,msg_type,[MessageList.Music("163",wyyyySearch_Music_ID_List[Ordinal])])
            pass

async def AIProc(bot: Bot, zhiling:str, id:str, msg_type: Message_Type, m: Event, api:str,model:str):
    chatText = zhiling.replace("/ai", "")
    sender_id = m.check().raw["sender"]["user_id"]# 发送者QQ号
    msg_id = m.check().raw["message_id"]# 消息ID
    # msg_list : list = []
    # if msg_type == Message_Type.group:
    #     msg_list.append(MessageList.At(sender_id))
    #     msg_list.append(MessageList.text(" "))
    # msg_list.append(MessageList.text("喵~"))
    # await bot.send_msg(id,msg_type,msg_list)
    def ai(text:str):
        text_AI = asyncio.run(AIAPI.chat(content=text,id=id,msg_type=msg_type,memory=True,api=api,model=model))
        msg_list = []
        msg_list.append(MessageList.reply(msg_id))
        if msg_type == Message_Type.group:
            msg_list.append(MessageList.At(sender_id))
            msg_list.append(MessageList.text("\n"))
        msg_list.append(MessageList.text(text_AI))
        asyncio.run(bot.send_msg(id,msg_type,msg_list))
    th = threading.Thread(target=ai,daemon=True,args=(chatText,))
    th.start()
    print("Thread Exit")
    # await bot.send_msg(id,msg_type,[MessageList.text(await AIollama.chat(chatText))])

# class HashPairKey:#用于区分不同群聊的结构体
#     def __init__(self):
#         self.id = ""
#         self.msg_type = Message_Type.group
#     def __init__(self,id:str,msg_type:Message_Type):
#         self.id = id
#         self.msg_type = msg_type

async def sendMsgProc(bot: Bot, zhiling:str, id:str,msg_type: Message_Type):
    text = zhiling.replace("/send_msg", "")
    text = text.strip()
    # /send_msg type id text
    z = text.split(" ")
    contents = " ".join(z[2:])
    if len(z) < 3:
        return
    if z[0] == "group":
        await bot.send_msg(z[1],Message_Type.group,[MessageList.text(contents)])
    elif z[0] == "private":
        await bot.send_msg(z[1],Message_Type.private,[MessageList.text(contents)])

async def sendPicProc(bot: Bot, zhiling:str, id:str,msg_type: Message_Type):
    text = zhiling.replace("/send_pic", "")
    text = text.strip()
    # /send_pic type id picUrl [picUrl] ...
    z = text.split(" ")
    if len(z) < 3:
        return
    # contents = " ".join(z[2:])
    imgUrls = z[2:]
    contents = []
    for i in imgUrls:
        contents.append(MessageList.image(i))
    if z[0] == "group":
        await bot.send_msg(z[1],Message_Type.group,contents)
    elif z[0] == "private":
        await bot.send_msg(z[1],Message_Type.private,contents)

calcMsg : dict = {
    str : int
}
maxMsgThenReply : dict = {
    str : int
}
aiModel : dict = {
    str : [str,str]
    #id : [ai api,ai model]
}
badword_count = {}  # 结构: {(group_id, user_id): [count, first_time]}
BADWORD_LIMIT = 3   # 1分钟内最多允许3次
BADWORD_PERIOD = 60 # 秒, 表示1分钟一次刷新计数

defaultModel = ["deepseek",""]
async def msgProc(bot: Bot, m: Event):
    print(m.check().raw)
    zhiling = m.check().get_msg()
    print("消息内容:",zhiling)
    zhiling = m.check().get_raw_msg()
    at = m.check().get_the_first_at_object_qq_number_str()
    id : str = ""
    msg_type : Message_Type
    self_id :str = str(m.check().raw["self_id"])
    sender_id = m.check().raw["sender"]["user_id"]# 发送者QQ号
    if m.check().raw["message_type"] == "private":
        id = m.check().raw["user_id"]
        msg_type = Message_Type.private
    elif m.check().raw["message_type"] == "group":
        id = m.check().raw["group_id"]
        msg_type = Message_Type.group
    id = str(id)
    memHashKey = id + ',' + msg_type.value

    global calcMsg,maxMsgThenReply,aiModel
    if memHashKey not in calcMsg.keys():
        calcMsg[memHashKey] = 0
    if memHashKey not in maxMsgThenReply.keys():
        maxMsgThenReply[memHashKey] = 0
    calcMsg[memHashKey] += 1 # 消息计数+1,当达到一定值将重置为0,并回复消息
    if maxMsgThenReply[memHashKey] == 0:
        maxMsgThenReply[memHashKey] = random.randint(30, 50)# [30,50]区间,是闭区间
        # maxMsgThenReply[memHashKey] = random.randint(10, 20)
    
    if memHashKey not in aiModel.keys():
        aiModel[memHashKey] = defaultModel

    print("calcMsg[memHashKey]:", calcMsg[memHashKey])
    print("maxMsgThenReply[memHashKey]:", maxMsgThenReply[memHashKey])
    print("aiModel[memHashKey]:", aiModel[memHashKey])

    match zhiling:
        case _ if msg_type == Message_Type.group: # 所有群聊消息检查
            msgText = zhiling.strip()

            # 智能禁言检测
            ban_duration = 60  # 禁言时长,单位秒
            key = (id, sender_id)
            now = time.time()
            if check_badwords(msgText):
                # 初始化或重置窗口
                if key not in badword_count or now - badword_count[key][1] > BADWORD_PERIOD:
                    badword_count[key] = [1, now, [msgText]]
                else:
                    badword_count[key][0] += 1
                    badword_count[key][2].append(msgText)
                # 判断是否超限
                if badword_count[key][0] >= BADWORD_LIMIT:
                    print(f"已禁言成员:{sender_id},1分钟内所有违规消息:{badword_count[key][2]}")
                    await bot.send_msg(id, msg_type,
                        [MessageList.At(sender_id), MessageList.text(
                            f"1分钟内多次违规,已禁言!禁言成员:{sender_id}" # \n违规内容:\n" + "\n".join(badword_count[key][2])
                        )]
                    )
                    await bot.set_group_ban(group_id=id, user_id=sender_id, duration=ban_duration)
                    badword_count[key] = [0, now, []]  # 重置计数和消息列表
                # else:
                #     await bot.send_msg(
                #         id, msg_type,
                #         [MessageList.text(f"检测到违规词,请注意言辞!({badword_count[key][0]}/{BADWORD_LIMIT})")]
                #     )

    match zhiling:
        case _ if msg_type == Message_Type.group and at != self_id:
            zhiling = m.check().get_msg()
            msgText = ""
            for msgJson in zhiling:
                if msgJson["type"] != "at":
                    find_it = True
                if msgJson["type"] == "text":
                    msgText += msgJson["data"]["text"]
                    #await bot.send_group_msg(id,[MessageList.text(msgText)])
                elif msgJson["type"] == "at":
                    msgText += "@" + msgJson["data"]["qq"]
                elif msgJson["type"] == "image":
                    pass
            msgText = msgText.strip()
            msgList = msgText.split()
            if msgList[0].lower() == "/changeai":
                if len(msgList) == 3:
                    model = [msgList[1],msgList[2]]
                elif len(msgList) == 2:
                    model = [msgList[1],""]
                else:
                    model = defaultModel
                aiModel[memHashKey] = model
                await bot.send_msg(id,msg_type,[MessageList.text("已切换AI模型")])
                
            if msgText != "" and calcMsg[memHashKey] > maxMsgThenReply[memHashKey]:
                print("calcMsg[memHashKey] > maxMsgThenReply[memHashKey]", calcMsg[memHashKey],">",maxMsgThenReply[memHashKey])
                calcMsg[memHashKey] = 0
                maxMsgThenReply[memHashKey] = 0

                def sendAIResponse():
                    AI_Response = []
                    AI_Response.append(MessageList.text(asyncio.run(AIAPI.chat(content=msgText,id=id,msg_type=msg_type,memory=False,api=aiModel[memHashKey][0],model=aiModel[memHashKey][1]))))
                    asyncio.run(bot.send_msg(id, msg_type, AI_Response))
                print("AI Intelligence Response Thread Start")
                threading.Thread(target=sendAIResponse,daemon=True).start()
                
        case _ if msg_type == Message_Type.private or (msg_type == Message_Type.group and at == self_id):
        # case _:
            zhiling = m.check().get_msg()
            find_it = False
            msgText = ""
            for msgJson in zhiling:
                if msgJson["type"] != "at":
                    find_it = True
                if msgJson["type"] == "text":
                    msgText += msgJson["data"]["text"]
                    #await bot.send_group_msg(id,[MessageList.text(msgText)])
                elif msgJson["type"] == "at":
                    if msgJson["data"]["qq"] != self_id:
                        msgText += "@" + msgJson["data"]["qq"]
                elif msgJson["type"] == "image":
                    pass
                    # msgText += msgJson["data"]["file"]
            if find_it == False:
                await bot.send_msg(id,msg_type,[MessageList.text("你干嘛!?")])
            else:
                zhiling = msgText.strip()
                z = zhiling.lower()
                match zhiling:
                    case _ if "/echo" in zhiling and zhiling[:5] == "/echo":
                        await echoProc(bot, m, id, msg_type)
                    case "/bing":
                        await bingProc(bot, zhiling, id, msg_type)
                    case "/dev":
                        await bot.send_msg(id,msg_type,[MessageList.text("调试信息:\n" + str(m.check().raw))])
                    case "/random":
                        await bot.send_msg(id,msg_type,[MessageList.image("https://moe.jitsu.top/img/")])
                    case "/help":
                        await bot.send_msg(id,msg_type,[MessageList.text("/bing——必应每日一图\n/dev——发送调试信息\n/random——随机二次元\n/help——帮助\n/echo——重复话语\n/music——点歌(签证以停止服务,将无法发送音乐卡片)\n/ai——与AI对话\n/changeAI——切换AI模型\n/ShowCurrentAI——显示当前AI模型\n/ChangePrompt——修改提示词\n")])
                    case _ if "/music" in zhiling and zhiling[:6] == "/music":
                        await musicProc(bot, zhiling, id, msg_type)
                    case _ if "/changeai" in zhiling.lower() and zhiling[:9].lower() == "/changeai":
                        msgList = zhiling.split()
                        if msgList[0].lower() == "/changeai":
                            if len(msgList) == 3:
                                model = [msgList[1],msgList[2]]
                            elif len(msgList) == 2:
                                model = [msgList[1],""]
                            else:
                                model = defaultModel
                            aiModel[memHashKey] = model
                            await bot.send_msg(id,msg_type,[MessageList.text("已切换AI模型")])
                    case _ if "/showcurrentai" in zhiling.lower() and zhiling[:14].lower() == "/showcurrentai":
                        await bot.send_msg(id,msg_type,[MessageList.text("当前AI模型:\n" + aiModel[memHashKey][0] + "->" + (aiModel[memHashKey][1] if aiModel[memHashKey][1] != "" else "默认"))])
                    case _ if "/changeprompt" in zhiling.lower() and zhiling[:13].lower() == "/changeprompt":
                        await AIAPI.changePrompt(prompt=zhiling[14:],id=id,msg_type=msg_type)
                        await bot.send_msg(id,msg_type,[MessageList.text("提示词已修改,已清空当前聊天记录")])
                    case _ if "/send_msg" in zhiling.lower() and zhiling[:9].lower() == "/send_msg":
                        await sendMsgProc(bot, zhiling, id, msg_type)
                    case _ if "/send_pic" in zhiling.lower() and zhiling[:9].lower() == "/send_pic":
                        await sendPicProc(bot, zhiling, id, msg_type)
                    # case _:
                    case _ if "/ai" in zhiling and zhiling[:3] == "/ai":
                        await AIProc(bot, zhiling, id, msg_type, m,aiModel[memHashKey][0],aiModel[memHashKey][1])


下面是接入本地ollama服务的代码

import ollama
import json
from ollama import AsyncClient
#client = ollama.Client(host="localhost:11434")
client = AsyncClient(host="http://localhost:11434")


ChatCount=0
messages = []

async def chat(content:str) -> str:
    global ChatCount,messages
    
    message = {
        'role': 'user',
        'content': content
    }
    messages.append(message)
    msg_to_send = json.dumps(messages)
    response = await client.chat(model='qwen2:7b',messages=messages,stream=False)
    message = {
      "role": "assistant",
      "content": response["message"]["content"]
    }
    messages.append(message)
    ChatCount += 1
    if(ChatCount > 10):
        messages = []
    return response["message"]["content"]

然后是发送AI回复的处理函数

# Please install OpenAI SDK first: `pip3 install openai`

import os# 获取模块文件路径
from openai import OpenAI,AsyncOpenAI
import asyncio
import json
from enum import Enum
from bot import Message_Type
messages : dict = {str : list}

# 定义一个异步函数chat,用于与AI进行对话
# DeepSeek的model有"deepseek-chat"和"deepseek-reasoner"
# kimi的model有moonshot-v1-8k moonshot-v1-32k moonshot-v1-128k moonshot-v1-8k-vision-preview moonshot-v1-32k-vision-preview moonshot-v1-128k-vision-preview,后者昂贵
async def chat(content:str, id:str="all", msg_type:Message_Type=Message_Type.group, memory:bool=True, api:str="deepseek", model:str="deepseek-chat", prompt:str="") -> str:
    model = model.strip()
    hashKey = id + ',' + msg_type.value
    apis = {}
    with open(os.path.join(os.path.dirname(__file__),"ai_apis.json"), "r", encoding="utf-8") as api_file:
        apis = json.load(api_file)
    if api not in apis.keys() and model == "":
        raise Exception(f"API {api} not found")
    # if model not in apis[api]["models"]:
    #     raise Exception(f"Model {model} not found in API {api}")
    if model == "":
        model = apis[api]["models"][0]
        
    # 创建一个AsyncOpenAI客户端
    client = AsyncOpenAI(api_key=apis[api]["key"], base_url=apis[api]["url"])
    # 定义一个全局变量messages,用于存储对话历史
    global messages
    # 定义一个字典message,用于存储用户发送的消息
    message = {
        'role': 'user',
        'content': content
    }
    # 定义一个空字符串response,用于存储AI的回复
    response = ''
    try:
        # 打印正在获取AI回复
        print("getting AI response")
        # 如果group_id不在messages的键中,则将group_id添加到messages的键中,并将对应的值设为一个空列表
        if hashKey not in messages.keys():
            if prompt == "":
                with open(os.path.join(os.path.dirname(__file__),"AIPrompt.txt"), "r", encoding="utf-8") as prompt_file:
                    prompt = prompt_file.read()
                messages[hashKey] = [# 此处可用于存放提示词
                    {
                        "role": "system",
                        # "content": "请你扮演一个刚从美国留学回国的人,说话时候会故意中文夹杂部分英文单词,显得非常fancy,对话中总是带有很强的优越感。"
                        "content": prompt
                    },
                ]
            else:
                messages[hashKey] = []
        # 将message添加到messages[hashKey]中
        send_messages = messages[hashKey] + [message]
        # 调用client.chat.completions.create方法,获取AI的回复
        response = await client.chat.completions.with_raw_response.create(
            model=model,
            messages=send_messages,
            stream=False,
            n=1# 下文choices中元素的个数
        )
        # 打印获取到的AI回复
        print("Succeeded gotten AI response")
        if response.status_code != 200 or response.text == '':
            raise Exception(f"DeepSeek API response status code: {response.status_code}, response: {response.text if response.text != '' else '(null)'}")
        responseJson = json.loads(response.text)
        print("AI Response:"+responseJson["choices"][0]["message"]["content"])
        # 如果memory为True,则将message和AI的回复添加到messages[hashKey]中
        if memory:
            messages[hashKey].append(message)
            messages[hashKey].append(responseJson["choices"][0]["message"])
        # 关闭client
        await client.close()
        # 返回AI的回复
        return responseJson["choices"][0]["message"]["content"]
    except Exception as e:
        # 如果发生异常,则打印异常信息
        import traceback,sys
        # tb = traceback.extract_tb(sys.exc_info()[2])
        print(sys.exc_info())
        # 关闭client
        await client.close()
        # 返回异常信息和API的返回信息
        # return str(sys.exc_info()) + '\nException contents: ' + str(e) + "\nHttp Response: " + str(response)
        return ''


async def changePrompt(prompt:str, id:str="all", msg_type:Message_Type=Message_Type.group):
    global messages
    hashKey = id + ',' + msg_type.value
    messages[hashKey] = [
        {
            "role": "system",
            "content": prompt
        },
    ]
if __name__ == "__main__":
    # path = os.path.dirname(__file__) + "\\"
    # with open(path + "AIPrompt2.txt", "r", encoding="utf-8") as prompt_file:
    #     content = prompt_file.read()
    #     print(content)
    async def main():
        print(await chat("写一个正则表达式,要求匹配一个字符串中包含另一个字符串(b),且b前面没有b的第一个字符,若有,则b前面的该字符前必须有该字符"))
    asyncio.run(main())

其中,AIAPI.py使用到的ai_apis.json格式如下

{
    "localhost":{
        "name": "localhost",
        "url": "http://localhost:11434",
        "key": "",
        "models": [
            "wangshenzhi/gemma2-9b-chinese-chat:latest",
            "qwen3:8b",
            "qwen2:7b"
        ]
    },
    "kimi":{
        "name": "kimi",
        "url": "https://api.moonshot.cn/v1",
        "key": "",
        "models": [
            "moonshot-v1-8k",
            "moonshot-v1-32k",
            "moonshot-v1-128k",
            "moonshot-v1-8k-vision-preview",
            "moonshot-v1-32k-vision-preview",
            "moonshot-v1-128k-vision-preview"
        ]
    },
    "deepseek":{
        "name": "deepseek",
        "url": "https://api.deepseek.com",
        "key": "",
        "models": [
            "deepseek-chat",
            "deepseek-reasoner"
        ]
    }
}
posted @ 2025-09-26 19:59  lyxyz5223  阅读(21)  评论(0)    收藏  举报
//代码块美化————行号