Przeglądaj źródła

提示词:拆分四类来源专用 Retrieval 角色

用 Pattern 统计关系、Decode 可追溯案例、External 外部事实、Knowledge 方法规则四份独立 Prompt 替换泛化 Retrieval;同步 preset、Prompt manifest、公开常量和质量合同测试。
SamLee 18 godzin temu
rodzic
commit
daa61a9a9d

+ 26 - 13
script_build_host/src/script_build_host/agents/presets.py

@@ -8,13 +8,16 @@ from agent.core.presets import register_preset
 from .prompts import (
     COMPARISON_WORKER_PROMPT,
     COMPOSE_WORKER_PROMPT,
+    DECODE_RETRIEVAL_WORKER_PROMPT,
     DIRECTION_WORKER_PROMPT,
     ELEMENT_SET_WORKER_PROMPT,
+    EXTERNAL_RETRIEVAL_WORKER_PROMPT,
+    KNOWLEDGE_RETRIEVAL_WORKER_PROMPT,
     PARAGRAPH_WORKER_PROMPT,
+    PATTERN_RETRIEVAL_WORKER_PROMPT,
     PLANNER_PROMPT,
     PORTFOLIO_WORKER_PROMPT,
     RETRIEVAL_VALIDATOR_PROMPT,
-    RETRIEVAL_WORKER_PROMPT,
     ROOT_VALIDATOR_PROMPT,
     ROOT_WORKER_PROMPT,
     SCRIPT_CANDIDATE_VALIDATOR_PROMPT,
@@ -41,7 +44,7 @@ _FORBIDDEN = [
 ]
 
 
-def _worker(tools: list[str], *, prompt: str = RETRIEVAL_WORKER_PROMPT) -> AgentPreset:
+def _worker(tools: list[str], *, prompt: str) -> AgentPreset:
     return AgentPreset(
         role=AgentRole.WORKER,
         allowed_tools=list(dict.fromkeys([*tools, "submit_attempt"])),
@@ -87,19 +90,31 @@ def register_script_presets() -> None:
     )
     register_preset(
         "script_pattern_retrieval_worker",
-        _worker(["read_input_snapshot", "query_pattern_qa"]),
+        _worker(
+            ["read_input_snapshot", "query_pattern_qa"],
+            prompt=PATTERN_RETRIEVAL_WORKER_PROMPT,
+        ),
     )
     register_preset(
         "script_decode_retrieval_worker",
-        _worker(["read_input_snapshot", "search_script_decode_case"]),
+        _worker(
+            ["read_input_snapshot", "search_script_decode_case"],
+            prompt=DECODE_RETRIEVAL_WORKER_PROMPT,
+        ),
     )
     register_preset(
         "script_external_retrieval_worker",
-        _worker(["read_input_snapshot", "external_search_case", "load_images"]),
+        _worker(
+            ["read_input_snapshot", "external_search_case", "load_images"],
+            prompt=EXTERNAL_RETRIEVAL_WORKER_PROMPT,
+        ),
     )
     register_preset(
         "script_knowledge_retrieval_worker",
-        _worker(["read_input_snapshot", "search_knowledge"]),
+        _worker(
+            ["read_input_snapshot", "search_knowledge"],
+            prompt=KNOWLEDGE_RETRIEVAL_WORKER_PROMPT,
+        ),
     )
     register_preset(
         "script_direction_worker",
@@ -108,12 +123,13 @@ def register_script_presets() -> None:
             prompt=DIRECTION_WORKER_PROMPT,
         ),
     )
