feat: optimize document and model usage

This commit is contained in:
saboteur7
2026-02-03 02:58:15 +08:00
parent a7b99cde4e
commit 501866d12a
16 changed files with 514 additions and 404 deletions

View File

@@ -3,6 +3,7 @@ import time
import web
import json
import uuid
import io
from queue import Queue, Empty
from bridge.context import *
from bridge.reply import Reply, ReplyType
@@ -197,46 +198,50 @@ class WebChannel(ChatChannel):
def startup(self):
port = conf().get("web_port", 9899)
logger.info("""[WebChannel] 当前channel为web可修改 config.json 配置文件中的 channel_type 字段进行切换。全部可用类型为:
1. web: 网页
2. terminal: 终端
3. feishu: 飞书
4. dingtalk: 钉钉
5. wechatcom_app: 企微自建应用
6. wechatmp: 个人公众号
7. wechatmp_service: 企业公众号""")
logger.info(f"Web对话网页已运行, 请使用浏览器访问 http://localhost:{port}/chat (本地运行) 或 http://ip:{port}/chat (服务器运行)")
# 打印可用渠道类型提示
logger.info("[WebChannel] 当前channel为web可修改 config.json 配置文件中的 channel_type 字段进行切换。全部可用类型为:")
logger.info("[WebChannel] 1. web - 网页")
logger.info("[WebChannel] 2. terminal - 终端")
logger.info("[WebChannel] 3. feishu - 飞书")
logger.info("[WebChannel] 4. dingtalk - 钉钉")
logger.info("[WebChannel] 5. wechatcom_app - 企微自建应用")
logger.info("[WebChannel] 6. wechatmp - 个人公众号")
logger.info("[WebChannel] 7. wechatmp_service - 企业公众号")
logger.info(f"[WebChannel] 🌐 本地访问: http://localhost:{port}/chat")
logger.info(f"[WebChannel] 🌍 服务器访问: http://YOUR_IP:{port}/chat (请将YOUR_IP替换为服务器IP)")
logger.info("[WebChannel] ✅ Web对话网页已运行")
# 确保静态文件目录存在
static_dir = os.path.join(os.path.dirname(__file__), 'static')
if not os.path.exists(static_dir):
os.makedirs(static_dir)
logger.info(f"Created static directory: {static_dir}")
logger.debug(f"[WebChannel] Created static directory: {static_dir}")
urls = (
'/', 'RootHandler', # 添加根路径处理器
'/', 'RootHandler',
'/message', 'MessageHandler',
'/poll', 'PollHandler', # 添加轮询处理器
'/poll', 'PollHandler',
'/chat', 'ChatHandler',
'/config', 'ConfigHandler', # 添加配置处理器
'/assets/(.*)', 'AssetsHandler', # 匹配 /assets/任何路径
'/config', 'ConfigHandler',
'/assets/(.*)', 'AssetsHandler',
)
app = web.application(urls, globals(), autoreload=False)
# 完全禁用web.py的HTTP日志输出
# 创建一个空的日志处理函数
def null_log_function(status, environ):
pass
# 替换web.py的日志函数
web.httpserver.LogMiddleware.log = lambda self, status, environ: None
# 配置web.py的日志级别为ERROR
logging.getLogger("web").setLevel(logging.ERROR)
logging.getLogger("web.httpserver").setLevel(logging.ERROR)
# 启动服务器
web.httpserver.runsimple(app.wsgifunc(), ("0.0.0.0", port))
# 抑制 web.py 默认的服务器启动消息
old_stdout = sys.stdout
sys.stdout = io.StringIO()
try:
web.httpserver.runsimple(app.wsgifunc(), ("0.0.0.0", port))
finally:
sys.stdout = old_stdout
class RootHandler:

View File

