"""拆分:把帖子拆成一个或多个 What/Why/How 知识片段。""" from __future__ import annotations from typing import Optional from creation_knowledge.integrations.llm import ChatFn, default_chat from creation_knowledge.models import ExtractedContent, KnowledgeItem, Post from creation_knowledge.prompts import load_prompt from creation_knowledge.stages._common import content_for_llm, norm_text, norm_types SYSTEM = "你是严谨的创作知识拆分器,原文有什么提什么,绝不编造。" def _to_item(raw: dict) -> Optional[KnowledgeItem]: what = norm_text(raw.get("what")) why = norm_text(raw.get("why")) how = norm_text(raw.get("how")) # knowledge_types 以非空字段为准(模型给的若不一致,用实际有内容的对齐) types = norm_types(raw.get("knowledge_types")) actual = [t for t, v in (("what", what), ("why", why), ("how", how)) if v] types = [t for t in types if t in actual] or actual if not types: return None # 三个都空,丢弃 title = norm_text(raw.get("title")) or (what or why or how or "")[:20] evidence = [e for e in (raw.get("evidence") or []) if norm_text(e)] return KnowledgeItem( title=title, knowledge_types=types, what=what, why=why, how=how, evidence=[str(e).strip() for e in evidence], ) def split_post( post: Post, content: ExtractedContent, *, chat: Optional[ChatFn] = None, env_file: str = ".env", ) -> list[KnowledgeItem]: chat = chat or default_chat(env_file) user = load_prompt("split").format( title=post.title or "(无)", topics="、".join(post.topic_list) or "(无)", content=content_for_llm(post, content) or "(空)", ) data = chat(SYSTEM, user) items = [_to_item(raw) for raw in (data.get("items") or [])] return [it for it in items if it is not None]