Project-Rivet / v2 /engine /synthesis.py
HumboldtJoker's picture
Upload folder using huggingface_hub
4554903 verified
Raw
History Blame Contribute Delete
5.65 kB
"""Synthesis chip — the only place Rivet calls the model.
Everything upstream in the DAG is evidence gathering; everything
downstream is verification. The prompt is assembled from:
- the BDI beliefs relevant to this intent (constraints first)
- upstream artifacts (real source excerpts, migration/security reports)
- Pharos-routed knowledge packs (KV-injected on the transformers
backend, system-context on Ollama)
- the conversation history for this session
The chip never sees raw context files — beliefs and artifacts are the
interface. If it isn't in the BDI or an artifact, Rivet doesn't claim it.
"""
import json
from kintsugi_core import (
BaseSkillChip,
BDIStore,
EFEWeights,
SkillCapability,
SkillContext,
SkillDomain,
SkillRequest,
SkillResponse,
)
RIVET_SYSTEM = """You are Rivet, a senior engineer embedded with the \
Multiverse Campus team.
## Non-negotiable rules
1. Never suggest a destructive migration (DROP, TRUNCATE, in-place type \
change, RENAME). Staging and prod share the database. If asked for one, \
give the additive multi-step alternative instead — and never print the \
destructive statement, not even as a "don't do this" example.
2. Every code suggestion states: what it changes, what it could break, \
and what tests verify it.
3. If you have not read the relevant source (check the SOURCE EVIDENCE \
section), say you are reasoning from architecture, not source.
4. Auth changes get an explicit callout: "This touches authentication. \
Review with security before merging."
5. Flag known audit findings proactively when the question walks into one.
6. You are a colleague, not the lead. Suggest, don't decree.
"""
def _format_beliefs(bdi: BDIStore, belief_ids: list) -> str:
lines = []
for bid in belief_ids:
b = bdi.get_belief(bid)
if b is not None:
lines.append(f"- ({b.confidence:.2f}) {b.content}")
return "\n".join(lines) if lines else "(none loaded)"
def _format_analysis(analysis: dict) -> str:
if not analysis or not analysis.get("files"):
notes = "; ".join(analysis.get("notes", [])) if analysis else ""
return f"No source files were read for this request. {notes}".strip()
parts = []
for f in analysis["files"]:
header = f"### {f['path']}"
if f.get("git_status"):
header += f" (git: {f['git_status']} — uncommitted changes!)"
parts.append(f"{header}\n```\n{f['excerpt']}\n```")
if f.get("recent_history"):
parts.append(f"Recent commits touching this file:\n{f['recent_history']}")
return "\n\n".join(parts)
def _format_report(name: str, report: dict) -> str:
if not report:
return ""
return f"## {name}\n```json\n{json.dumps(report, indent=2, default=str)[:4000]}\n```"
class SynthesisChip(BaseSkillChip):
name = "synthesis"
description = "Generate the draft answer from evidence + beliefs + packs"
version = "2.0.0"
domain = SkillDomain.GENERAL
efe_weights = EFEWeights()
capabilities = [SkillCapability.EXTERNAL_API]
def __init__(self, model_client, bdi: BDIStore, pharos_router=None,
max_tokens: int = 1536):
super().__init__()
self.model = model_client
self.bdi = bdi
self.pharos = pharos_router
self.max_tokens = max_tokens
async def handle(self, request: SkillRequest,
context: SkillContext) -> SkillResponse:
question = context.metadata.get("question", request.raw_input)
session = context.metadata.get("session")
belief_ids = context.metadata.get("belief_ids", [])
# Pharos: route the question to knowledge packs.
knowledge, pack_names = "", []
if self.pharos is not None:
routed = self.pharos.route(question)
knowledge = routed.knowledge_text
pack_names = routed.pack_names
if session and pack_names:
for p in pack_names:
session.record_evidence("pharos_pack", p, self.name)
prompt_parts = ["# ORGANIZATIONAL BELIEFS (BDI)\n"
+ _format_beliefs(self.bdi, belief_ids)]
analysis = request.parameters.get("analysis") or {}
prompt_parts.append("# SOURCE EVIDENCE\n" + _format_analysis(analysis))
for key, title in (
("migration_report", "MIGRATION SAFETY REPORT"),
("security_report", "SECURITY REVIEW REPORT"),
):
block = _format_report(title, request.parameters.get(key) or {})
if block:
prompt_parts.append(block)
if session and session.history:
recent = session.history[-6:]
convo = "\n".join(f"{t['role']}: {t['content'][:400]}" for t in recent)
prompt_parts.append(f"# CONVERSATION SO FAR\n{convo}")
prompt_parts.append(f"# QUESTION\n{question}")
prompt = "\n\n".join(prompt_parts)
reply = self.model.generate(
prompt, system=RIVET_SYSTEM, knowledge=knowledge,
max_tokens=self.max_tokens,
)
if not reply.ok:
return SkillResponse(
content=f"model call failed: {reply.error}", success=False,
data={"text": "", "error": reply.error},
)
return SkillResponse(
content="draft generated", success=True,
data={
"text": reply.text,
"backend": reply.backend,
"knowledge_injected": reply.knowledge_injected,
"packs_used": pack_names,
},
)