feat(skill-learning): preserve base skill during synthesis
This commit is contained in:
@ -205,7 +205,13 @@ class SkillLearningService:
|
||||
)
|
||||
if candidate.kind == "merge_skills":
|
||||
target_name = self._suggest_skill_name(candidate, packet)
|
||||
payload = await self.synthesizer.synthesize_merge(candidate, packet, provider, model)
|
||||
payload = await self.synthesizer.synthesize_merge(
|
||||
candidate,
|
||||
packet,
|
||||
provider,
|
||||
model,
|
||||
base_skill=self._merged_base_skill_snapshot(candidate.related_skill_names),
|
||||
)
|
||||
return self.draft_service.create_merge_draft(
|
||||
skill_name=target_name,
|
||||
base_version=None,
|
||||
@ -217,7 +223,13 @@ class SkillLearningService:
|
||||
)
|
||||
target_skill = candidate.related_skill_names[0]
|
||||
base_version = candidate.evidence.get("skill_version")
|
||||
payload = await self.synthesizer.synthesize_revision(candidate, packet, provider, model)
|
||||
payload = await self.synthesizer.synthesize_revision(
|
||||
candidate,
|
||||
packet,
|
||||
provider,
|
||||
model,
|
||||
base_skill=self._base_skill_snapshot(target_skill, base_version),
|
||||
)
|
||||
return self.draft_service.create_revision_draft(
|
||||
skill_name=target_skill,
|
||||
base_version=base_version,
|
||||
@ -228,6 +240,46 @@ class SkillLearningService:
|
||||
evidence_refs=[{"run_id": item} for item in candidate.source_run_ids],
|
||||
)
|
||||
|
||||
def _base_skill_snapshot(self, skill_name: str, version: str | None) -> dict[str, Any] | None:
|
||||
loaded = self.draft_service.store.read_published_skill(skill_name, version)
|
||||
if loaded is None:
|
||||
return None
|
||||
return {
|
||||
"skill_name": loaded.version.skill_name,
|
||||
"version": loaded.version.version,
|
||||
"frontmatter": dict(loaded.version.frontmatter),
|
||||
"content": loaded.content,
|
||||
"summary": loaded.version.summary,
|
||||
"tool_hints": list(loaded.version.tool_hints),
|
||||
}
|
||||
|
||||
def _merged_base_skill_snapshot(self, skill_names: list[str]) -> dict[str, Any] | None:
|
||||
snapshots = [
|
||||
snapshot
|
||||
for name in skill_names
|
||||
if (snapshot := self._base_skill_snapshot(name, None)) is not None
|
||||
]
|
||||
if not snapshots:
|
||||
return None
|
||||
return {
|
||||
"skill_name": "merge:" + ",".join(str(item["skill_name"]) for item in snapshots),
|
||||
"version": "mixed",
|
||||
"frontmatter": {"merged_skills": [item["frontmatter"] for item in snapshots]},
|
||||
"content": "\n\n".join(
|
||||
f"<!-- base skill: {item['skill_name']} {item['version']} -->\n{item['content']}"
|
||||
for item in snapshots
|
||||
),
|
||||
"summary": "\n".join(str(item["summary"]) for item in snapshots if item.get("summary")),
|
||||
"tool_hints": list(
|
||||
dict.fromkeys(
|
||||
tool
|
||||
for item in snapshots
|
||||
for tool in item.get("tool_hints", [])
|
||||
if str(tool).strip()
|
||||
)
|
||||
),
|
||||
}
|
||||
|
||||
def rescore_skill_versions(self) -> list[SkillPerformanceSnapshot]:
|
||||
snapshots: list[SkillPerformanceSnapshot] = []
|
||||
grouped: dict[tuple[str, str], list[SkillEffectRecord]] = {}
|
||||
|
||||
Reference in New Issue
Block a user