M2b:导入改造产出可审阅灵胚(启镜物化世谱)与组装管线(符文展开/火候进入 IR),Kernel 打通采样参数链路

This commit is contained in:
chenxin committed 2026-08-21 23:43:29 +08:00
1 parent e6a3b7121f
commit 5f36e3785c
86 files changed
+424 -14455

No files matched your search

+66 -6
View File
@@ -383,25 +383,80 @@ def _citation_row(node_id: str, data: dict) -> Citation:
)
async def build_generation_prompt(question: TreeNode, instructions: str | None) -> str:
"""按祖先链组装投影 prompt(M2 形态:祖先路径 + 问题 + 临时指引;记忆/引文随 M3)。"""
async def build_generation_prompt(
question: TreeNode,
instructions: str | None,
*,
char_name: str | None = None,
user_name: str | None = None,
) -> str:
"""按祖先链组装投影 prompt 并做符文展开({{char}}/{{user}}/…)。
M2 形态:祖先路径 + 问题 + 临时指引;获准记忆与显式引文随 M3 息壤接入。
"""
from app.modules.macros.builtins import build_default_registry
from app.modules.macros.engine import render
from app.modules.macros.types import MacroContext
ctx = MacroContext(char_name=char_name, user_name=user_name)
registry = build_default_registry()
def expand(text: str) -> str:
return render(text, ctx, registry=registry)
chain = await ancestor_chain(question.id)
lines: list[str] = []
for n in chain:
if n.id == question.id:
continue
speaker = "用户" if n.node_type == "question" else "人物"
lines.append(f"{speaker}:{n.content}")
lines.append(f"{speaker}:{expand(n.content)}")
transcript = "\n".join(lines)
parts = []
if transcript:
parts.append(f"【共同经历(祖先路径)】\n{transcript}")
parts.append(f"【当前问题】\n{question.content}")
parts.append(f"【当前问题】\n{expand(question.content)}")
if instructions:
parts.append(f"【本次指引】\n{instructions}")
parts.append(f"【本次指引】\n{expand(instructions)}")
return "\n\n".join(parts)
async def _names_for_generation(tree: MirrorTree) -> tuple[str | None, str | None]:
"""人物名与执镜者名(符文上下文)。"""
from app.models.user import User
async with AsyncSessionLocal() as session:
character = await session.get(Character, tree.character_id)
char_name = character.name if character else None
user_name = None
if character is not None:
user = await session.get(User, character.owner_scope)
user_name = user.username if user else None
return char_name, user_name
async def _generation_overrides(owner_scope: str) -> dict:
"""火候(GenerationPreferences):本镜域默认采样参数 → IR 覆写。"""
from sqlalchemy import select
from app.models.governance import GenerationPreferences
async with AsyncSessionLocal() as session:
prefs = await session.get(GenerationPreferences, owner_scope)
if prefs is None:
# 兼容旧默认 owner_scope 行(历史数据)
prefs = (
await session.execute(
select(GenerationPreferences).where(
GenerationPreferences.owner_scope == owner_scope
)
)
).scalar_one_or_none()
if prefs is None:
return {}
return {"temperature": prefs.temperature, "max_tokens": prefs.max_output_tokens}
async def spawn_answer(
*,
question_id: str,
@@ -436,13 +491,18 @@ async def spawn_answer(
source="mirror_tree",
)
prompt = await build_generation_prompt(question, instructions)
char_name, user_name = await _names_for_generation(tree)
prompt = await build_generation_prompt(
question, instructions, char_name=char_name, user_name=user_name
)
overrides = await _generation_overrides(owner_scope)
run = await kernel.start_foreground_run(
character_id=tree.character_id,
prompt=prompt,
system_contract=None,
origin="tree_answer",
on_run_final=_make_finalize(tree.id, tree.character_id, node_id),
**overrides,
)
async with AsyncSessionLocal() as session:
node = await session.get(TreeNode, node_id)