@@ -1,6 +1,7 @@
# -*- coding=utf-8 -*-
import io
import os
import sys
import time
import requests
@@ -35,9 +36,8 @@ class WechatComAppChannel(ChatChannel):
self.agent_id = conf().get("wechatcomapp_agent_id")
self.token = conf().get("wechatcomapp_token")
self.aes_key = conf().get("wechatcomapp_aes_key")
print(self.corp_id, self.secret, self.agent_id, self.token, self.aes_key)
logger.info(
"[wechatcom] init: corp_id: {}, secret: {}, agent_id: {}, token: {}, aes_key: {}".format(self.corp_id, self.secret, self.agent_id, self.token, self.aes_key)
"[wechatcom] Initializing WeCom app channel, corp_id: {}, agent_id: {}".format(self.corp_id, self.agent_id)
)
self.crypto = WeChatCrypto(self.token, self.aes_key, self.corp_id)
self.client = WechatComAppClient(self.corp_id, self.secret)
@@ -47,7 +47,17 @@ class WechatComAppChannel(ChatChannel):
urls = ("/wxcomapp/?", "channel.wechatcom.wechatcomapp_channel.Query")
app = web.application(urls, globals(), autoreload=False)
port = conf().get("wechatcomapp_port", 9898)
web.httpserver.runsimple(app.wsgifunc(), ("0.0.0.0", port))
logger.info("[wechatcom] ✅ WeCom app channel started successfully")
logger.info("[wechatcom] 📡 Listening on http://0.0.0.0:{}/wxcomapp/".format(port))
logger.info("[wechatcom] 🤖 Ready to receive messages")
# Suppress web.py's default server startup message
old_stdout = sys.stdout
sys.stdout = io.StringIO()
try:
web.httpserver.runsimple(app.wsgifunc(), ("0.0.0.0", port))
finally:
sys.stdout = old_stdout
def send(self, reply: Reply, context: Context):
receiver = context["receiver"]
@@ -74,6 +84,10 @@ class WechatComAppChannel(ChatChannel):
response = self.client.media.upload("voice", open(path, "rb"))
logger.debug("[wechatcom] upload voice response: {}".format(response))
media_ids.append(response["media_id"])
except ImportError as e:
logger.error("[wechatcom] voice conversion failed: {}".format(e))
logger.error("[wechatcom] please install pydub: pip install pydub")
return
except WeChatClientException as e:
logger.error("[wechatcom] upload voice failed: {}".format(e))
return

View File

@@ -21,7 +21,11 @@ from common.log import logger
from common.singleton import singleton
from common.utils import split_string_by_utf8_length, remove_markdown_symbol
from config import conf
from voice.audio_convert import any_to_mp3, split_audio
try:
from voice.audio_convert import any_to_mp3, split_audio
except ImportError as e:
logger.debug("import voice.audio_convert failed, voice features will not be supported: {}".format(e))
# If using SSL, uncomment the following lines, and modify the certificate path.
# from cheroot.server import HTTPServer
@@ -85,26 +89,31 @@ class WechatMPChannel(ChatChannel):
logger.info("[wechatmp] text cached, receiver {}\n{}".format(receiver, reply_text))
self.cache_dict[receiver].append(("text", reply_text))
elif reply.type == ReplyType.VOICE:
voice_file_path = reply.content
duration, files = split_audio(voice_file_path, 60 * 1000)
if len(files) > 1:
logger.info("[wechatmp] voice too long {}s > 60s , split into {} parts".format(duration / 1000.0, len(files)))
try:
voice_file_path = reply.content
duration, files = split_audio(voice_file_path, 60 * 1000)
if len(files) > 1:
logger.info("[wechatmp] voice too long {}s > 60s , split into {} parts".format(duration / 1000.0, len(files)))
for path in files:
# support: <2M, <60s, mp3/wma/wav/amr
try:
with open(path, "rb") as f:
response = self.client.material.add("voice", f)
logger.debug("[wechatmp] upload voice response: {}".format(response))
f_size = os.fstat(f.fileno()).st_size
time.sleep(1.0 + 2 * f_size / 1024 / 1024)
# todo check media_id
except WeChatClientException as e:
logger.error("[wechatmp] upload voice failed: {}".format(e))
return
media_id = response["media_id"]
logger.info("[wechatmp] voice uploaded, receiver {}, media_id {}".format(receiver, media_id))
self.cache_dict[receiver].append(("voice", media_id))
for path in files:
# support: <2M, <60s, mp3/wma/wav/amr
try:
with open(path, "rb") as f:
response = self.client.material.add("voice", f)
logger.debug("[wechatmp] upload voice response: {}".format(response))
f_size = os.fstat(f.fileno()).st_size
time.sleep(1.0 + 2 * f_size / 1024 / 1024)
# todo check media_id
except WeChatClientException as e:
logger.error("[wechatmp] upload voice failed: {}".format(e))
return
media_id = response["media_id"]
logger.info("[wechatmp] voice uploaded, receiver {}, media_id {}".format(receiver, media_id))
self.cache_dict[receiver].append(("voice", media_id))
except ImportError as e:
logger.error("[wechatmp] voice conversion failed: {}".format(e))
logger.error("[wechatmp] please install pydub: pip install pydub")
return
elif reply.type == ReplyType.IMAGE_URL: # 从网络下载图片
img_url = reply.content
@@ -213,6 +222,10 @@ class WechatMPChannel(ChatChannel):
logger.debug("[wechatcom] upload voice response: {}".format(response))
media_ids.append(response["media_id"])
os.remove(path)
except ImportError as e:
logger.error("[wechatmp] voice conversion failed: {}".format(e))
logger.error("[wechatmp] please install pydub: pip install pydub")
return
except WeChatClientException as e:
logger.error("[wechatmp] upload voice failed: {}".format(e))
return