fix: prevent AI coach chat replies from truncating mid-sentence

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
dekun
2026-06-11 00:44:08 +08:00
parent 0e2e360ccf
commit 6169fee7b9
5 changed files with 221 additions and 36 deletions
+4
View File
@@ -85,6 +85,10 @@ HUB_TRUST_LAN=true
# 与四实例相同变量名;默认 OpenAI 兼容网关(改 AI_PROVIDER=ollama 可走本机 Ollama
# 详见 manual_trading_hub/AI教练说明.md 与仓库根 AI复盘与模型配置说明.md
AI_TIMEOUT_SECONDS=120
# AI 教练聊天:单次输出 token 上限与截断自动续写次数(默认 8192 / 3)
# CHAT_MAX_OUTPUT_TOKENS=8192
# CHAT_MAX_CONTINUATIONS=3
# CHAT_AI_TIMEOUT_SECONDS=300
# AI 提供方:openai(默认,OpenAI 兼容网关)| ollama(本机 Ollama
AI_PROVIDER=openai
+2
View File
@@ -7,6 +7,7 @@ from hub_ai.attachments import parse_chat_attachments
from hub_ai.client import generate_text, model_label
from hub_ai.config import (
CHAT_CONTEXT_MAX_CHARS,
CHAT_MAX_CONTINUATIONS,
CHAT_MAX_HISTORY_TURNS,
CHAT_MAX_OUTPUT_TOKENS,
CHAT_SUMMARY_EXCERPT_MAX_CHARS,
@@ -107,6 +108,7 @@ def send_chat_message(
temperature=CHAT_TEMPERATURE,
images_b64=parsed.get("images_b64") or None,
max_tokens=CHAT_MAX_OUTPUT_TOKENS,
max_continuations=CHAT_MAX_CONTINUATIONS,
)
if reply.startswith("AI 调用失败"):
return {"ok": False, "msg": reply, "session_id": sid}
+11 -2
View File
@@ -9,7 +9,7 @@ _REPO_ROOT = Path(__file__).resolve().parents[2]
if str(_REPO_ROOT) not in sys.path:
sys.path.insert(0, str(_REPO_ROOT))
from ai_client import ai_generate, ai_provider_label # noqa: E402
from ai_client import ai_generate, ai_generate_chat, ai_provider_label # noqa: E402
def model_label() -> str:
@@ -23,11 +23,20 @@ def generate_text(
temperature: float,
images_b64: Optional[Sequence[str]] = None,
max_tokens: int | None = None,
max_continuations: int = 3,
) -> str:
if max_tokens is not None and max_tokens > 0:
return ai_generate_chat(
system=system,
user=user,
temperature=temperature,
images_b64=images_b64,
max_tokens=int(max_tokens),
max_continuations=max_continuations,
)
prompt = f"{system.strip()}\n\n---\n\n{user.strip()}"
return ai_generate(
prompt,
temperature=temperature,
images_b64=images_b64,
max_tokens=max_tokens,
)
+10 -1
View File
@@ -5,10 +5,19 @@ import os
HUB_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
def _int_env(key: str, default: int) -> int:
try:
return int(os.getenv(key, str(default)) or default)
except ValueError:
return default
SUMMARY_TEMPERATURE = 0.15
CHAT_TEMPERATURE = 0.5
CHAT_MAX_HISTORY_TURNS = 40
CHAT_MAX_OUTPUT_TOKENS = 2048
CHAT_MAX_OUTPUT_TOKENS = _int_env("CHAT_MAX_OUTPUT_TOKENS", 8192)
CHAT_MAX_CONTINUATIONS = _int_env("CHAT_MAX_CONTINUATIONS", 3)
CHAT_CONTEXT_MAX_CHARS = 128_000
CHAT_SUMMARY_EXCERPT_MAX_CHARS = 8000
SUMMARY_RETENTION_DAYS = 90