Files
AutoControlCourse/chatbot.py

84 lines
3.7 KiB
Python

import json
import aiohttp
import config
async def chat_with_ai(message: str, history: list):
"""
与 AI 模型进行流式对话。
"""
system_prompt = """你是一位精通自动控制原理的专家教授。请用清晰、准确、专业的中文来回答有关自动控制课程内容的问题。
重要规则:
1. 当需要表达数学公式时,必须使用 LaTeX 格式
2. 行内公式使用 $公式$ 或 \\(公式\\)
3. 独立公式使用 $$公式$$ 或 \\[公式\\]
4. 例如:传递函数可以写成 $G(s) = \\frac{K}{s(s+1)}$
5. 二阶系统标准形式:$$G(s) = \\frac{\\omega_n^2}{s^2 + 2\\zeta\\omega_n s + \\omega_n^2}$$
请在适当的时候使用公式和示例来辅助解释。"""
if not config.API_KEY or config.API_KEY.strip() == "":
history.append({"role": "assistant", "content": "❌ 错误:API_KEY 未配置。请在 config.py 文件中配置 API_KEY。"})
yield history
return
history.append({"role": "user", "content": message})
# 添加临时的 "正在思考" 消息
history.append({"role": "assistant", "content": "正在思考..."})
yield history
bot_response = ""
try:
if config.API_TYPE == "deepseek":
api_url = f"{config.API_BASE_URL}/chat/completions"
messages_for_api = [{"role": "system", "content": system_prompt}] + history[:-1]
payload = {
"model": config.API_MODEL,
"messages": messages_for_api,
"stream": True, "temperature": 0.7, "max_tokens": 2048
}
headers = {
"Content-Type": "application/json",
"Authorization": f"Bearer {config.API_KEY}"
}
async with aiohttp.ClientSession() as session:
async with session.post(api_url, json=payload, headers=headers, timeout=aiohttp.ClientTimeout(total=60)) as response:
if response.status == 200:
async for line in response.content:
line = line.decode('utf-8').strip()
if not line or line == "data: [DONE]": continue
if line.startswith("data: "): line = line[6:]
try:
data = json.loads(line)
if "choices" in data and len(data["choices"]) > 0:
delta = data["choices"][0].get("delta", {})
content = delta.get("content", "")
if content:
bot_response += content
history[-1]["content"] = bot_response
yield history
except json.JSONDecodeError:
pass
if not bot_response:
history[-1]["content"] = "⚠️ API 返回了空响应,请稍后重试。"
yield history
else:
error_text = await response.text()
history[-1]["content"] = f"❌ API请求出错 (状态码: {response.status}):\n{error_text}"
yield history
else:
history[-1]["content"] = f"❌ 不支持的 API 类型: {config.API_TYPE}"
yield history
except aiohttp.ClientError as e:
history[-1]["content"] = f"❌ 网络连接错误: {e}"
yield history
except Exception as e:
history[-1]["content"] = f"❌ 发生错误: {type(e).__name__}: {e}"
yield history