"""Deterministic payload assembly for decoded creation knowledge.""" from __future__ import annotations import json from typing import Any from decode_content.contracts import DIM_ATTRIBUTE_BY_TYPE TYPE2ATTR = DIM_ATTRIBUTE_BY_TYPE def _post_value(post: Any, key: str, default: Any = "") -> Any: if isinstance(post, dict): return post.get(key, default) return getattr(post, key, default) def build_content(knowledge: dict[str, Any]) -> str | dict[str, Any]: t = knowledge.get("type") if t == "how": lines = [f"目标:{knowledge.get('purpose', '')}"] for idx, step in enumerate(knowledge.get("steps", []), 1): intent = step.get("intent") or step.get("purpose") or "" label = f"步骤{idx}" + (f"(目的:{intent})" if intent else "") lines.extend( [ label, f" 输入:{step.get('input', '')}", f" 指引:{step.get('directive', '')}", f" 产出:{step.get('output', '')}", ] ) return "\n".join(lines) if t == "what": return { "name": knowledge.get("title") or "", "kind": knowledge.get("kind"), "维度拆分规则": knowledge.get("维度拆分规则") if knowledge.get("kind") == "子集" else None, "body": [ { "item_name": item.get("item_name", ""), "item_desc": item.get("item_desc", ""), "作用域": item.get("作用域") or [], } for item in (knowledge.get("body") or []) ], } return knowledge.get("阐述") or knowledge.get("desc") or "" def _payload_content(knowledge: dict[str, Any]) -> str: content = build_content(knowledge) return content if isinstance(content, str) else json.dumps(content, ensure_ascii=False) def _add_scopes(scopes: list[dict[str, str]], seen: set[tuple[str, str]], items: list[dict[str, Any]]) -> None: for item in items: scope_type = item.get("scope_type") value = item.get("value") if not (scope_type and value): continue key = (scope_type, value) if key in seen: continue seen.add(key) scopes.append({"scope_type": scope_type, "value": value}) def collect_payload_scopes(knowledge: dict[str, Any]) -> list[dict[str, str]]: scopes: list[dict[str, str]] = [] seen: set[tuple[str, str]] = set() if knowledge.get("type") == "how": for step in knowledge.get("steps", []): _add_scopes(scopes, seen, step.get("作用域", [])) else: _add_scopes(scopes, seen, knowledge.get("作用域", [])) return scopes def build_payload(post: Any, knowledge: dict[str, Any], how_titles: dict[str, str] | None = None) -> dict[str, Any]: how_titles = how_titles or {} t = knowledge.get("type") ext = [ {"key": "业务阶段", "type": "str", "value": stage} for stage in (knowledge.get("业务阶段") or []) ] if t == "what" and knowledge.get("概要"): ext.append({"key": "概要", "type": "str", "value": knowledge["概要"]}) if t == "how": creation_stages: list[str] = [] seen_stages: set[str] = set() for step in knowledge.get("steps", []): stage = step.get("创作阶段") if stage and stage not in seen_stages: seen_stages.add(stage) creation_stages.append(stage) ext.extend({"key": "创作阶段", "type": "str", "value": stage} for stage in creation_stages) ext.extend( {"key": "动作", "type": "str", "value": step["动作"]} for step in knowledge.get("steps", []) if step.get("动作") ) if knowledge.get("role") == "组件" and knowledge.get("parent"): parent = knowledge["parent"] ext.append( { "key": "出自", "type": "str", "value": f"{how_titles.get(parent.get('how_id'), parent.get('how_id'))} 第{parent.get('step')}步", } ) return { "source": { "id": _post_value(post, "id"), "source_type": "post", "title": _post_value(post, "title") or "", "author": _post_value(post, "author_name") or "", "source_metadata": { "platform": _post_value(post, "platform"), "url": _post_value(post, "url"), }, }, "title": knowledge.get("title"), "content": _payload_content(knowledge), "dim_creations": ["创作"], "dim_attributes": [TYPE2ATTR.get(t, "how工序")], "scopes": collect_payload_scopes(knowledge), "custom_ext": ext, } def build_payloads(post: Any, knowledges: list[dict[str, Any]]) -> list[dict[str, Any]]: how_titles = {k.get("id"): k.get("title") for k in knowledges if k.get("type") == "how"} return [build_payload(post, knowledge, how_titles) for knowledge in knowledges]