Initial commit: WeChat bot project with AI chat, video export, and image upload scripts
This commit is contained in:
232
chat_bot.py
Normal file
232
chat_bot.py
Normal file
@@ -0,0 +1,232 @@
|
||||
import time
|
||||
from prompt_toolkit import prompt
|
||||
from openai import OpenAI
|
||||
from get_tianqi import get_tianqi_data
|
||||
from cha_xianglaing import search1
|
||||
from weixin import weix
|
||||
import json
|
||||
|
||||
tool_list = [
|
||||
{"name":"tainqi","description":"查询天气"},
|
||||
{"name":"sousuo","description":"网页搜索"},
|
||||
{"name":"export_video","description":"导出视频片段"},
|
||||
]
|
||||
|
||||
toole_details = {
|
||||
"tianqi":{
|
||||
"type":"function",
|
||||
"function":{
|
||||
"name":"tianqi",
|
||||
"description":"查询天气状况(温度、湿度、风力、天气....)时使用此tool",
|
||||
"strict": True,
|
||||
"parameters": {
|
||||
"type":"object",
|
||||
"properties":{
|
||||
"city":{"type": "string", "description": "要获取天气的城市名称"}
|
||||
},
|
||||
"required": ["city"],
|
||||
"additionalProperties": False
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
def get_tools_details():
|
||||
# 获取工具详情
|
||||
pass
|
||||
|
||||
|
||||
class send_message:
|
||||
def __init__(self, system_content: str ,tool_choice="auto"):
|
||||
self.ai_return = []
|
||||
self.tool_choice1 = tool_choice
|
||||
self.messages_1 = [
|
||||
{"role": "system", "content": system_content},
|
||||
]
|
||||
def test_openai(self):
|
||||
# print("111",self.messages_1)
|
||||
client = OpenAI(api_key="tp-cj0x379me5rqk198qnnt4n1spcdbx986jjr163gu2iiw1s7w",
|
||||
base_url="https://token-plan-cn.xiaomimimo.com/v1")
|
||||
response = client.chat.completions.create(
|
||||
model="mimo-v2.5-pro",
|
||||
messages=self.messages_1,
|
||||
top_p=0.5,
|
||||
tools=[
|
||||
{"type": "function",
|
||||
"function": {
|
||||
"name": "get_tianqi",
|
||||
"description": "获取天气信息。当你需要回答任何与天气、气温、冷暖有关的问题时调用此工具;判断用户是否是询问温度而不是出现冷热就调用此工具,例如用户说:你这个笑话好冷,则无需调用。**必须**使用此工具来获取实时、真实的天气数据。",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"city": {"type": "string", "description": "城市名称"}
|
||||
},
|
||||
"required": ["city"],
|
||||
"additionalProperties": False
|
||||
}
|
||||
}
|
||||
},{"type": "function",
|
||||
"function": {
|
||||
"name": "get_donghua_images",
|
||||
"description": "用户需要查询具体动画场景时调用此工具。例如:用户说这个场景不错帮我找下,调用此工具;",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"donghua": {"type": "string", "description": "动画场景描述,必须为英文;例如:Tom is tired"},
|
||||
"xiangsidu": {"type": "integer", "description": "图片与场景的相似度要求,例如:'给我相似度大于50%的图片 则传值0.5'"},
|
||||
"tupianshuliang": {"type": "integer", "description": "返回图片数量,例如:'给我返回10张图片 则传值10'"},
|
||||
},
|
||||
"required": ["donghua"],
|
||||
"additionalProperties": False
|
||||
}}
|
||||
},
|
||||
{"type": "function",
|
||||
"function": {
|
||||
"name": "export_video",
|
||||
"description": "当用户确认某张图片并要求导出视频时调用此工具。例如:'这张图不错,给我前后30秒的视频'、'导出这个场景后面5分钟'、'我要整个视频'、'帮我截取这个片段'",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"image_name": {
|
||||
"type": "string",
|
||||
"description": "用户确认的图片文件名,例如 '001 Puss Gets the Boot [1940]_05m23s_456.jpg'"
|
||||
},
|
||||
"mode": {
|
||||
"type": "string",
|
||||
"enum": ["around", "after", "before", "total"],
|
||||
"description": "导出模式:around=前后各N秒,after=后N秒,before=前N秒,total=整个视频"
|
||||
},
|
||||
"seconds": {
|
||||
"type": "integer",
|
||||
"description": "秒数,total模式下可省略,默认300秒。例如用户说'前后30秒'则传30,'前后5分钟'则传300",
|
||||
"default": 300
|
||||
}
|
||||
},
|
||||
"required": ["image_name", "mode","seconds"],
|
||||
"additionalProperties": False
|
||||
}}
|
||||
}
|
||||
],
|
||||
tool_choice=self.tool_choice1,
|
||||
)
|
||||
return response.choices[0].message
|
||||
|
||||
|
||||
def test_json_format(json_string):
|
||||
try:
|
||||
return json.loads(json_string)
|
||||
except json.JSONDecodeError:
|
||||
return False
|
||||
def get_tianqi(ai_json):
|
||||
print(f"正在获取{ai_json['city']}的天气信息...")
|
||||
return f"{get_tianqi_data(ai_json['city'])}"
|
||||
# m = send_message('')
|
||||
|
||||
|
||||
|
||||
cont = 1
|
||||
# m = send_message('你是一个个人助手,会适当使用工具')
|
||||
class get_ai_message:
|
||||
def __init__(self):
|
||||
self.system_content = open("猫和老鼠分镜.md", "r", encoding="utf-8").read()
|
||||
self.m = send_message(self.system_content)
|
||||
self.wx = weix()
|
||||
|
||||
async def _handle_donghua(self, args):
|
||||
"""处理动画图片搜索工具"""
|
||||
donghua = args["donghua"]
|
||||
xiangsidu = args.get("xiangsidu", 0)
|
||||
tupianshuliang = args.get("tupianshuliang", 5)
|
||||
re_donghua_image = search1(query_text=donghua, top_k=tupianshuliang)
|
||||
result_str = ""
|
||||
for result in re_donghua_image:
|
||||
if result.score < xiangsidu:
|
||||
continue
|
||||
result_str += f"相似度:{result.score},图片路径:{result.payload}\n"
|
||||
print(result)
|
||||
await self.wx.send_images(result.payload["image_path"])
|
||||
return result_str if result_str else "未找到符合条件的图片"
|
||||
|
||||
async def _handle_export_video(self, args):
|
||||
"""处理视频导出工具"""
|
||||
from video_cutter import export_video_clip
|
||||
export_result = export_video_clip(
|
||||
image_name=args["image_name"],
|
||||
mode=args["mode"],
|
||||
seconds=args.get("seconds", 300)
|
||||
)
|
||||
if export_result["success"]:
|
||||
await self.wx.send_video(export_result["video_path"])
|
||||
return (
|
||||
f"✅ 视频已导出并发送!\n"
|
||||
f"⏱️ 时间范围:{export_result['start_time']} -> {export_result['end_time']}\n"
|
||||
f"🎬 时长:{export_result['duration']}"
|
||||
)
|
||||
else:
|
||||
return f"❌ 视频导出失败:{export_result['error']}"
|
||||
|
||||
async def sen_mess(self, s_input_text):
|
||||
# 拼接用户消息
|
||||
self.m.messages_1.append({"role": "user", "content": s_input_text})
|
||||
|
||||
while True:
|
||||
out_text = self.m.test_openai()
|
||||
|
||||
if out_text.tool_calls:
|
||||
# 将 assistant 的 tool_calls 消息整体追加到 messages(转为 dict)
|
||||
self.m.messages_1.append({
|
||||
"role": "assistant",
|
||||
"content": out_text.content,
|
||||
"tool_calls": [
|
||||
{
|
||||
"id": tc.id,
|
||||
"type": "function",
|
||||
"function": {
|
||||
"name": tc.function.name,
|
||||
"arguments": tc.function.arguments
|
||||
}
|
||||
}
|
||||
for tc in out_text.tool_calls
|
||||
]
|
||||
})
|
||||
|
||||
for tool_call in out_text.tool_calls:
|
||||
args = test_json_format(tool_call.function.arguments)
|
||||
tool_name = tool_call.function.name
|
||||
print("M调用了工具:", tool_name)
|
||||
|
||||
tool_result = ""
|
||||
if tool_name == "get_tianqi":
|
||||
tool_result = get_tianqi(args)
|
||||
elif tool_name == "get_donghua_images":
|
||||
tool_result = await self._handle_donghua(args)
|
||||
elif tool_name == "export_video":
|
||||
tool_result = await self._handle_export_video(args)
|
||||
|
||||
# 工具结果以 tool role 追加到 messages
|
||||
self.m.messages_1.append({
|
||||
"role": "tool",
|
||||
"tool_call_id": tool_call.id,
|
||||
"content": tool_result
|
||||
})
|
||||
print(f"工具 {tool_name} 返回: {tool_result[:100]}...")
|
||||
|
||||
# 循环继续,让 LLM 看到工具结果后继续推理
|
||||
|
||||
elif out_text.content:
|
||||
# 没有工具调用,发送最终文本给用户
|
||||
self.m.messages_1.append({"role": "assistant", "content": out_text.content})
|
||||
await self.wx.send_text(out_text.content)
|
||||
print(f"小爱:{out_text.content}")
|
||||
return out_text.content
|
||||
|
||||
gm = get_ai_message()
|
||||
bot = gm.wx.bot
|
||||
@bot.on_message
|
||||
async def echo_handler(msg):
|
||||
print(f"收到来自 {msg.user_id} 的消息: {msg.text}")
|
||||
await gm.sen_mess(msg.text)
|
||||
# await bot.reply(msg, f"你说了: {msg.text}")
|
||||
bot.run()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user