fix: prevent AI coach chat replies from truncating mid-sentence
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -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,
|
||||
)
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user