feat: TenantSource 抽象——File源(测试/档案)与DB源(生产),registry 数据源可切换+reload upsert
Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
@@ -47,6 +47,11 @@ def _format_deflection_pool(deflections) -> str:
|
||||
)
|
||||
|
||||
|
||||
# 四件套键名(单一事实源): PromptProvider 构造校验 / FileTenantSource 读盘
|
||||
# / DbTenantSource 快照组形态, 三处消费同一清单
|
||||
PROMPTS_KEYS = ("system", "company_facts", "extractor", "evaluator")
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class PromptProvider:
|
||||
"""租户提示词四件套持有者(Task 6, R1 话术单一事实源)。
|
||||
@@ -54,9 +59,12 @@ class PromptProvider:
|
||||
frozen(Task 9 收口, Task 6 审查遗留): 实例跨租户运行时/模块级
|
||||
DEFAULT_PROVIDER 共享, 不可变防共享单例被毒化。
|
||||
|
||||
- from_dir(dir): 读 system/company_facts/extractor/evaluator 四个 md,
|
||||
存实例字段——提示词属于租户(seed_profiles/<slug>/prompts/),不再有
|
||||
代码级 app/engine/prompts 副本;
|
||||
- from_dir(dir): 读 system/company_facts/extractor/evaluator 四个 md
|
||||
委托 from_config——提示词属于租户(seed_profiles/<slug>/prompts/),
|
||||
不再有代码级 app/engine/prompts 副本;
|
||||
- from_config(md: dict)(Phase 2 Task 4): 快照 prompts 组(dict 四键)
|
||||
直接构造——registry 对文件/DB 两源的统一入口(文件源读盘入快照,
|
||||
DB 源嵌 config_json);缺键/值非字符串 → 显性 ValueError 带键名;
|
||||
- build_system(wall_deflections): system.md 的 $DEFLECTION_POOL 占位符
|
||||
替换为按语言枚举的话术清单 + "\\n\\n" + company_facts(行为 prompt
|
||||
在前、事实卡居中、当轮提醒最后拼接——拼接位在 AIService 内);
|
||||
@@ -68,15 +76,28 @@ class PromptProvider:
|
||||
extractor: str
|
||||
evaluator: str
|
||||
|
||||
@classmethod
|
||||
def from_config(cls, md: dict) -> "PromptProvider":
|
||||
"""快照 prompts 组 → PromptProvider。缺键/非字符串显性炸带键名
|
||||
(DB 快照坏数据不留到 build_system 才炸)。"""
|
||||
bad = [k for k in PROMPTS_KEYS if not isinstance((md or {}).get(k), str)]
|
||||
if bad:
|
||||
raise ValueError(f"prompts 配置缺少(或非字符串)键: {', '.join(bad)}")
|
||||
return cls(
|
||||
system=md["system"],
|
||||
company_facts=md["company_facts"],
|
||||
extractor=md["extractor"],
|
||||
evaluator=md["evaluator"])
|
||||
|
||||
@classmethod
|
||||
def from_dir(cls, prompts_dir) -> "PromptProvider":
|
||||
d = Path(prompts_dir)
|
||||
return cls(
|
||||
system=(d / "system.md").read_text(encoding="utf-8"),
|
||||
company_facts=(d / "company_facts.md").read_text(encoding="utf-8"),
|
||||
extractor=(d / "extractor.md").read_text(encoding="utf-8"),
|
||||
evaluator=(d / "evaluator.md").read_text(encoding="utf-8"),
|
||||
)
|
||||
return cls.from_config({
|
||||
"system": (d / "system.md").read_text(encoding="utf-8"),
|
||||
"company_facts": (d / "company_facts.md").read_text(encoding="utf-8"),
|
||||
"extractor": (d / "extractor.md").read_text(encoding="utf-8"),
|
||||
"evaluator": (d / "evaluator.md").read_text(encoding="utf-8"),
|
||||
})
|
||||
|
||||
def build_system(self, wall_deflections=None) -> str:
|
||||
system = self.system
|
||||
|
||||
Reference in New Issue
Block a user