|
|
@@ -13,6 +13,37 @@ logger = logging.getLogger(__name__)
|
|
|
_ALLOWED_TEMPLATE_TYPES = frozenset({"info", "analysis", "metric", "judgment"})
|
|
|
|
|
|
|
|
|
+def _merge_dict(target: dict, patch: dict) -> dict:
|
|
|
+ for k, v in patch.items():
|
|
|
+ if isinstance(v, dict) and isinstance(target.get(k), dict):
|
|
|
+ target[k] = _merge_dict(dict(target[k]), v)
|
|
|
+ else:
|
|
|
+ target[k] = v
|
|
|
+ return target
|
|
|
+
|
|
|
+
|
|
|
+def _build_effective_request(req: SectionRequest) -> SectionRequest:
|
|
|
+ # 统一数据口径:最终 data_package 以自动结果与人工补录文本为主,
|
|
|
+ # 若上游已完成 RAG/整理并放入 data_package,则在此并入作为最终素材。
|
|
|
+ final_data = _merge_dict({}, dict(req.auto_data_package))
|
|
|
+ if req.manual_supplement_text.strip():
|
|
|
+ final_data["manual_supplement_text"] = req.manual_supplement_text.strip()
|
|
|
+ if req.data_package:
|
|
|
+ final_data = _merge_dict(final_data, dict(req.data_package))
|
|
|
+
|
|
|
+ # 红色字段来自顶层 template,不再单独由请求顶层 paragraph_* / example / notes 传入
|
|
|
+ template = req.template if isinstance(req.template, dict) else {}
|
|
|
+ return req.model_copy(
|
|
|
+ update={
|
|
|
+ "paragraph_position": str(template.get("paragraph_position", "")).strip(),
|
|
|
+ "paragraph_logic": str(template.get("paragraph_logic", "")).strip(),
|
|
|
+ "example": str(template.get("example", "")).strip(),
|
|
|
+ "notes": str(template.get("notes", "")).strip(),
|
|
|
+ "data_package": final_data,
|
|
|
+ }
|
|
|
+ )
|
|
|
+
|
|
|
+
|
|
|
def _stub_section(req: SectionRequest) -> SectionResponse:
|
|
|
text = (
|
|
|
f"【占位正文】knowledge_unit_id={req.knowledge_unit_id} "
|
|
|
@@ -29,41 +60,9 @@ async def run_section(
|
|
|
llm: LlmClient,
|
|
|
rag: RagService | None = None,
|
|
|
) -> SectionResponse:
|
|
|
+ effective = _build_effective_request(req)
|
|
|
if settings.stub_skills:
|
|
|
- return _stub_section(req)
|
|
|
-
|
|
|
- effective = req
|
|
|
- if req.rag_recall:
|
|
|
- if not req.task_id:
|
|
|
- raise ValueError("rag_recall=true 时必须提供 task_id")
|
|
|
- if rag is None:
|
|
|
- raise ValueError("RagService 未注入,无法执行召回")
|
|
|
- if not (settings.embedding_api_key or settings.llm_api_key):
|
|
|
- raise ValueError("RAG 召回需配置 FINREP_EMBEDDING_API_KEY 或 FINREP_LLM_API_KEY")
|
|
|
- q = (req.rag_query or "").strip()
|
|
|
- if not q:
|
|
|
- q = "\n".join(
|
|
|
- s
|
|
|
- for s in (
|
|
|
- (req.paragraph_position or "").strip(),
|
|
|
- (req.paragraph_logic or "").strip(),
|
|
|
- f"knowledge_unit_id:{req.knowledge_unit_id}",
|
|
|
- )
|
|
|
- if s
|
|
|
- )
|
|
|
- recall = await rag.retrieve(
|
|
|
- req.task_id,
|
|
|
- q,
|
|
|
- top_k=req.rag_top_k,
|
|
|
- min_score=req.rag_min_score,
|
|
|
- )
|
|
|
- dp = dict(req.data_package)
|
|
|
- dp["rag_recall"] = {
|
|
|
- "query": q,
|
|
|
- "hits": [h.model_dump() for h in recall.hits],
|
|
|
- "formatted_context": recall.formatted_context,
|
|
|
- }
|
|
|
- effective = req.model_copy(update={"data_package": dp})
|
|
|
+ return _stub_section(effective)
|
|
|
|
|
|
tt = (effective.template_type or "info").lower()
|
|
|
if tt not in _ALLOWED_TEMPLATE_TYPES:
|