+    structure_writes = [
+        "read_attempt_workspace",
+        "create_script_paragraphs",
+    ]
     paragraph_writes = [
         "read_attempt_workspace",
-        "create_script_paragraph",
         "create_script_paragraphs",
-        "append_paragraph_atoms",
-        "delete_paragraph_atom",
         "batch_update_script_paragraphs",
     ]
     element_writes = [
@@ -132,7 +148,7 @@ def register_script_presets() -> None:
     register_preset(
         "script_structure_worker",
         _worker(
-            [*common_candidate_reads, *paragraph_writes],
+            [*common_candidate_reads, *structure_writes],
             prompt=STRUCTURE_WORKER_PROMPT,
         ),
     )
@@ -161,10 +177,7 @@ def register_script_presets() -> None:
         "script_compose_worker",
         _worker(
             [
-                "read_input_snapshot",
                 "read_active_frontier",
-                *paragraph_writes,
-                *element_writes,
                 "save_structured_script_candidate",
             ],
             prompt=COMPOSE_WORKER_PROMPT,

+ 8 - 2
script_build_host/src/script_build_host/agents/prompts/__init__.py

@@ -3,13 +3,16 @@
 from .contracts import (
     COMPARISON_WORKER_PROMPT,
     COMPOSE_WORKER_PROMPT,
+    DECODE_RETRIEVAL_WORKER_PROMPT,
     DIRECTION_WORKER_PROMPT,
     ELEMENT_SET_WORKER_PROMPT,
+    EXTERNAL_RETRIEVAL_WORKER_PROMPT,
+    KNOWLEDGE_RETRIEVAL_WORKER_PROMPT,
     PARAGRAPH_WORKER_PROMPT,
+    PATTERN_RETRIEVAL_WORKER_PROMPT,
     PLANNER_PROMPT,
     PORTFOLIO_WORKER_PROMPT,
     RETRIEVAL_VALIDATOR_PROMPT,
-    RETRIEVAL_WORKER_PROMPT,
     ROOT_VALIDATOR_PROMPT,
     ROOT_WORKER_PROMPT,
     SCRIPT_CANDIDATE_VALIDATOR_PROMPT,
@@ -22,13 +25,16 @@ from .contracts import (
 __all__ = [
     "COMPARISON_WORKER_PROMPT",
     "COMPOSE_WORKER_PROMPT",
+    "DECODE_RETRIEVAL_WORKER_PROMPT",
     "DIRECTION_WORKER_PROMPT",
     "ELEMENT_SET_WORKER_PROMPT",
+    "EXTERNAL_RETRIEVAL_WORKER_PROMPT",
+    "KNOWLEDGE_RETRIEVAL_WORKER_PROMPT",
     "PARAGRAPH_WORKER_PROMPT",
+    "PATTERN_RETRIEVAL_WORKER_PROMPT",
     "PLANNER_PROMPT",
     "PORTFOLIO_WORKER_PROMPT",
     "RETRIEVAL_VALIDATOR_PROMPT",
-    "RETRIEVAL_WORKER_PROMPT",
     "ROOT_VALIDATOR_PROMPT",
     "ROOT_WORKER_PROMPT",
     "SCRIPT_CANDIDATE_VALIDATOR_PROMPT",

+ 12 - 9
script_build_host/src/script_build_host/agents/prompts/contracts.py

@@ -15,7 +15,10 @@ def _read(filename: str) -> str:
 
 
 PLANNER_PROMPT = _read("script_planner.md")
-RETRIEVAL_WORKER_PROMPT = _read("retrieval_worker.md")
+PATTERN_RETRIEVAL_WORKER_PROMPT = _read("pattern_retrieval_worker.md")
+DECODE_RETRIEVAL_WORKER_PROMPT = _read("decode_retrieval_worker.md")
+EXTERNAL_RETRIEVAL_WORKER_PROMPT = _read("external_retrieval_worker.md")
+KNOWLEDGE_RETRIEVAL_WORKER_PROMPT = _read("knowledge_retrieval_worker.md")
 DIRECTION_WORKER_PROMPT = _read("direction_worker.md")
 RETRIEVAL_VALIDATOR_PROMPT = _read("retrieval_validator.md")
 SCRIPT_CANDIDATE_VALIDATOR_PROMPT = _read("candidate_validator.md")
@@ -42,26 +45,26 @@ def script_build_prompt_manifest() -> tuple[dict[str, object], ...]:
         ),
         "script_pattern_retrieval_worker": (
             "worker",
-            "retrieval_worker.md",
-            RETRIEVAL_WORKER_PROMPT,
+            "pattern_retrieval_worker.md",
+            PATTERN_RETRIEVAL_WORKER_PROMPT,
             1,
         ),
         "script_decode_retrieval_worker": (
             "worker",
-            "retrieval_worker.md",
-            RETRIEVAL_WORKER_PROMPT,
+            "decode_retrieval_worker.md",
+            DECODE_RETRIEVAL_WORKER_PROMPT,
             1,
         ),
         "script_external_retrieval_worker": (
             "worker",
-            "retrieval_worker.md",
-            RETRIEVAL_WORKER_PROMPT,
+            "external_retrieval_worker.md",
+            EXTERNAL_RETRIEVAL_WORKER_PROMPT,
             1,
         ),
         "script_knowledge_retrieval_worker": (
             "worker",
-            "retrieval_worker.md",
-            RETRIEVAL_WORKER_PROMPT,
+            "knowledge_retrieval_worker.md",
+            KNOWLEDGE_RETRIEVAL_WORKER_PROMPT,
             1,
         ),
         "script_retrieval_validator": (

+ 11 - 0
script_build_host/src/script_build_host/agents/prompts/decode_retrieval_worker.md

@@ -0,0 +1,11 @@
+你只执行一个 Decode Case Retrieval TaskSpec。先读冻结输入,再且仅再调用一次
+`search_script_decode_case`;一次查询必须覆盖本 Task 的全部验收标准。成功后 Host 会冻结
+EvidenceRecordV1、提交 Attempt 并立即终止 Worker,不要自行调用 `submit_attempt`。
+
+根据真实缺口选择 `return_field`:主脉络用于结构参考,元素用于人物、物件、动作和场景,
+主题/形式/作用/感受用于相应写法参考。keyword 只能来自冻结输入和 Task objective;只有
+账号专属任务才传 account_name。案例是可追溯参考,不是可照抄模板:保留来源定位与原意,
+不要把多个案例拼成虚构案例,也不要在检索 Worker 内起草正文。
+
+不得第二次查询、分页、扩展或验证;没有命中可以是诚实结果。不要创建 Task、文件、命令、
+数据库查询或任意网络请求。

+ 10 - 0
script_build_host/src/script_build_host/agents/prompts/external_retrieval_worker.md

@@ -0,0 +1,10 @@
+你只执行一个 External Retrieval TaskSpec。先读冻结输入,再且仅再调用一次
+`external_search_case`;一次 keyword 必须覆盖本 Task 的全部验收标准。成功后 Host 会冻结
+EvidenceRecordV1、提交 Attempt 并立即终止 Worker,不要自行调用 `submit_attempt`。
+
+优先检索能补足脚本的信息:可核验事实、真实案例、受众语言、平台表达和必要的视觉线索。
+保留原始来源、平台标识和上下文,明确区分事实、来源观点和你的归纳,不把搜索摘要当事实,
+不虚构数字、人物或出处。外部案例用于证据和启发,不在本 Worker 中直接生成脚本文案。
+
+本角色的成功检索会立即结束 Attempt,因此不要再调用 `load_images`,也不得二次查询、分页、
+扩展或验证。没有命中可以是诚实结果。不要创建 Task、文件、命令、数据库查询或任意网络请求。

+ 10 - 0
script_build_host/src/script_build_host/agents/prompts/knowledge_retrieval_worker.md

@@ -0,0 +1,10 @@
+你只执行一个 Knowledge Retrieval TaskSpec。先读冻结输入,再且仅再调用一次
+`search_knowledge`;一次 keyword 必须覆盖本 Task 的全部验收标准。成功后 Host 会冻结
+EvidenceRecordV1、提交 Attempt 并立即终止 Worker,不要自行调用 `submit_attempt`。
+
+检索创作方法、领域规则、评估标准或可执行步骤,用来回答“应该怎样做、为什么这样做”。
+保留知识条目的适用条件、限制和来源;不要把通用方法冒充当前主题事实,不要虚构示例,
+也不要在检索 Worker 内起草脚本文案。
+
+不得第二次查询、分页、扩展或验证;没有命中可以是诚实结果。不要创建 Task、文件、命令、
+数据库查询或任意网络请求。

+ 10 - 0
script_build_host/src/script_build_host/agents/prompts/pattern_retrieval_worker.md

@@ -0,0 +1,10 @@
+你只执行一个 Pattern Retrieval TaskSpec。先读冻结输入,再且仅再调用一次
+`query_pattern_qa`;一次 message 必须覆盖本 Task 的全部验收标准。成功后 Host 会冻结
+EvidenceRecordV1、提交 Attempt 并立即终止 Worker,不要自行调用 `submit_attempt`。
+
+查询重点是可复核的模式与关系:共同出现的创作特征、支持度、置信度、提升度、样本数和
+代表实例。按 Task scope 区分账号内模式与跨账号模式,不把相关性写成因果,不改写网关
+返回的统计含义。检索结果只为后续 Direction 或创作提供证据,不直接起草脚本。
+
+不得第二次查询、分页、扩展或验证,不得伪造 Pattern;没有命中可以是诚实结果。不要创建
+Task、文件、命令、数据库查询或任意网络请求。

+ 0 - 10
script_build_host/src/script_build_host/agents/prompts/retrieval_worker.md

@@ -1,10 +0,0 @@
-Execute exactly one retrieval TaskSpec. Read only the frozen input and call the
-single retrieval capability exposed by this preset. Freeze the normalized
-EvidenceRecordV1 returned by the gateway. The Host submits the Attempt and
-terminates the Worker immediately after that successful call. Do not call
-`submit_attempt` yourself. Do not create tasks, agents, files, shell
-commands, database queries, or arbitrary network requests.
-
-Call the retrieval capability exactly once per Attempt. One query must request
-all evidence needed by the Task criteria. Never call retrieval again to
-broaden, refine, paginate, or verify the result.

+ 99 - 0
script_build_host/tests/test_prompt_quality.py

@@ -0,0 +1,99 @@
+from __future__ import annotations
+
+from agent import get_preset
+
+from script_build_host.agents.presets import register_script_presets
+from script_build_host.agents.prompts import (
+    COMPARISON_WORKER_PROMPT,
+    COMPOSE_WORKER_PROMPT,
+    DECODE_RETRIEVAL_WORKER_PROMPT,
+    DIRECTION_WORKER_PROMPT,
+    ELEMENT_SET_WORKER_PROMPT,
+    EXTERNAL_RETRIEVAL_WORKER_PROMPT,
+    KNOWLEDGE_RETRIEVAL_WORKER_PROMPT,
+    PARAGRAPH_WORKER_PROMPT,
+    PATTERN_RETRIEVAL_WORKER_PROMPT,
+    PLANNER_PROMPT,
+    ROOT_VALIDATOR_PROMPT,
+    SCRIPT_CANDIDATE_VALIDATOR_PROMPT,
+    STRUCTURE_WORKER_PROMPT,
+    script_build_prompt_manifest,
+)
+
+
+def test_retrieval_roles_freeze_distinct_source_specific_prompts() -> None:
+    retrieval_presets = {
+        "script_pattern_retrieval_worker": (
+            "pattern_retrieval_worker.md",
+            PATTERN_RETRIEVAL_WORKER_PROMPT,
+            "query_pattern_qa",
+        ),
+        "script_decode_retrieval_worker": (
+            "decode_retrieval_worker.md",
+            DECODE_RETRIEVAL_WORKER_PROMPT,
+            "search_script_decode_case",
+        ),
+        "script_external_retrieval_worker": (
+            "external_retrieval_worker.md",
+            EXTERNAL_RETRIEVAL_WORKER_PROMPT,
+            "external_search_case",
+        ),
+        "script_knowledge_retrieval_worker": (
+            "knowledge_retrieval_worker.md",
+            KNOWLEDGE_RETRIEVAL_WORKER_PROMPT,
+            "search_knowledge",
+        ),
+    }
+    manifest = {str(item["preset"]): item for item in script_build_prompt_manifest()}
+
+    assert len({content for _, content, _ in retrieval_presets.values()}) == 4
+    for preset, (filename, content, tool_name) in retrieval_presets.items():
+        assert manifest[preset]["source_id"] == filename
+        assert manifest[preset]["content"] == content
+        assert tool_name in content
+        assert "且仅再调用一次" in content
+
+
+def test_registered_retrieval_presets_use_their_own_prompt() -> None:
+    register_script_presets()
+    expected = {
+        "script_pattern_retrieval_worker": PATTERN_RETRIEVAL_WORKER_PROMPT,
+        "script_decode_retrieval_worker": DECODE_RETRIEVAL_WORKER_PROMPT,
+        "script_external_retrieval_worker": EXTERNAL_RETRIEVAL_WORKER_PROMPT,
+        "script_knowledge_retrieval_worker": KNOWLEDGE_RETRIEVAL_WORKER_PROMPT,
+    }
+    for preset, prompt in expected.items():
+        assert get_preset(preset).system_prompt == prompt
+
+
+def test_creative_prompts_preserve_quality_and_convergence_contracts() -> None:
+    assert "前期可探索不同的真实路径" in PLANNER_PROMPT
+    assert "一个最主要的缺陷簇" in PLANNER_PROMPT
+    assert "受众可感知结果" in DIRECTION_WORKER_PROMPT
+    assert "不预写 Phase 2" in DIRECTION_WORKER_PROMPT
+    assert "段落方案" in DIRECTION_WORKER_PROMPT
+    assert "不是完成的正文" in STRUCTURE_WORKER_PROMPT
+    assert "不可随意互换" in STRUCTURE_WORKER_PROMPT
+    assert "受众最终能直接看到" in PARAGRAPH_WORKER_PROMPT
+    assert "不是提纲、创作说明" in PARAGRAPH_WORKER_PROMPT
+    assert "只是抽象评价" in ELEMENT_SET_WORKER_PROMPT
+    assert "先按完全相同的 criteria 独立评价" in COMPARISON_WORKER_PROMPT
+    assert "不在 Compose 阶段补写或润色" in COMPOSE_WORKER_PROMPT
+
+
+def test_validator_prompts_require_audience_visible_semantic_evidence() -> None:
+    dimensions = (
+        "D1 Goal 实现",
+        "D2 具体可执行",
+        "D3 结构叙事",
+        "D4 元素一致",
+        "D5 主题与 persona",
+        "D6 信息与事实",
+    )
+    for dimension in dimensions:
+        assert dimension in SCRIPT_CANDIDATE_VALIDATOR_PROMPT
+    assert "标签、自述和 Artifact URI 本身都不能证明内容质量" in (
+        SCRIPT_CANDIDATE_VALIDATOR_PROMPT
+    )
+    assert "真实受众的阅读顺序" in ROOT_VALIDATOR_PROMPT
+    assert "空 evidence、空正文、零独立 Element 或零 Link" in ROOT_VALIDATOR_PROMPT