Initial commit: WeChat bot project with AI chat, video export, and image upload scripts

This commit is contained in:
anqiang12
2026-06-18 15:53:24 +08:00
commit 3b1e106cb0
16 changed files with 2541 additions and 0 deletions

232
chat_bot.py Normal file
View 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()