Files
life-echo/api/app/features/evaluation/candidate_runner.py

84 lines
2.9 KiB
Python
Raw Normal View History

"""独立候选回放:多轮 user 链式调用 LLM不走路由 WS / ChatOrchestrator。"""
from __future__ import annotations
import time
from typing import Any
from app.core.logging import get_logger
logger = get_logger(__name__)
def _system_prompt_for_eval(version_config: dict | None) -> str:
cfg = version_config or {}
extra = (cfg.get("system_prompt_suffix") or "").strip()
base = """你是「岁月留书」老年友好访谈员。语气温暖、耐心,先承接情绪再 gently 追问事实与感受;回答简洁分段,避免术语。"""
if extra:
return f"{base}\n\n{extra}"
return base
def _model_override(version_config: dict | None) -> str | None:
if not version_config:
return None
m = version_config.get("model")
return str(m).strip() if m else None
class EvalCandidateRunner:
"""使用 LangChain Chat 模型回放用户轮次。"""
def __init__(self, llm: Any) -> None:
self._llm = llm
async def replay_utterances(
self,
utterances: list[str],
*,
version_config: dict | None = None,
temperature: float = 0.7,
) -> tuple[list[str], list[int]]:
"""返回每轮 assistant 回复与耗时 ms。"""
if not self._llm:
raise RuntimeError(" replay: llm 未配置")
from langchain_core.messages import AIMessage, HumanMessage, SystemMessage
sys_prompt = _system_prompt_for_eval(version_config)
model = _model_override(version_config)
lc_messages: list = [SystemMessage(content=sys_prompt)]
replies: list[str] = []
latencies: list[int] = []
bound = (
self._llm.bind(model=model, temperature=temperature)
if model
else self._llm.bind(temperature=temperature)
)
for u in utterances:
text = (u or "").strip()
if not text:
continue
lc_messages.append(HumanMessage(content=text))
t0 = time.perf_counter()
result = await bound.ainvoke(lc_messages)
elapsed_ms = int((time.perf_counter() - t0) * 1000)
reply = str(getattr(result, "content", "") or "").strip()
replies.append(reply)
latencies.append(elapsed_ms)
lc_messages.append(AIMessage(content=reply))
return replies, latencies
def simple_memoir_from_transcript(utterances: list[str], replies: list[str]) -> str:
"""轻量成稿:供评审用占位(非生产叙事管线)。"""
lines = ["# 访谈摘录整理(评测占位稿)", ""]
for i, u in enumerate(utterances):
lines.append(f"## 片段 {i + 1}")
lines.append("")
lines.append(f"**用户:** {u.strip()}")
if i < len(replies):
lines.append("")
lines.append(f"**访谈者:** {replies[i].strip()}")
lines.append("")
return "\n".join(lines)