Spaces:
Sleeping
Sleeping
Commit ·
f779b69
1
Parent(s): 911b955
ad
Browse files
agentgraph/methods/production/openai_structured_extractor.py
CHANGED
|
@@ -255,9 +255,9 @@ TRACE DATA:
|
|
| 255 |
{input_data}"""
|
| 256 |
|
| 257 |
try:
|
| 258 |
-
response = self.
|
| 259 |
model=self.model,
|
| 260 |
-
|
| 261 |
{"role": "system", "content": system_prompt},
|
| 262 |
{"role": "user", "content": user_prompt}
|
| 263 |
],
|
|
@@ -266,10 +266,10 @@ TRACE DATA:
|
|
| 266 |
|
| 267 |
# Get the parsed response with reasoning steps
|
| 268 |
logger.info("Parsing OpenAI response...")
|
| 269 |
-
reasoning_result = response.
|
| 270 |
logger.info(f"Response parsed successfully. Type: {type(reasoning_result)}")
|
| 271 |
|
| 272 |
-
knowledge_graph = reasoning_result
|
| 273 |
logger.info(f"Knowledge graph extracted. Type: {type(knowledge_graph)}")
|
| 274 |
|
| 275 |
# Save reasoning steps and knowledge graph for analysis
|
|
@@ -279,7 +279,7 @@ TRACE DATA:
|
|
| 279 |
|
| 280 |
# Log reasoning steps for debugging
|
| 281 |
logger.info("CoT Reasoning Steps:")
|
| 282 |
-
for step in reasoning_result
|
| 283 |
logger.info(f"Step: {step.explanation}")
|
| 284 |
|
| 285 |
logger.info(f"Extraction complete: {len(knowledge_graph.entities)} entities, {len(knowledge_graph.relations)} relations")
|
|
@@ -309,11 +309,11 @@ TRACE DATA:
|
|
| 309 |
|
| 310 |
# Prepare data to save using model_dump for safe serialization
|
| 311 |
logger.info("Serializing reasoning steps...")
|
| 312 |
-
reasoning_steps_data = [step.model_dump() for step in reasoning_result
|
| 313 |
logger.info(f"Reasoning steps serialized: {len(reasoning_steps_data)} steps")
|
| 314 |
|
| 315 |
logger.info("Serializing knowledge graph...")
|
| 316 |
-
kg_data = reasoning_result
|
| 317 |
logger.info(f"Knowledge graph serialized: {kg_data.get('system_name', 'Unknown')}")
|
| 318 |
|
| 319 |
save_data = {
|
|
|
|
| 255 |
{input_data}"""
|
| 256 |
|
| 257 |
try:
|
| 258 |
+
response = self.responses.parse(
|
| 259 |
model=self.model,
|
| 260 |
+
input=[
|
| 261 |
{"role": "system", "content": system_prompt},
|
| 262 |
{"role": "user", "content": user_prompt}
|
| 263 |
],
|
|
|
|
| 266 |
|
| 267 |
# Get the parsed response with reasoning steps
|
| 268 |
logger.info("Parsing OpenAI response...")
|
| 269 |
+
reasoning_result = response.output_parsed
|
| 270 |
logger.info(f"Response parsed successfully. Type: {type(reasoning_result)}")
|
| 271 |
|
| 272 |
+
knowledge_graph = reasoning_result["final_answer"]
|
| 273 |
logger.info(f"Knowledge graph extracted. Type: {type(knowledge_graph)}")
|
| 274 |
|
| 275 |
# Save reasoning steps and knowledge graph for analysis
|
|
|
|
| 279 |
|
| 280 |
# Log reasoning steps for debugging
|
| 281 |
logger.info("CoT Reasoning Steps:")
|
| 282 |
+
for step in reasoning_result["steps"]:
|
| 283 |
logger.info(f"Step: {step.explanation}")
|
| 284 |
|
| 285 |
logger.info(f"Extraction complete: {len(knowledge_graph.entities)} entities, {len(knowledge_graph.relations)} relations")
|
|
|
|
| 309 |
|
| 310 |
# Prepare data to save using model_dump for safe serialization
|
| 311 |
logger.info("Serializing reasoning steps...")
|
| 312 |
+
reasoning_steps_data = [step.model_dump() for step in reasoning_result["steps"]]
|
| 313 |
logger.info(f"Reasoning steps serialized: {len(reasoning_steps_data)} steps")
|
| 314 |
|
| 315 |
logger.info("Serializing knowledge graph...")
|
| 316 |
+
kg_data = reasoning_result['final_answer'].model_dump()
|
| 317 |
logger.info(f"Knowledge graph serialized: {kg_data.get('system_name', 'Unknown')}")
|
| 318 |
|
| 319 |
save_data = {
|
agentgraph/methods/production/openai_structured_extractor_backup_20250907_161109.py
DELETED
|
@@ -1,548 +0,0 @@
|
|
| 1 |
-
#!/usr/bin/env python3
|
| 2 |
-
"""
|
| 3 |
-
OpenAI Structured Outputs Knowledge Extractor
|
| 4 |
-
|
| 5 |
-
A simple, direct approach using OpenAI's structured outputs API to extract
|
| 6 |
-
knowledge graphs in one step using Pydantic models.
|
| 7 |
-
"""
|
| 8 |
-
|
| 9 |
-
import os
|
| 10 |
-
import json
|
| 11 |
-
import logging
|
| 12 |
-
from typing import Optional, List, Dict, Any
|
| 13 |
-
import uuid
|
| 14 |
-
from datetime import datetime
|
| 15 |
-
from dotenv import load_dotenv
|
| 16 |
-
from openai import OpenAI
|
| 17 |
-
from pydantic import BaseModel
|
| 18 |
-
|
| 19 |
-
# Import Pydantic models
|
| 20 |
-
from agentgraph.shared.models.reference_based import KnowledgeGraph, Entity, Relation, ContentReference
|
| 21 |
-
|
| 22 |
-
# CoT reasoning models
|
| 23 |
-
class Step(BaseModel):
|
| 24 |
-
explanation: str
|
| 25 |
-
output: str
|
| 26 |
-
|
| 27 |
-
class KnowledgeGraphReasoning(BaseModel):
|
| 28 |
-
steps: List[Step]
|
| 29 |
-
final_answer: KnowledgeGraph
|
| 30 |
-
|
| 31 |
-
# Load environment variables from root directory
|
| 32 |
-
load_dotenv('/Users/zekunwu/Desktop/agent_monitoring/.env')
|
| 33 |
-
|
| 34 |
-
# Configure logging
|
| 35 |
-
logger = logging.getLogger(__name__)
|
| 36 |
-
|
| 37 |
-
|
| 38 |
-
class OpenAIStructuredExtractor:
|
| 39 |
-
"""
|
| 40 |
-
Simple knowledge graph extractor using OpenAI's structured outputs.
|
| 41 |
-
"""
|
| 42 |
-
|
| 43 |
-
def __init__(self, model: str = "gpt-5-mini"):
|
| 44 |
-
"""
|
| 45 |
-
Initialize the extractor.
|
| 46 |
-
|
| 47 |
-
Args:
|
| 48 |
-
model: OpenAI model to use (must support structured outputs)
|
| 49 |
-
"""
|
| 50 |
-
self.model = model
|
| 51 |
-
self.client = OpenAI(api_key=os.getenv("OPENAI_API_KEY"))
|
| 52 |
-
logger.info(f"OpenAI Structured Extractor initialized with model: {model}")
|
| 53 |
-
|
| 54 |
-
def extract_knowledge_graph(self, input_data: str, context_documents: Optional[List[Dict[str, Any]]] = None) -> KnowledgeGraph:
|
| 55 |
-
"""
|
| 56 |
-
Extract knowledge graph from input data using OpenAI structured outputs.
|
| 57 |
-
|
| 58 |
-
Args:
|
| 59 |
-
input_data: The trace data to analyze
|
| 60 |
-
context_documents: Optional context documents (unused in this simple version)
|
| 61 |
-
|
| 62 |
-
Returns:
|
| 63 |
-
KnowledgeGraph: Extracted knowledge graph
|
| 64 |
-
"""
|
| 65 |
-
logger.info(f"Starting knowledge graph extraction for {len(input_data)} characters of input")
|
| 66 |
-
|
| 67 |
-
# System prompt - focus on your role and methodology
|
| 68 |
-
system_prompt = """You are an expert knowledge graph analyst specializing in agent system traces.
|
| 69 |
-
|
| 70 |
-
Extract comprehensive knowledge graphs capturing all entities and their precise relationships. Focus on workflow accuracy and relationship completeness.
|
| 71 |
-
|
| 72 |
-
CORE PRINCIPLES:
|
| 73 |
-
1. Capture ALL participants: agents, tools, tasks, inputs, outputs, humans
|
| 74 |
-
2. Use professional naming (spaces, not underscores)
|
| 75 |
-
3. Map complete workflows: Input → Agents perform Tasks → Output → Human
|
| 76 |
-
4. Focus on MAIN workflow tasks (avoid over-decomposition into subtasks)
|
| 77 |
-
5. Use NEXT only for clear sequential task dependencies
|
| 78 |
-
6. Use REQUIRED_BY for essential tool dependencies (not USES for general support)
|
| 79 |
-
7. Identify failures: errors, mistakes, broken processes, incorrect outputs
|
| 80 |
-
8. Suggest optimizations: improvements, efficiency gains, better approaches
|
| 81 |
-
|
| 82 |
-
ID ASSIGNMENT GUIDELINES:
|
| 83 |
-
- Use sequential numbering starting from 001 for each entity type
|
| 84 |
-
- agent_001, agent_002, agent_003... (in order of appearance/importance)
|
| 85 |
-
- task_001, task_002, task_003... (in workflow order)
|
| 86 |
-
- input_001, output_001, human_001 (typically one of each)
|
| 87 |
-
- tool_001 for Computer Terminal or similar tools
|
| 88 |
-
- Assign based on trace content, not predetermined roles
|
| 89 |
-
|
| 90 |
-
RELATIONSHIP TYPES (use exactly these):
|
| 91 |
-
- CONSUMED_BY: Input consumed by agent (input_001 → agent_001)
|
| 92 |
-
- PERFORMS: Agent performs task (agent_001 → task_001)
|
| 93 |
-
- NEXT: Task A leads to Task B in sequence (task_001 → task_002)
|
| 94 |
-
- PRODUCES: Task produces output (task_001 → output_001)
|
| 95 |
-
- DELIVERS_TO: Output delivered to human (output_001 → human_001)
|
| 96 |
-
- REQUIRED_BY: Tool required by task (agent_004 → task_001)
|
| 97 |
-
- USES: Agent uses tool (agent_001 → agent_004)
|
| 98 |
-
- ASSIGNED_TO: Task assigned to agent (task_001 → agent_002)
|
| 99 |
-
- INTERVENES: Agent coordinates task (agent_002 → task_001)
|
| 100 |
-
|
| 101 |
-
Return complete, accurate knowledge graphs with proper workflow sequences."""
|
| 102 |
-
|
| 103 |
-
# User prompt - specific instructions with few-shot example and data
|
| 104 |
-
user_prompt = f"""Analyze this agent system trace step by step and extract a knowledge graph.
|
| 105 |
-
|
| 106 |
-
Think through this systematically. Use as many reasoning steps as needed to thoroughly analyze the trace.
|
| 107 |
-
Each step should have a clear explanation and specific output findings.
|
| 108 |
-
|
| 109 |
-
IMPORTANT FORMATTING RULES:
|
| 110 |
-
- Set raw_prompt to empty string "" for ALL entities (content should only be in raw_prompt_ref)
|
| 111 |
-
- Set interaction_prompt to empty string "" for ALL relations (content should only be in interaction_prompt_ref)
|
| 112 |
-
- Use only line number references in raw_prompt_ref and interaction_prompt_ref, never include actual text content
|
| 113 |
-
- Determine your own number of reasoning steps based on trace complexity
|
| 114 |
-
|
| 115 |
-
EXAMPLE OUTPUT STRUCTURE:
|
| 116 |
-
Here's the expected knowledge graph structure for multi-agent collaboration traces:
|
| 117 |
-
{{
|
| 118 |
-
"system_name": "California Great America Ticket Analysis System",
|
| 119 |
-
"system_summary": "This system helps analyze the cost-saving potential of purchasing season passes versus individual daily tickets at California's Great America in San Jose. The process starts with an inquiry regarding savings from the Inquiry about Savings from Season Pass vs Daily Tickets (input_001), which is consumed by the Verification Expert (agent_002), who performs the Verify Cost of Daily Ticket and Season Pass in 2024 (task_001).",
|
| 120 |
-
"entities": [
|
| 121 |
-
{{
|
| 122 |
-
"id": "agent_001",
|
| 123 |
-
"type": "Agent",
|
| 124 |
-
"name": "Problem Solving Expert",
|
| 125 |
-
"importance": "HIGH",
|
| 126 |
-
"raw_prompt": "",
|
| 127 |
-
"raw_prompt_ref": [{{"line_start": 17, "line_end": 17}}, {{"line_start": 34, "line_end": 34}}, {{"line_start": 45, "line_end": 45}}]
|
| 128 |
-
}},
|
| 129 |
-
{{
|
| 130 |
-
"id": "agent_002",
|
| 131 |
-
"type": "Agent",
|
| 132 |
-
"name": "Verification Expert",
|
| 133 |
-
"importance": "HIGH",
|
| 134 |
-
"raw_prompt": "",
|
| 135 |
-
"raw_prompt_ref": [{{"line_start": 66, "line_end": 66}}, {{"line_start": 112, "line_end": 112}}, {{"line_start": 149, "line_end": 149}}, {{"line_start": 164, "line_end": 164}}]
|
| 136 |
-
}},
|
| 137 |
-
{{
|
| 138 |
-
"id": "agent_003",
|
| 139 |
-
"type": "Agent",
|
| 140 |
-
"name": "Arithmetic Progressions Expert",
|
| 141 |
-
"importance": "MEDIUM",
|
| 142 |
-
"raw_prompt": "",
|
| 143 |
-
"raw_prompt_ref": [{{"line_start": 172, "line_end": 172}}, {{"line_start": 181, "line_end": 181}}]
|
| 144 |
-
}},
|
| 145 |
-
{{
|
| 146 |
-
"id": "agent_004",
|
| 147 |
-
"type": "Tool",
|
| 148 |
-
"name": "Computer Terminal",
|
| 149 |
-
"importance": "LOW",
|
| 150 |
-
"raw_prompt": "",
|
| 151 |
-
"raw_prompt_ref": [{{"line_start": 21, "line_end": 21}}, {{"line_start": 32, "line_end": 32}}]
|
| 152 |
-
}},
|
| 153 |
-
{{
|
| 154 |
-
"id": "task_001",
|
| 155 |
-
"type": "Task",
|
| 156 |
-
"name": "Verify Cost of Daily Ticket and Season Pass in 2024",
|
| 157 |
-
"importance": "HIGH",
|
| 158 |
-
"raw_prompt": "",
|
| 159 |
-
"raw_prompt_ref": [{{"line_start": 8, "line_end": 8}}, {{"line_start": 10, "line_end": 10}}, {{"line_start": 11, "line_end": 12}}]
|
| 160 |
-
}},
|
| 161 |
-
{{
|
| 162 |
-
"id": "task_002",
|
| 163 |
-
"type": "Task",
|
| 164 |
-
"name": "Calculate Savings Amount",
|
| 165 |
-
"importance": "HIGH",
|
| 166 |
-
"raw_prompt": "",
|
| 167 |
-
"raw_prompt_ref": [{{"line_start": 119, "line_end": 126}}]
|
| 168 |
-
}},
|
| 169 |
-
{{
|
| 170 |
-
"id": "input_001",
|
| 171 |
-
"type": "Input",
|
| 172 |
-
"name": "Inquiry about Savings from Season Pass vs Daily Tickets",
|
| 173 |
-
"importance": "HIGH",
|
| 174 |
-
"raw_prompt": "",
|
| 175 |
-
"raw_prompt_ref": [{{"line_start": 6, "line_end": 6}}]
|
| 176 |
-
}},
|
| 177 |
-
{{
|
| 178 |
-
"id": "output_001",
|
| 179 |
-
"type": "Output",
|
| 180 |
-
"name": "Saved Amount from Season Pass Purchase",
|
| 181 |
-
"importance": "HIGH",
|
| 182 |
-
"raw_prompt": "",
|
| 183 |
-
"raw_prompt_ref": [{{"line_start": 119, "line_end": 119}}, {{"line_start": 126, "line_end": 126}}]
|
| 184 |
-
}},
|
| 185 |
-
{{
|
| 186 |
-
"id": "human_001",
|
| 187 |
-
"type": "Human",
|
| 188 |
-
"name": "Park Visitor",
|
| 189 |
-
"importance": "HIGH",
|
| 190 |
-
"raw_prompt": "",
|
| 191 |
-
"raw_prompt_ref": [{{"line_start": 1, "line_end": 1}}]
|
| 192 |
-
}}
|
| 193 |
-
],
|
| 194 |
-
"relations": [
|
| 195 |
-
{{
|
| 196 |
-
"id": "relation_001",
|
| 197 |
-
"source": "input_001",
|
| 198 |
-
"target": "agent_002",
|
| 199 |
-
"type": "CONSUMED_BY",
|
| 200 |
-
"importance": "HIGH",
|
| 201 |
-
"interaction_prompt": "",
|
| 202 |
-
"interaction_prompt_ref": [{{"line_start": 6, "line_end": 6}}]
|
| 203 |
-
}},
|
| 204 |
-
{{
|
| 205 |
-
"id": "relation_002",
|
| 206 |
-
"source": "agent_002",
|
| 207 |
-
"target": "task_001",
|
| 208 |
-
"type": "PERFORMS",
|
| 209 |
-
"importance": "HIGH",
|
| 210 |
-
"interaction_prompt": "",
|
| 211 |
-
"interaction_prompt_ref": [{{"line_start": 112, "line_end": 112}}, {{"line_start": 164, "line_end": 164}}]
|
| 212 |
-
}},
|
| 213 |
-
{{
|
| 214 |
-
"id": "relation_003",
|
| 215 |
-
"source": "task_001",
|
| 216 |
-
"target": "agent_002",
|
| 217 |
-
"type": "ASSIGNED_TO",
|
| 218 |
-
"importance": "HIGH",
|
| 219 |
-
"interaction_prompt": "",
|
| 220 |
-
"interaction_prompt_ref": [{{"line_start": 8, "line_end": 8}}]
|
| 221 |
-
}},
|
| 222 |
-
{{
|
| 223 |
-
"id": "relation_004",
|
| 224 |
-
"source": "task_001",
|
| 225 |
-
"target": "output_001",
|
| 226 |
-
"type": "PRODUCES",
|
| 227 |
-
"importance": "HIGH",
|
| 228 |
-
"interaction_prompt": "",
|
| 229 |
-
"interaction_prompt_ref": [{{"line_start": 119, "line_end": 119}}]
|
| 230 |
-
}},
|
| 231 |
-
{{
|
| 232 |
-
"id": "relation_005",
|
| 233 |
-
"source": "output_001",
|
| 234 |
-
"target": "human_001",
|
| 235 |
-
"type": "DELIVERS_TO",
|
| 236 |
-
"importance": "HIGH",
|
| 237 |
-
"interaction_prompt": "",
|
| 238 |
-
"interaction_prompt_ref": [{{"line_start": 126, "line_end": 126}}]
|
| 239 |
-
}},
|
| 240 |
-
{{
|
| 241 |
-
"id": "relation_006",
|
| 242 |
-
"source": "task_001",
|
| 243 |
-
"target": "task_002",
|
| 244 |
-
"type": "NEXT",
|
| 245 |
-
"importance": "HIGH",
|
| 246 |
-
"interaction_prompt": "",
|
| 247 |
-
"interaction_prompt_ref": [{{"line_start": 164, "line_end": 164}}]
|
| 248 |
-
}},
|
| 249 |
-
{{
|
| 250 |
-
"id": "relation_007",
|
| 251 |
-
"source": "task_002",
|
| 252 |
-
"target": "agent_004",
|
| 253 |
-
"type": "REQUIRED_BY",
|
| 254 |
-
"importance": "MEDIUM",
|
| 255 |
-
"interaction_prompt": "",
|
| 256 |
-
"interaction_prompt_ref": [{{"line_start": 50, "line_end": 55}}]
|
| 257 |
-
}}
|
| 258 |
-
],
|
| 259 |
-
"failures": [
|
| 260 |
-
{{
|
| 261 |
-
"id": "failure_001",
|
| 262 |
-
"description": "Verification Expert failed to access real-time pricing data, relying on potentially outdated cost estimates",
|
| 263 |
-
"raw_text": "However, since I am currently unable to access external websites, I will use the provided cost",
|
| 264 |
-
"raw_text_ref": [],
|
| 265 |
-
"affected_id": "agent_002",
|
| 266 |
-
"risk_type": "RETRIEVAL_ERROR"
|
| 267 |
-
}}
|
| 268 |
-
],
|
| 269 |
-
"optimizations": [
|
| 270 |
-
{{
|
| 271 |
-
"id": "opt_001",
|
| 272 |
-
"description": "Implement automated price verification system to reduce manual verification overhead and improve accuracy",
|
| 273 |
-
"raw_text": "Enhanced price verification with real-time data access",
|
| 274 |
-
"raw_text_ref": [],
|
| 275 |
-
"affected_ids": ["agent_002", "task_001"],
|
| 276 |
-
"recommendation_type": "TOOL_ENHANCEMENT"
|
| 277 |
-
}}
|
| 278 |
-
]
|
| 279 |
-
}}
|
| 280 |
-
|
| 281 |
-
Now analyze the following trace data:
|
| 282 |
-
|
| 283 |
-
ENTITY TYPES:
|
| 284 |
-
- Agent: AI agents with specific roles
|
| 285 |
-
- Task: Specific tasks or objectives
|
| 286 |
-
- Tool: Tools or functions used
|
| 287 |
-
- Input: Data inputs to the system
|
| 288 |
-
- Output: Data outputs from the system
|
| 289 |
-
- Human: Human users or stakeholders
|
| 290 |
-
|
| 291 |
-
RELATIONSHIP TYPES:
|
| 292 |
-
- CONSUMED_BY: Input→Agent
|
| 293 |
-
- PERFORMS: Agent→Task
|
| 294 |
-
- ASSIGNED_TO: Task→Agent
|
| 295 |
-
- USES: Agent→Tool
|
| 296 |
-
- REQUIRED_BY: Tool→Task
|
| 297 |
-
- SUBTASK_OF: Task→Task
|
| 298 |
-
- NEXT: Task→Task (sequence)
|
| 299 |
-
- PRODUCES: Task→Output
|
| 300 |
-
- DELIVERS_TO: Output→Human
|
| 301 |
-
- INTERVENES: Agent/Human→Task
|
| 302 |
-
|
| 303 |
-
REQUIREMENTS:
|
| 304 |
-
For each entity provide:
|
| 305 |
-
- id: unique identifier
|
| 306 |
-
- type: one of the types above
|
| 307 |
-
- name: descriptive name
|
| 308 |
-
- importance: HIGH, MEDIUM, or LOW
|
| 309 |
-
- raw_prompt: actual prompt/specification content that defines this entity
|
| 310 |
-
- raw_prompt_ref: list of content references pointing to relevant lines in the input trace where this entity is mentioned or defined
|
| 311 |
-
|
| 312 |
-
For each relation provide:
|
| 313 |
-
- id: unique identifier
|
| 314 |
-
- source/target: entity IDs
|
| 315 |
-
- type: one of the types above
|
| 316 |
-
- importance: HIGH, MEDIUM, or LOW
|
| 317 |
-
- interaction_prompt: runtime evidence showing this relationship occurred
|
| 318 |
-
- interaction_prompt_ref: list of content references pointing to relevant lines in the input trace where this relationship evidence is found
|
| 319 |
-
|
| 320 |
-
IMPORTANT: Create appropriate line number references based on where entities and relationships are mentioned in the trace. Use reasonable line estimates for JSON structure.
|
| 321 |
-
|
| 322 |
-
Also provide system_name and system_summary for the overall system.
|
| 323 |
-
|
| 324 |
-
EXTRACTION FOCUS:
|
| 325 |
-
1. Identify MAIN participants: primary agents, core tasks, key inputs/outputs, humans
|
| 326 |
-
2. Focus on the PRIMARY workflow (avoid creating too many subtasks)
|
| 327 |
-
3. Connect entities based on ACTUAL interactions in the trace
|
| 328 |
-
4. Use clean professional naming (no underscores)
|
| 329 |
-
5. DETECT FAILURES: Look for errors, exceptions, incorrect results, failed executions
|
| 330 |
-
6. SUGGEST OPTIMIZATIONS: Identify inefficiencies, improvement opportunities
|
| 331 |
-
|
| 332 |
-
CRITICAL RELATIONSHIP PATTERNS (follow exactly):
|
| 333 |
-
- input_001 --CONSUMED_BY--> agent_002 (main processing agent)
|
| 334 |
-
- agent_002 --PERFORMS--> task_001 (primary task execution)
|
| 335 |
-
- task_001 --ASSIGNED_TO--> agent_002 (task ownership)
|
| 336 |
-
- task_001 --PRODUCES--> output_001 (direct output generation)
|
| 337 |
-
- output_001 --DELIVERS_TO--> human_001 (final delivery)
|
| 338 |
-
- agent_002 --INTERVENES--> task_001 (coordination/oversight)
|
| 339 |
-
- agent_001 --USES--> agent_004 (tool utilization)
|
| 340 |
-
|
| 341 |
-
ENTITY ID RULES:
|
| 342 |
-
- agent_001: First mentioned expert, agent_002: Main performer, agent_003: Supporting expert
|
| 343 |
-
- agent_004: Always Computer Terminal (tool type)
|
| 344 |
-
- task_001: Primary workflow task (avoid creating task_002 unless truly sequential)
|
| 345 |
-
- Use exactly these IDs, don't create tool_001 or extra tasks unnecessarily
|
| 346 |
-
|
| 347 |
-
FAILURE DETECTION (look for):
|
| 348 |
-
- Execution errors, exceptions, failed operations
|
| 349 |
-
- Incorrect outputs, wrong calculations, invalid results
|
| 350 |
-
- Missing validations, incomplete processes
|
| 351 |
-
- Tool limitations, access restrictions
|
| 352 |
-
- Agent coordination problems
|
| 353 |
-
|
| 354 |
-
OPTIMIZATION OPPORTUNITIES (suggest):
|
| 355 |
-
- Tool enhancements, automation possibilities
|
| 356 |
-
- Workflow simplifications, redundancy removal
|
| 357 |
-
- Agent merging or specialization
|
| 358 |
-
- Performance improvements, efficiency gains
|
| 359 |
-
- Missing capabilities or better approaches
|
| 360 |
-
|
| 361 |
-
IMPORTANT: Always provide at least 1-2 failures and optimizations based on trace analysis.
|
| 362 |
-
|
| 363 |
-
TRACE DATA:
|
| 364 |
-
{input_data}"""
|
| 365 |
-
|
| 366 |
-
try:
|
| 367 |
-
response = self.client.responses.parse(
|
| 368 |
-
model=self.model,
|
| 369 |
-
input=[
|
| 370 |
-
{"role": "system", "content": system_prompt},
|
| 371 |
-
{"role": "user", "content": user_prompt}
|
| 372 |
-
],
|
| 373 |
-
text_format=KnowledgeGraphReasoning,
|
| 374 |
-
)
|
| 375 |
-
|
| 376 |
-
# Get the parsed response with reasoning steps
|
| 377 |
-
logger.info("Parsing OpenAI response...")
|
| 378 |
-
reasoning_result = response.output_parsed
|
| 379 |
-
logger.info(f"Response parsed successfully. Type: {type(reasoning_result)}")
|
| 380 |
-
|
| 381 |
-
knowledge_graph = reasoning_result.final_answer
|
| 382 |
-
logger.info(f"Knowledge graph extracted. Type: {type(knowledge_graph)}")
|
| 383 |
-
|
| 384 |
-
# Save reasoning steps and knowledge graph for analysis
|
| 385 |
-
logger.info("About to save extraction results...")
|
| 386 |
-
self._save_extraction_results(reasoning_result, input_data)
|
| 387 |
-
logger.info("Save extraction results completed.")
|
| 388 |
-
|
| 389 |
-
# Log reasoning steps for debugging
|
| 390 |
-
logger.info("CoT Reasoning Steps:")
|
| 391 |
-
for step in reasoning_result.steps:
|
| 392 |
-
logger.info(f"Step: {step.explanation}")
|
| 393 |
-
|
| 394 |
-
logger.info(f"Extraction complete: {len(knowledge_graph.entities)} entities, {len(knowledge_graph.relations)} relations")
|
| 395 |
-
return knowledge_graph
|
| 396 |
-
|
| 397 |
-
except Exception as e:
|
| 398 |
-
logger.error(f"Extraction failed: {e}")
|
| 399 |
-
raise
|
| 400 |
-
|
| 401 |
-
def _save_extraction_results(self, reasoning_result, trace_text: str):
|
| 402 |
-
"""Save reasoning steps and knowledge graph for analysis"""
|
| 403 |
-
try:
|
| 404 |
-
logger.info("Starting to save extraction results...")
|
| 405 |
-
|
| 406 |
-
# Create results directory if it doesn't exist
|
| 407 |
-
results_dir = "extraction_analysis"
|
| 408 |
-
os.makedirs(results_dir, exist_ok=True)
|
| 409 |
-
logger.info(f"Results directory ready: {results_dir}")
|
| 410 |
-
|
| 411 |
-
# Generate timestamp and unique ID
|
| 412 |
-
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
|
| 413 |
-
extraction_id = str(uuid.uuid4())[:8]
|
| 414 |
-
filename = f"cot_extraction_{timestamp}_{extraction_id}.json"
|
| 415 |
-
logger.info(f"Generated filename: {filename}")
|
| 416 |
-
|
| 417 |
-
# Prepare data to save using model_dump for safe serialization
|
| 418 |
-
logger.info("Serializing reasoning steps...")
|
| 419 |
-
reasoning_steps_data = [step.model_dump() for step in reasoning_result.steps]
|
| 420 |
-
logger.info(f"Reasoning steps serialized: {len(reasoning_steps_data)} steps")
|
| 421 |
-
|
| 422 |
-
logger.info("Serializing knowledge graph...")
|
| 423 |
-
kg_data = reasoning_result.final_answer.model_dump()
|
| 424 |
-
logger.info(f"Knowledge graph serialized: {kg_data.get('system_name', 'Unknown')}")
|
| 425 |
-
|
| 426 |
-
save_data = {
|
| 427 |
-
"timestamp": timestamp,
|
| 428 |
-
"extraction_id": extraction_id,
|
| 429 |
-
"model": self.model,
|
| 430 |
-
"reasoning_steps": reasoning_steps_data,
|
| 431 |
-
"knowledge_graph": kg_data,
|
| 432 |
-
"input_trace_length": len(trace_text),
|
| 433 |
-
"input_trace_preview": trace_text[:500] + "..." if len(trace_text) > 500 else trace_text
|
| 434 |
-
}
|
| 435 |
-
|
| 436 |
-
# Save to file
|
| 437 |
-
filepath = os.path.join(results_dir, filename)
|
| 438 |
-
logger.info(f"Writing to file: {filepath}")
|
| 439 |
-
|
| 440 |
-
with open(filepath, 'w', encoding='utf-8') as f:
|
| 441 |
-
json.dump(save_data, f, indent=2, ensure_ascii=False)
|
| 442 |
-
|
| 443 |
-
# Verify file was written
|
| 444 |
-
file_size = os.path.getsize(filepath)
|
| 445 |
-
logger.info(f"Extraction results saved successfully: {filepath} ({file_size} bytes)")
|
| 446 |
-
|
| 447 |
-
except Exception as e:
|
| 448 |
-
logger.error(f"Failed to save extraction results: {e}")
|
| 449 |
-
import traceback
|
| 450 |
-
logger.error(f"Traceback: {traceback.format_exc()}")
|
| 451 |
-
|
| 452 |
-
def process_text(self, input_data: str) -> Dict[str, Any]:
|
| 453 |
-
"""
|
| 454 |
-
Process text and return structured response (for compatibility with extraction factory).
|
| 455 |
-
|
| 456 |
-
Args:
|
| 457 |
-
input_data: The trace data to analyze
|
| 458 |
-
|
| 459 |
-
Returns:
|
| 460 |
-
Dict with success status and kg_data
|
| 461 |
-
"""
|
| 462 |
-
try:
|
| 463 |
-
kg = self.extract_knowledge_graph(input_data)
|
| 464 |
-
return {
|
| 465 |
-
"success": True,
|
| 466 |
-
"kg_data": kg.model_dump()
|
| 467 |
-
}
|
| 468 |
-
except Exception as e:
|
| 469 |
-
return {
|
| 470 |
-
"success": False,
|
| 471 |
-
"error": str(e),
|
| 472 |
-
"kg_data": {}
|
| 473 |
-
}
|
| 474 |
-
|
| 475 |
-
def extract_knowledge_graph_with_context(
|
| 476 |
-
input_data: str,
|
| 477 |
-
context_documents: Optional[List[Dict[str, Any]]] = None,
|
| 478 |
-
model: str = "gpt-5-mini"
|
| 479 |
-
) -> KnowledgeGraph:
|
| 480 |
-
"""
|
| 481 |
-
Main entry point for knowledge graph extraction.
|
| 482 |
-
|
| 483 |
-
Args:
|
| 484 |
-
input_data: The trace data to analyze
|
| 485 |
-
context_documents: Optional context documents
|
| 486 |
-
model: OpenAI model to use
|
| 487 |
-
|
| 488 |
-
Returns:
|
| 489 |
-
KnowledgeGraph: Extracted knowledge graph
|
| 490 |
-
"""
|
| 491 |
-
extractor = OpenAIStructuredExtractor(model=model)
|
| 492 |
-
return extractor.extract_knowledge_graph(input_data, context_documents)
|
| 493 |
-
|
| 494 |
-
def extract_knowledge_graph(input_data: str) -> KnowledgeGraph:
|
| 495 |
-
"""
|
| 496 |
-
Simple entry point without context (for backward compatibility).
|
| 497 |
-
|
| 498 |
-
Args:
|
| 499 |
-
input_data: The trace data to analyze
|
| 500 |
-
|
| 501 |
-
Returns:
|
| 502 |
-
KnowledgeGraph: Extracted knowledge graph
|
| 503 |
-
"""
|
| 504 |
-
return extract_knowledge_graph_with_context(input_data)
|
| 505 |
-
|
| 506 |
-
# Factory class for integration
|
| 507 |
-
class OpenAIStructuredFactory:
|
| 508 |
-
"""Factory class for OpenAI structured extraction method."""
|
| 509 |
-
|
| 510 |
-
def __init__(self, model: str = "gpt-5-mini"):
|
| 511 |
-
self.model = model
|
| 512 |
-
self.extractor = OpenAIStructuredExtractor(model)
|
| 513 |
-
|
| 514 |
-
def set_model(self, model: str):
|
| 515 |
-
"""Set the model for this factory."""
|
| 516 |
-
self.model = model
|
| 517 |
-
self.extractor = OpenAIStructuredExtractor(model)
|
| 518 |
-
|
| 519 |
-
def process_text(self, input_data: str) -> Dict[str, Any]:
|
| 520 |
-
"""Process text using the extractor."""
|
| 521 |
-
return self.extractor.process_text(input_data)
|
| 522 |
-
|
| 523 |
-
def extract_knowledge_graph(self, input_data: str, context_documents: Optional[List[Dict[str, Any]]] = None) -> KnowledgeGraph:
|
| 524 |
-
"""Extract knowledge graph using the current model."""
|
| 525 |
-
return self.extractor.extract_knowledge_graph(input_data, context_documents)
|
| 526 |
-
|
| 527 |
-
# Export factory instance
|
| 528 |
-
openai_structured_factory = OpenAIStructuredFactory()
|
| 529 |
-
|
| 530 |
-
if __name__ == "__main__":
|
| 531 |
-
# Simple test
|
| 532 |
-
test_input = """
|
| 533 |
-
Agent: DataAnalyzer
|
| 534 |
-
Task: Analyze customer data and generate insights
|
| 535 |
-
Tool: pandas_analyzer
|
| 536 |
-
|
| 537 |
-
The DataAnalyzer agent processes customer data using pandas_analyzer tool
|
| 538 |
-
to generate business insights for the marketing team.
|
| 539 |
-
"""
|
| 540 |
-
|
| 541 |
-
print("Testing OpenAI Structured Extractor...")
|
| 542 |
-
try:
|
| 543 |
-
kg = extract_knowledge_graph(test_input)
|
| 544 |
-
print(f"✅ Success! Extracted {len(kg.entities)} entities and {len(kg.relations)} relations")
|
| 545 |
-
print(f"System: {kg.system_name}")
|
| 546 |
-
print(f"Summary: {kg.system_summary}")
|
| 547 |
-
except Exception as e:
|
| 548 |
-
print(f"❌ Error: {e}")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|