PlanOpticon

planopticon / video_processor / agent / skills / requirements_chat.py
Source Blame History 95 lines
0981a08… noreply 1 """Skill: Interactive requirements gathering via guided questions."""
0981a08… noreply 2
0981a08… noreply 3 import json
0981a08… noreply 4
0981a08… noreply 5 from video_processor.agent.skills.base import (
0981a08… noreply 6 AgentContext,
0981a08… noreply 7 Artifact,
0981a08… noreply 8 Skill,
0981a08… noreply 9 register_skill,
0981a08… noreply 10 )
0981a08… noreply 11 from video_processor.utils.json_parsing import parse_json_from_response
0981a08… noreply 12
0981a08… noreply 13
0981a08… noreply 14 class RequirementsChatSkill(Skill):
0981a08… noreply 15 name = "requirements_chat"
0981a08… noreply 16 description = "Interactive requirements gathering via guided questions"
0981a08… noreply 17
0981a08… noreply 18 def execute(self, context: AgentContext, **kwargs) -> Artifact:
0981a08… noreply 19 """Generate a structured requirements questionnaire."""
0981a08… noreply 20 stats = context.query_engine.stats()
0981a08… noreply 21 entities = context.query_engine.entities()
0981a08… noreply 22
0981a08… noreply 23 parts = [
0981a08… noreply 24 "You are a requirements analyst. Based on the following "
0981a08… noreply 25 "knowledge graph context, generate a requirements "
0981a08… noreply 26 "gathering questionnaire.",
0981a08… noreply 27 "",
0981a08… noreply 28 "## Knowledge Graph Overview",
0981a08… noreply 29 stats.to_text(),
0981a08… noreply 30 "",
0981a08… noreply 31 "## Entities",
0981a08… noreply 32 entities.to_text(),
0981a08… noreply 33 "",
0981a08… noreply 34 "## Planning Entities",
0981a08… noreply 35 ]
0981a08… noreply 36 for e in context.planning_entities:
0981a08… noreply 37 parts.append(f"- {e}")
0981a08… noreply 38
0981a08… noreply 39 parts.append(
0981a08… noreply 40 '\nGenerate a JSON object with a "questions" array. '
0981a08… noreply 41 "Each question should have:\n"
0981a08… noreply 42 '- "id": string (e.g. "Q1")\n'
0981a08… noreply 43 '- "category": "goals"|"constraints"|"priorities"|"scope"\n'
0981a08… noreply 44 '- "question": string\n'
0981a08… noreply 45 '- "context": string (why this matters)\n\n'
0981a08… noreply 46 "Include 8-12 targeted questions.\n\n"
0981a08… noreply 47 "Return ONLY the JSON."
0981a08… noreply 48 )
0981a08… noreply 49
0981a08… noreply 50 prompt = "\n".join(parts)
0981a08… noreply 51 response = context.provider_manager.chat(messages=[{"role": "user", "content": prompt}])
0981a08… noreply 52 parsed = parse_json_from_response(response)
0981a08… noreply 53 content = json.dumps(parsed, indent=2) if not isinstance(parsed, str) else parsed
0981a08… noreply 54
0981a08… noreply 55 return Artifact(
0981a08… noreply 56 name="Requirements Questionnaire",
0981a08… noreply 57 content=content,
0981a08… noreply 58 artifact_type="requirements",
0981a08… noreply 59 format="json",
0981a08… noreply 60 metadata={"stage": "questionnaire"},
0981a08… noreply 61 )
0981a08… noreply 62
0981a08… noreply 63 def gather_requirements(self, context: AgentContext, answers: dict) -> dict:
0981a08… noreply 64 """Take Q&A pairs and synthesize structured requirements."""
0981a08… noreply 65 stats = context.query_engine.stats()
0981a08… noreply 66
0981a08… noreply 67 qa_text = ""
0981a08… noreply 68 for qid, answer in answers.items():
0981a08… noreply 69 qa_text += f"- {qid}: {answer}\n"
0981a08… noreply 70
0981a08… noreply 71 parts = [
0981a08… noreply 72 "You are a requirements analyst. Based on the knowledge "
0981a08… noreply 73 "graph context and the answered questions, synthesize "
0981a08… noreply 74 "structured requirements.",
0981a08… noreply 75 "",
0981a08… noreply 76 "## Knowledge Graph Overview",
0981a08… noreply 77 stats.to_text(),
0981a08… noreply 78 "",
0981a08… noreply 79 "## Answers",
0981a08… noreply 80 qa_text,
0981a08… noreply 81 "Return a JSON object with:\n"
0981a08… noreply 82 '- "goals": list of goal strings\n'
0981a08… noreply 83 '- "constraints": list of constraint strings\n'
0981a08… noreply 84 '- "priorities": list (ordered high to low)\n'
0981a08… noreply 85 '- "scope": {"in_scope": [...], "out_of_scope": [...]}\n\n'
0981a08… noreply 86 "Return ONLY the JSON.",
0981a08… noreply 87 ]
0981a08… noreply 88
0981a08… noreply 89 prompt = "\n".join(parts)
0981a08… noreply 90 response = context.provider_manager.chat(messages=[{"role": "user", "content": prompt}])
0981a08… noreply 91 result = parse_json_from_response(response)
0981a08… noreply 92 return result if isinstance(result, dict) else {"raw": result}
0981a08… noreply 93
0981a08… noreply 94
0981a08… noreply 95 register_skill(RequirementsChatSkill())

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button