This commit is contained in:
ttt
2026-04-14 14:58:14 +08:00
parent 8b5b24fa2a
commit 4a53be7eeb
3 changed files with 382 additions and 1515 deletions

View File

@@ -1,6 +1,13 @@
""" """
FastAPI 应用主入口 FastAPI 应用主入口
""" """
# ========== 压制 MongoDB 疯狂刷屏日志 ==========
import logging
logging.getLogger("pymongo").setLevel(logging.WARNING)
logging.getLogger("pymongo.topology").setLevel(logging.WARNING)
logging.getLogger("urllib3").setLevel(logging.WARNING)
# ==============================================
import logging import logging
import logging.handlers import logging.handlers
import sys import sys

View File

@@ -42,41 +42,86 @@ class LLMService:
"Content-Type": "application/json" "Content-Type": "application/json"
} }
# DeepSeek API temperature 范围: (0, 2]
if temperature < 0.01:
temperature = 0.01
elif temperature > 2.0:
temperature = 2.0
payload = { payload = {
"model": self.model_name, "model": self.model_name,
"messages": messages, "messages": messages,
"temperature": temperature "temperature": temperature
} }
# DeepSeek API 限制 max_tokens 范围
if max_tokens: if max_tokens:
if max_tokens > 8192:
max_tokens = 8192
payload["max_tokens"] = max_tokens payload["max_tokens"] = max_tokens
# 移除不兼容的参数
for key in ["stream", "stop", "presence_penalty", "frequency_penalty", "logit_bias"]:
kwargs.pop(key, None)
# 添加其他参数 # 添加其他参数
payload.update(kwargs) payload.update(kwargs)
try: # 验证消息格式
logger.info(f"LLM API 请求: model={self.model_name}, temperature={temperature}, max_tokens={max_tokens}") validated_messages = []
logger.info(f"消息数量: {len(messages)}")
for i, msg in enumerate(messages): for i, msg in enumerate(messages):
logger.info(f"消息[{i}]: role={msg.get('role')}, content长度={len(msg.get('content', ''))}") role = msg.get("role", "")
content = msg.get("content", "")
async with httpx.AsyncClient(timeout=60.0) as client: # 确保 content 是字符串
if not isinstance(content, str):
logger.warning(f"消息[{i}] content 不是字符串类型: {type(content)},转换为字符串")
content = str(content)
# 确保 role 有效
if role not in ["system", "user", "assistant"]:
logger.warning(f"消息[{i}] role 无效: {role},跳过")
continue
validated_messages.append({"role": role, "content": content})
payload["messages"] = validated_messages
logger.info(f"验证后消息数量: {len(validated_messages)}")
try:
logger.info(f"LLM API 请求: model={self.model_name}, base_url={self.base_url}, temperature={temperature}, max_tokens={max_tokens}")
logger.info(f"消息数量: {len(messages)}")
total_content_len = sum(len(msg.get('content', '')) for msg in messages)
logger.info(f"总内容长度: {total_content_len}")
async with httpx.AsyncClient(timeout=120.0) as client:
response = await client.post( response = await client.post(
f"{self.base_url}/chat/completions", f"{self.base_url}/chat/completions",
headers=headers, headers=headers,
json=payload json=payload
) )
logger.info(f"LLM API 响应状态: {response.status_code}") logger.info(f"LLM API 响应状态: {response.status_code}")
if response.status_code != 200: if response.status_code != 200:
logger.error(f"LLM API 响应内容: {response.text}") error_text = response.text
logger.error(f"LLM API 错误响应: {error_text}")
# 尝试解析错误详情
try:
error_json = response.json()
error_msg = error_json.get("error", {}).get("message", error_text)
logger.error(f"错误详情: {error_msg}")
except:
pass
response.raise_for_status() response.raise_for_status()
return response.json() return response.json()
except httpx.HTTPStatusError as e: except httpx.HTTPStatusError as e:
logger.error(f"LLM API 请求失败: {e.response.status_code} - {e.response.text}") logger.error(f"LLM API HTTP 错误: {e.response.status_code} - {e.response.text}")
raise raise
except Exception as e: except Exception as e:
logger.error(f"LLM API 调用异常: {str(e)}") logger.error(f"LLM API 调用异常: {str(e)}", exc_info=True)
raise raise
def extract_message_content(self, response: Dict[str, Any]) -> str: def extract_message_content(self, response: Dict[str, Any]) -> str:
@@ -119,6 +164,10 @@ class LLMService:
"Content-Type": "application/json" "Content-Type": "application/json"
} }
# DeepSeek API 限制
if max_tokens and max_tokens > 8192:
max_tokens = 8192
payload = { payload = {
"model": self.model_name, "model": self.model_name,
"messages": messages, "messages": messages,
@@ -129,9 +178,14 @@ class LLMService:
if max_tokens: if max_tokens:
payload["max_tokens"] = max_tokens payload["max_tokens"] = max_tokens
# 移除不兼容的参数
for key in ["stop", "presence_penalty", "frequency_penalty", "logit_bias"]:
kwargs.pop(key, None)
payload.update(kwargs) payload.update(kwargs)
try: try:
logger.info(f"LLM 流式 API 请求: model={self.model_name}, max_tokens={max_tokens}")
async with httpx.AsyncClient(timeout=120.0) as client: async with httpx.AsyncClient(timeout=120.0) as client:
async with client.stream( async with client.stream(
"POST", "POST",
@@ -139,9 +193,14 @@ class LLMService:
headers=headers, headers=headers,
json=payload json=payload
) as response: ) as response:
if response.status_code != 200:
error_text = await response.aread()
logger.error(f"LLM 流式 API 错误: {response.status_code} - {error_text}")
response.raise_for_status()
async for line in response.aiter_lines(): async for line in response.aiter_lines():
if line.startswith("data: "): if line.startswith("data: "):
data = line[6:] # Remove "data: " prefix data = line[6:]
if data == "[DONE]": if data == "[DONE]":
break break
try: try:
@@ -157,7 +216,7 @@ class LLMService:
logger.error(f"LLM 流式 API 请求失败: {e.response.status_code}") logger.error(f"LLM 流式 API 请求失败: {e.response.status_code}")
raise raise
except Exception as e: except Exception as e:
logger.error(f"LLM 流式 API 调用异常: {str(e)}") logger.error(f"LLM 流式 API 调用异常: {str(e)}", exc_info=True)
raise raise
async def analyze_excel_data( async def analyze_excel_data(

File diff suppressed because it is too large Load Diff