deepagents-printshop 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- agents/content_editor/__init__.py +1 -0
- agents/content_editor/agent.py +279 -0
- agents/content_editor/content_reviewer.py +327 -0
- agents/content_editor/versioned_agent.py +455 -0
- agents/latex_specialist/__init__.py +1 -0
- agents/latex_specialist/agent.py +531 -0
- agents/latex_specialist/latex_analyzer.py +510 -0
- agents/latex_specialist/latex_optimizer.py +1192 -0
- agents/qa_orchestrator/__init__.py +1 -0
- agents/qa_orchestrator/agent.py +603 -0
- agents/qa_orchestrator/langgraph_workflow.py +733 -0
- agents/qa_orchestrator/pipeline_types.py +72 -0
- agents/qa_orchestrator/quality_gates.py +495 -0
- agents/qa_orchestrator/workflow_coordinator.py +139 -0
- agents/research_agent/__init__.py +1 -0
- agents/research_agent/agent.py +258 -0
- agents/research_agent/llm_report_generator.py +1023 -0
- agents/research_agent/report_generator.py +536 -0
- agents/visual_qa/__init__.py +1 -0
- agents/visual_qa/agent.py +410 -0
- deepagents_printshop-0.1.0.dist-info/METADATA +744 -0
- deepagents_printshop-0.1.0.dist-info/RECORD +37 -0
- deepagents_printshop-0.1.0.dist-info/WHEEL +4 -0
- deepagents_printshop-0.1.0.dist-info/entry_points.txt +2 -0
- deepagents_printshop-0.1.0.dist-info/licenses/LICENSE +86 -0
- tools/__init__.py +1 -0
- tools/change_tracker.py +419 -0
- tools/content_type_loader.py +171 -0
- tools/graph_generator.py +281 -0
- tools/latex_generator.py +374 -0
- tools/llm_latex_generator.py +678 -0
- tools/magazine_layout.py +462 -0
- tools/pattern_injector.py +250 -0
- tools/pattern_learner.py +477 -0
- tools/pdf_compiler.py +386 -0
- tools/version_manager.py +346 -0
- tools/visual_qa.py +799 -0
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Workflow Coordinator
|
|
3
|
+
|
|
4
|
+
Provides quality assessment and workflow summary utilities for the QA pipeline.
|
|
5
|
+
The LangGraph graph handles orchestration directly; this module supplies the
|
|
6
|
+
quality-gate evaluation helpers that nodes and routing functions call.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
import sys
|
|
10
|
+
from pathlib import Path
|
|
11
|
+
from typing import Any, Dict, List
|
|
12
|
+
|
|
13
|
+
# Add project root to path
|
|
14
|
+
project_root = Path(__file__).parent.parent.parent
|
|
15
|
+
sys.path.insert(0, str(project_root))
|
|
16
|
+
|
|
17
|
+
from agents.qa_orchestrator.quality_gates import QualityGateManager, QualityAssessment
|
|
18
|
+
from agents.qa_orchestrator.pipeline_types import AgentResult, AgentType, WorkflowStage # noqa: F401 -- re-exported
|
|
19
|
+
from tools.version_manager import VersionManager
|
|
20
|
+
from tools.change_tracker import ChangeTracker
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class WorkflowCoordinator:
|
|
24
|
+
"""
|
|
25
|
+
Quality assessment and summary utilities for the QA pipeline.
|
|
26
|
+
|
|
27
|
+
The LangGraph graph owns orchestration; this class provides:
|
|
28
|
+
- assess_workflow_quality() -- build a QualityAssessment from raw agent result dicts
|
|
29
|
+
- get_workflow_summary() -- build a summary dict from PipelineState
|
|
30
|
+
- quality_gate_manager -- for gate evaluations in routing functions
|
|
31
|
+
"""
|
|
32
|
+
|
|
33
|
+
def __init__(self, content_source: str = "research_report"):
|
|
34
|
+
self.content_source = content_source
|
|
35
|
+
self.version_manager = VersionManager()
|
|
36
|
+
self.change_tracker = ChangeTracker()
|
|
37
|
+
self.quality_gate_manager = QualityGateManager()
|
|
38
|
+
|
|
39
|
+
# Set up paths based on content source
|
|
40
|
+
self.content_dir = Path(f"artifacts/sample_content/{content_source}")
|
|
41
|
+
self.output_filename = content_source
|
|
42
|
+
|
|
43
|
+
def assess_workflow_quality(self, agent_results: List[Dict[str, Any]]) -> QualityAssessment:
|
|
44
|
+
"""
|
|
45
|
+
Assess overall workflow quality based on agent result dicts.
|
|
46
|
+
|
|
47
|
+
Args:
|
|
48
|
+
agent_results: List of serialized AgentResult dicts from PipelineState.
|
|
49
|
+
|
|
50
|
+
Returns:
|
|
51
|
+
Comprehensive quality assessment.
|
|
52
|
+
"""
|
|
53
|
+
assessment = QualityAssessment()
|
|
54
|
+
|
|
55
|
+
for r in agent_results:
|
|
56
|
+
ar = AgentResult.from_dict(r)
|
|
57
|
+
|
|
58
|
+
if ar.agent_type == AgentType.CONTENT_EDITOR and ar.success:
|
|
59
|
+
assessment.content_score = int(ar.quality_score) if ar.quality_score else None
|
|
60
|
+
assessment.content_issues = ar.issues_found
|
|
61
|
+
|
|
62
|
+
elif ar.agent_type == AgentType.LATEX_SPECIALIST and ar.success:
|
|
63
|
+
assessment.latex_score = int(ar.quality_score) if ar.quality_score else None
|
|
64
|
+
assessment.latex_issues = ar.issues_found
|
|
65
|
+
|
|
66
|
+
if ar.metadata and "latex_analysis" in ar.metadata:
|
|
67
|
+
latex_analysis = ar.metadata["latex_analysis"]
|
|
68
|
+
assessment.latex_structure = latex_analysis.get("structure_score")
|
|
69
|
+
assessment.latex_typography = latex_analysis.get("typography_score")
|
|
70
|
+
assessment.latex_tables_figures = latex_analysis.get("tables_figures_score")
|
|
71
|
+
assessment.latex_best_practices = latex_analysis.get("best_practices_score")
|
|
72
|
+
|
|
73
|
+
elif ar.agent_type == AgentType.VISUAL_QA and ar.success:
|
|
74
|
+
if ar.quality_score is not None:
|
|
75
|
+
assessment.visual_qa_score = float(ar.quality_score)
|
|
76
|
+
assessment.visual_qa_issues = ar.issues_found
|
|
77
|
+
|
|
78
|
+
return assessment
|
|
79
|
+
|
|
80
|
+
def get_workflow_summary(self, state: Dict[str, Any]) -> Dict:
|
|
81
|
+
"""
|
|
82
|
+
Generate comprehensive workflow summary from PipelineState.
|
|
83
|
+
|
|
84
|
+
Args:
|
|
85
|
+
state: Final PipelineState dict.
|
|
86
|
+
|
|
87
|
+
Returns:
|
|
88
|
+
Workflow summary dictionary.
|
|
89
|
+
"""
|
|
90
|
+
agent_results = [AgentResult.from_dict(r) for r in state.get("agent_results", [])]
|
|
91
|
+
|
|
92
|
+
# Get final quality assessment
|
|
93
|
+
quality_assessments = state.get("quality_assessments", [])
|
|
94
|
+
final_assessment = quality_assessments[-1] if quality_assessments else None
|
|
95
|
+
|
|
96
|
+
# Calculate agent performance
|
|
97
|
+
agent_performance: Dict[str, Any] = {}
|
|
98
|
+
for ar in agent_results:
|
|
99
|
+
agent_name = ar.agent_type.value
|
|
100
|
+
if agent_name not in agent_performance:
|
|
101
|
+
agent_performance[agent_name] = {
|
|
102
|
+
"executions": 0,
|
|
103
|
+
"successes": 0,
|
|
104
|
+
"total_time": 0,
|
|
105
|
+
"quality_improvements": [],
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
perf = agent_performance[agent_name]
|
|
109
|
+
perf["executions"] += 1
|
|
110
|
+
if ar.success:
|
|
111
|
+
perf["successes"] += 1
|
|
112
|
+
perf["total_time"] += ar.processing_time
|
|
113
|
+
if ar.quality_score:
|
|
114
|
+
perf["quality_improvements"].append(ar.quality_score)
|
|
115
|
+
|
|
116
|
+
return {
|
|
117
|
+
"workflow_id": state.get("workflow_id", ""),
|
|
118
|
+
"execution_summary": {
|
|
119
|
+
"start_time": state.get("start_time"),
|
|
120
|
+
"end_time": state.get("end_time"),
|
|
121
|
+
"total_processing_time": state.get("total_processing_time"),
|
|
122
|
+
"iterations_completed": state.get("iterations_completed", 0),
|
|
123
|
+
"final_stage": state.get("current_stage", "unknown"),
|
|
124
|
+
"success": state.get("success", False),
|
|
125
|
+
"human_handoff": state.get("human_handoff", False),
|
|
126
|
+
"escalated": state.get("escalated", False),
|
|
127
|
+
},
|
|
128
|
+
"version_progression": {
|
|
129
|
+
"starting_version": agent_results[0].version_created if agent_results else None,
|
|
130
|
+
"final_version": state.get("current_version"),
|
|
131
|
+
"versions_created": [r.version_created for r in agent_results if r.success],
|
|
132
|
+
},
|
|
133
|
+
"quality_progression": {
|
|
134
|
+
"final_assessment": final_assessment,
|
|
135
|
+
"quality_evaluations": len(state.get("quality_evaluations", [])),
|
|
136
|
+
"overall_score": final_assessment.get("overall_score") if final_assessment else None,
|
|
137
|
+
},
|
|
138
|
+
"agent_performance": agent_performance,
|
|
139
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Research agent for generating LaTeX reports."""
|
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
"""
|
|
2
|
+
DeepAgents PrintShop - Research Agent
|
|
3
|
+
|
|
4
|
+
A specialized agent for generating LaTeX research reports with persistent memory.
|
|
5
|
+
Integrates with DeepAgents CLI framework.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import os
|
|
9
|
+
import sys
|
|
10
|
+
from pathlib import Path
|
|
11
|
+
|
|
12
|
+
# Add project root to path
|
|
13
|
+
project_root = Path(__file__).parent.parent.parent
|
|
14
|
+
sys.path.insert(0, str(project_root))
|
|
15
|
+
|
|
16
|
+
from report_generator import ResearchReportGenerator
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class ResearchAgent:
|
|
20
|
+
"""
|
|
21
|
+
Research agent with memory for generating LaTeX reports.
|
|
22
|
+
|
|
23
|
+
This agent demonstrates how to:
|
|
24
|
+
1. Track research artifacts across sessions
|
|
25
|
+
2. Generate professional LaTeX documents
|
|
26
|
+
3. Compile PDFs with proper formatting
|
|
27
|
+
4. Maintain report structure and styling
|
|
28
|
+
"""
|
|
29
|
+
|
|
30
|
+
def __init__(self, memory_dir: str = ".deepagents/research_agent/memories"):
|
|
31
|
+
"""
|
|
32
|
+
Initialize the research agent.
|
|
33
|
+
|
|
34
|
+
Args:
|
|
35
|
+
memory_dir: Directory for storing agent memories
|
|
36
|
+
"""
|
|
37
|
+
self.memory_dir = Path(memory_dir)
|
|
38
|
+
self.memory_dir.mkdir(parents=True, exist_ok=True)
|
|
39
|
+
self.report_gen = ResearchReportGenerator()
|
|
40
|
+
|
|
41
|
+
# Initialize memory files
|
|
42
|
+
self.init_memory()
|
|
43
|
+
|
|
44
|
+
def init_memory(self):
|
|
45
|
+
"""Initialize agent memory files."""
|
|
46
|
+
memory_files = {
|
|
47
|
+
"latex_knowledge.md": """# LaTeX Document Generation Knowledge
|
|
48
|
+
|
|
49
|
+
## Document Classes
|
|
50
|
+
- article: For short reports and papers
|
|
51
|
+
- report: For longer reports with chapters
|
|
52
|
+
- book: For books with complex structure
|
|
53
|
+
- beamer: For presentations
|
|
54
|
+
|
|
55
|
+
## Key Packages
|
|
56
|
+
- graphicx: Image handling
|
|
57
|
+
- hyperref: Hyperlinks and cross-references
|
|
58
|
+
- cite: Citation management
|
|
59
|
+
- booktabs: Professional tables
|
|
60
|
+
- tikz: Vector graphics
|
|
61
|
+
|
|
62
|
+
## Best Practices
|
|
63
|
+
1. Run pdflatex at least twice for proper cross-references
|
|
64
|
+
2. Use \\label{} and \\ref{} for internal references
|
|
65
|
+
3. Keep image paths relative to the .tex file
|
|
66
|
+
4. Use vector graphics (PDF/EPS) when possible
|
|
67
|
+
""",
|
|
68
|
+
"report_structure.md": """# Research Report Structure
|
|
69
|
+
|
|
70
|
+
## Standard Sections
|
|
71
|
+
1. Abstract
|
|
72
|
+
2. Introduction
|
|
73
|
+
3. Background/Related Work
|
|
74
|
+
4. Methodology
|
|
75
|
+
5. Results
|
|
76
|
+
6. Discussion
|
|
77
|
+
7. Conclusion
|
|
78
|
+
8. References
|
|
79
|
+
|
|
80
|
+
## Tables and Figures
|
|
81
|
+
- Always include captions
|
|
82
|
+
- Use labels for cross-referencing
|
|
83
|
+
- Place close to first reference in text
|
|
84
|
+
- Number sequentially
|
|
85
|
+
|
|
86
|
+
## Citations
|
|
87
|
+
- Use consistent citation style
|
|
88
|
+
- Include all necessary bibliographic information
|
|
89
|
+
- Cite primary sources when possible
|
|
90
|
+
""",
|
|
91
|
+
"artifacts_tracking.md": """# Research Artifacts Tracking
|
|
92
|
+
|
|
93
|
+
## Content Types
|
|
94
|
+
- Markdown files: Primary content source
|
|
95
|
+
- CSV files: Data tables
|
|
96
|
+
- Images: JPG/PNG for photos, diagrams
|
|
97
|
+
- Vector graphics: EPS/SVG for charts
|
|
98
|
+
- LaTeX snippets: Custom formatting
|
|
99
|
+
|
|
100
|
+
## Artifact Locations
|
|
101
|
+
- artifacts/sample_content/: Text content in markdown
|
|
102
|
+
- artifacts/data/: CSV data files
|
|
103
|
+
- artifacts/images/: Image assets
|
|
104
|
+
- artifacts/output/: Generated LaTeX and PDFs
|
|
105
|
+
|
|
106
|
+
## Conversion Pipeline
|
|
107
|
+
1. Load markdown content
|
|
108
|
+
2. Convert to LaTeX formatting
|
|
109
|
+
3. Add tables from CSV
|
|
110
|
+
4. Include images and diagrams
|
|
111
|
+
5. Generate bibliography
|
|
112
|
+
6. Compile to PDF
|
|
113
|
+
"""
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
for filename, content in memory_files.items():
|
|
117
|
+
filepath = self.memory_dir / filename
|
|
118
|
+
if not filepath.exists():
|
|
119
|
+
with open(filepath, 'w', encoding='utf-8') as f:
|
|
120
|
+
f.write(content)
|
|
121
|
+
|
|
122
|
+
def generate_report(self, report_type: str = "sample"):
|
|
123
|
+
"""
|
|
124
|
+
Generate a research report.
|
|
125
|
+
|
|
126
|
+
Args:
|
|
127
|
+
report_type: Type of report to generate (currently only 'sample')
|
|
128
|
+
"""
|
|
129
|
+
print(f"\n{'='*60}")
|
|
130
|
+
print(f"Generating {report_type} research report...")
|
|
131
|
+
print(f"{'='*60}\n")
|
|
132
|
+
|
|
133
|
+
if report_type == "sample":
|
|
134
|
+
tex_file = self.report_gen.generate_sample_report()
|
|
135
|
+
print(f"✓ LaTeX file created: {tex_file}\n")
|
|
136
|
+
|
|
137
|
+
# Compile to PDF
|
|
138
|
+
print("Compiling to PDF...")
|
|
139
|
+
success = self.report_gen.compile_to_pdf(tex_file)
|
|
140
|
+
|
|
141
|
+
if success:
|
|
142
|
+
pdf_file = tex_file.replace('.tex', '.pdf')
|
|
143
|
+
print(f"\n{'='*60}")
|
|
144
|
+
print("✓ Report generation complete!")
|
|
145
|
+
print(f"{'='*60}")
|
|
146
|
+
print(f"LaTeX: {tex_file}")
|
|
147
|
+
print(f"PDF: {pdf_file}")
|
|
148
|
+
print(f"{'='*60}\n")
|
|
149
|
+
|
|
150
|
+
# Update memory with successful generation
|
|
151
|
+
self.log_generation(tex_file, pdf_file)
|
|
152
|
+
else:
|
|
153
|
+
print(f"\n{'='*60}")
|
|
154
|
+
print("⚠ PDF compilation failed")
|
|
155
|
+
print(f"{'='*60}")
|
|
156
|
+
print(f"LaTeX file created: {tex_file}")
|
|
157
|
+
print("You can compile manually with: pdflatex <filename>.tex")
|
|
158
|
+
print(f"{'='*60}\n")
|
|
159
|
+
else:
|
|
160
|
+
print(f"Unknown report type: {report_type}")
|
|
161
|
+
|
|
162
|
+
def log_generation(self, tex_file: str, pdf_file: str):
|
|
163
|
+
"""Log successful report generation to memory."""
|
|
164
|
+
log_file = self.memory_dir / "generation_log.md"
|
|
165
|
+
|
|
166
|
+
from datetime import datetime
|
|
167
|
+
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
|
168
|
+
|
|
169
|
+
log_entry = f"""
|
|
170
|
+
## Report Generated: {timestamp}
|
|
171
|
+
- LaTeX: {tex_file}
|
|
172
|
+
- PDF: {pdf_file}
|
|
173
|
+
- Status: Success
|
|
174
|
+
"""
|
|
175
|
+
|
|
176
|
+
# Append to log file
|
|
177
|
+
with open(log_file, 'a', encoding='utf-8') as f:
|
|
178
|
+
f.write(log_entry)
|
|
179
|
+
|
|
180
|
+
def show_capabilities(self):
|
|
181
|
+
"""Display agent capabilities."""
|
|
182
|
+
print(f"\n{'='*60}")
|
|
183
|
+
print("DeepAgents PrintShop - Research Agent Capabilities")
|
|
184
|
+
print(f"{'='*60}\n")
|
|
185
|
+
|
|
186
|
+
capabilities = [
|
|
187
|
+
"📄 Generate LaTeX documents with customizable structure",
|
|
188
|
+
"📊 Create tables from CSV data with headers",
|
|
189
|
+
"🖼️ Include images (JPG/PNG) with text wrapping",
|
|
190
|
+
"📈 Generate vector diagrams with TikZ",
|
|
191
|
+
"🔗 Add hyperlinks and cross-references",
|
|
192
|
+
"📚 Manage citations and bibliography",
|
|
193
|
+
"🎨 Customize document class, fonts, and layout",
|
|
194
|
+
"📑 Generate table of contents automatically",
|
|
195
|
+
"✏️ Support for lists, equations, and formatting",
|
|
196
|
+
"📖 Compile to PDF with pdflatex",
|
|
197
|
+
"💾 Track artifacts across sessions with memory",
|
|
198
|
+
]
|
|
199
|
+
|
|
200
|
+
for cap in capabilities:
|
|
201
|
+
print(f" {cap}")
|
|
202
|
+
|
|
203
|
+
print(f"\n{'='*60}\n")
|
|
204
|
+
|
|
205
|
+
def interactive_mode(self):
|
|
206
|
+
"""Run the agent in interactive mode."""
|
|
207
|
+
self.show_capabilities()
|
|
208
|
+
|
|
209
|
+
print("Available commands:")
|
|
210
|
+
print(" 1. generate - Generate sample research report")
|
|
211
|
+
print(" 2. help - Show capabilities")
|
|
212
|
+
print(" 3. exit - Exit the agent")
|
|
213
|
+
print()
|
|
214
|
+
|
|
215
|
+
while True:
|
|
216
|
+
try:
|
|
217
|
+
command = input("research-agent> ").strip().lower()
|
|
218
|
+
|
|
219
|
+
if command in ['exit', 'quit', 'q']:
|
|
220
|
+
print("Goodbye!")
|
|
221
|
+
break
|
|
222
|
+
elif command in ['generate', 'gen', '1']:
|
|
223
|
+
self.generate_report("sample")
|
|
224
|
+
elif command in ['help', 'h', '2']:
|
|
225
|
+
self.show_capabilities()
|
|
226
|
+
elif command == '':
|
|
227
|
+
continue
|
|
228
|
+
else:
|
|
229
|
+
print(f"Unknown command: {command}")
|
|
230
|
+
print("Try 'help' for available commands")
|
|
231
|
+
except KeyboardInterrupt:
|
|
232
|
+
print("\nInterrupted. Use 'exit' to quit.")
|
|
233
|
+
except EOFError:
|
|
234
|
+
print("\nGoodbye!")
|
|
235
|
+
break
|
|
236
|
+
|
|
237
|
+
|
|
238
|
+
def main():
|
|
239
|
+
"""Main entry point for the research agent."""
|
|
240
|
+
agent = ResearchAgent()
|
|
241
|
+
|
|
242
|
+
# Check if running with arguments
|
|
243
|
+
if len(sys.argv) > 1:
|
|
244
|
+
command = sys.argv[1].lower()
|
|
245
|
+
if command == "generate":
|
|
246
|
+
agent.generate_report("sample")
|
|
247
|
+
elif command == "help":
|
|
248
|
+
agent.show_capabilities()
|
|
249
|
+
else:
|
|
250
|
+
print(f"Unknown command: {command}")
|
|
251
|
+
print("Available commands: generate, help")
|
|
252
|
+
else:
|
|
253
|
+
# Run in interactive mode
|
|
254
|
+
agent.interactive_mode()
|
|
255
|
+
|
|
256
|
+
|
|
257
|
+
if __name__ == "__main__":
|
|
258
|
+
main()
|