| | from dataclasses import dataclass, asdict |
| | from typing import Dict, Any, Optional |
| |
|
| | from .config import RunConfig, ModelSpec |
| | from .agents import AnalyzerAgent, RefactorAgent, CriticAgent, AgentResult, BaseAgent |
| | from .tasks import TaskContext, build_analyzer_prompt, build_refactor_prompt, build_critic_prompt |
| | from .backends import HFInferenceAPIBackend |
| |
|
| | try: |
| | from PIL import Image |
| | except Exception: |
| | Image = None |
| |
|
| |
|
| | @dataclass |
| | class RunTrace: |
| | task: str |
| | input_requirements: str |
| | diagram_context: str |
| | analyzer: AgentResult |
| | refactor: AgentResult |
| | critic: AgentResult |
| |
|
| | def to_dict(self) -> Dict[str, Any]: |
| | return { |
| | "task": self.task, |
| | "input_requirements": self.input_requirements, |
| | "diagram_context": self.diagram_context, |
| | "analyzer": asdict(self.analyzer), |
| | "refactor": asdict(self.refactor), |
| | "critic": asdict(self.critic), |
| | } |
| |
|
| |
|
| | class Orchestrator: |
| | def __init__(self, cfg: RunConfig, ctx: Optional[TaskContext] = None): |
| | self.cfg = cfg |
| | self.ctx = ctx or TaskContext() |
| |
|
| | self.analyzer = AnalyzerAgent(cfg.analyzer) |
| | self.refactor = RefactorAgent(cfg.refactor) |
| | self.critic = CriticAgent(cfg.critic) |
| |
|
| | |
| | |
| | self.ocr_backend = HFInferenceAPIBackend("microsoft/trocr-base-printed") |
| | self.caption_backend = HFInferenceAPIBackend("Salesforce/blip-image-captioning-large") |
| |
|
| | def _extract_diagram_context(self, image: Optional["Image.Image"]) -> str: |
| | if image is None: |
| | return "" |
| |
|
| | parts = [] |
| | try: |
| | ocr = self.ocr_backend.image_to_text(image) |
| | if ocr and ocr.strip(): |
| | parts.append("OCR (текст на изображении):\n" + ocr.strip()) |
| | except Exception as e: |
| | parts.append(f"OCR: ошибка ({type(e).__name__})") |
| |
|
| | try: |
| | cap = self.caption_backend.image_to_text(image) |
| | if cap and cap.strip(): |
| | parts.append("Описание изображения:\n" + cap.strip()) |
| | except Exception as e: |
| | parts.append(f"Caption: ошибка ({type(e).__name__})") |
| |
|
| | return "\n\n".join(parts).strip() |
| |
|
| | def run(self, requirements_text: str, image: Optional["Image.Image"] = None) -> RunTrace: |
| | diagram_context = self._extract_diagram_context(image) |
| |
|
| | p1 = build_analyzer_prompt(requirements_text, diagram_context, self.ctx) |
| | r1 = self.analyzer.run(p1) |
| |
|
| | p2 = build_refactor_prompt(requirements_text, r1.output, diagram_context, self.ctx) |
| | r2 = self.refactor.run(p2) |
| |
|
| | p3 = build_critic_prompt(requirements_text, r2.output, diagram_context, self.ctx) |
| | r3 = self.critic.run(p3) |
| |
|
| | return RunTrace( |
| | task=self.ctx.name, |
| | input_requirements=requirements_text, |
| | diagram_context=diagram_context, |
| | analyzer=r1, |
| | refactor=r2, |
| | critic=r3, |
| | ) |
| |
|