Initial commit: stock analysis backend and prototype UI.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
42
backend/llm.py
Normal file
42
backend/llm.py
Normal file
@@ -0,0 +1,42 @@
|
||||
"""大模型客户端(OpenAI 兼容接口)。
|
||||
|
||||
未配置 LLM_API_KEY 时 enabled() 返回 False,调用方应走规则降级。
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import requests
|
||||
|
||||
import config
|
||||
|
||||
|
||||
def enabled() -> bool:
|
||||
return bool(config.LLM_API_KEY)
|
||||
|
||||
|
||||
def chat(messages, temperature: float = 0.5, max_tokens: int = 900) -> str:
|
||||
"""调用 chat/completions。失败抛异常,由上层捕获降级。"""
|
||||
if not enabled():
|
||||
raise RuntimeError("LLM 未配置")
|
||||
url = config.LLM_BASE_URL.rstrip("/") + "/chat/completions"
|
||||
headers = {"Authorization": f"Bearer {config.LLM_API_KEY}", "Content-Type": "application/json"}
|
||||
payload = {"model": config.LLM_MODEL, "messages": messages,
|
||||
"temperature": temperature, "max_tokens": max_tokens, "stream": False}
|
||||
r = requests.post(url, json=payload, headers=headers, timeout=config.LLM_TIMEOUT)
|
||||
r.raise_for_status()
|
||||
data = r.json()
|
||||
return data["choices"][0]["message"]["content"].strip()
|
||||
|
||||
|
||||
SYSTEM_PROMPT = (
|
||||
"你是一名专业的A股市场分析师,擅长复盘、个股诊断与题材分析。"
|
||||
"你的结论必须严格基于用户提供的结构化数据,不臆造未提供的数字。"
|
||||
"语言简洁专业,使用中文。涉及操作建议时必须同时给出风险提示,"
|
||||
"并说明这不构成投资建议。"
|
||||
)
|
||||
|
||||
|
||||
def ask(user_content: str, temperature: float = 0.5, max_tokens: int = 900) -> str:
|
||||
return chat([
|
||||
{"role": "system", "content": SYSTEM_PROMPT},
|
||||
{"role": "user", "content": user_content},
|
||||
], temperature=temperature, max_tokens=max_tokens)
|
||||
Reference in New Issue
Block a user