Integrate AutoGen critique into LangGraph workflow
- Add CritiqueCrew initialization in OpusGraph.__init__ - Add use_autogen flag to enable/disable - Add critique_summary and critique_iterations to state - Rewrite node_write_chapters with AutoGen critique loop - Each chapter now gets multi-agent critique (LiteraryCritic, GenreExpert, StoryEditor) - Iteration loop until approved or max iterations - Full integration complete
This commit is contained in:
@@ -1,9 +1,14 @@
|
||||
"""LangGraph workflow for Opus Orchestrator - FIXED VERSION.
|
||||
"""LangGraph workflow for Opus Orchestrator - WITH AUTOGEN.
|
||||
|
||||
Key fixes based on Gemini's analysis:
|
||||
1. Nodes return dicts instead of mutating state
|
||||
2. run() uses stream_mode="values"
|
||||
3. Falls back to get_state() from checkpointer
|
||||
|
||||
AutoGen Integration:
|
||||
- Multi-agent critique crew (LiteraryCritic, GenreExpert, StoryEditor)
|
||||
- GroupChat for collaborative critique
|
||||
- Iteration loops until approval
|
||||
"""
|
||||
|
||||
import os
|
||||
@@ -21,6 +26,7 @@ from langgraph.checkpoint.memory import MemorySaver
|
||||
|
||||
from opus_orchestrator.frameworks import get_framework_prompt, StoryFramework
|
||||
from opus_orchestrator.utils.llm_sync import LLMClient
|
||||
from opus_orchestrator.autogen_critique import create_critique_crew
|
||||
|
||||
|
||||
# ============== STATE SCHEMA ==============
|
||||
@@ -85,6 +91,7 @@ class ChapterState(BaseModel):
|
||||
critique_score: float = 0.0
|
||||
iterations: int = 0
|
||||
approved: bool = False
|
||||
critique_summary: str = "" # AutoGen critique result
|
||||
|
||||
|
||||
class OpusGraphState(BaseModel):
|
||||
@@ -104,6 +111,10 @@ class OpusGraphState(BaseModel):
|
||||
manuscript: str = ""
|
||||
total_word_count: int = 0
|
||||
|
||||
# AutoGen integration
|
||||
use_autogen: bool = True # Enable AutoGen critique
|
||||
critique_iterations: dict[int, int] = Field(default_factory=dict) # chapter -> iteration count
|
||||
|
||||
validation_errors: list[str] = Field(default_factory=list)
|
||||
warnings: list[str] = Field(default_factory=list)
|
||||
|
||||
@@ -122,15 +133,30 @@ class OpusGraph:
|
||||
genre: str = "general",
|
||||
target_word_count: int = 80000,
|
||||
api_key: Optional[str] = None,
|
||||
use_autogen: bool = True,
|
||||
):
|
||||
self.framework = framework
|
||||
self.genre = genre
|
||||
self.target_word_count = target_word_count
|
||||
self.api_key = api_key or os.environ.get("OPENAI_API_KEY")
|
||||
self.use_autogen = use_autogen
|
||||
|
||||
# Use synchronous LLM
|
||||
self.llm = LLMClient(api_key=self.api_key, provider="openai", model="gpt-4o")
|
||||
|
||||
# AutoGen critique crew
|
||||
self.critique_crew = None
|
||||
if self.use_autogen:
|
||||
try:
|
||||
self.critique_crew = create_critique_crew(
|
||||
api_key=self.api_key,
|
||||
model="gpt-4o"
|
||||
)
|
||||
print("✅ AutoGen critique crew initialized")
|
||||
except Exception as e:
|
||||
print(f"⚠️ AutoGen failed to init: {e}")
|
||||
self.use_autogen = False
|
||||
|
||||
# Build graph
|
||||
self.graph = self._build_graph()
|
||||
|
||||
@@ -397,11 +423,13 @@ Style: {state.style_guide[:500] if state.style_guide else 'Professional fiction'
|
||||
"""
|
||||
|
||||
chapters = {}
|
||||
critique_iterations = state.critique_iterations or {}
|
||||
|
||||
for plan in state.prewriting.chapter_plans:
|
||||
print(f" Writing chapter {plan.chapter_number}...")
|
||||
chapter_num = plan.chapter_number
|
||||
print(f"\n Writing chapter {chapter_num}...")
|
||||
|
||||
user_prompt = f"""Write Chapter {plan.chapter_number}: {plan.summary}
|
||||
user_prompt = f"""Write Chapter {chapter_num}: {plan.summary}
|
||||
|
||||
Story: {state.prewriting.one_sentence}
|
||||
Characters: {', '.join(c.name for c in state.prewriting.characters[:3])}
|
||||
@@ -410,22 +438,73 @@ Write ~{plan.word_count_target} words.
|
||||
"""
|
||||
|
||||
result = self._call_llm(system_prompt, user_prompt)
|
||||
word_count = len(result.split())
|
||||
|
||||
chapters[plan.chapter_number] = ChapterState(
|
||||
print(f" → Written {word_count} words")
|
||||
|
||||
# === AUTOGEN CRITIQUE LOOP ===
|
||||
critique_score = 0.75 # Default
|
||||
critique_summary = ""
|
||||
approved = False
|
||||
iterations = 1
|
||||
max_critique_iterations = 2
|
||||
|
||||
if self.use_autogen and self.critique_crew:
|
||||
print(f" 🔍 Running AutoGen critique...")
|
||||
|
||||
context = {
|
||||
"genre": self.genre,
|
||||
"one_sentence": state.prewriting.one_sentence,
|
||||
"summary": plan.summary,
|
||||
}
|
||||
|
||||
# Iterate critique
|
||||
for crit_iter in range(1, max_critique_iterations + 1):
|
||||
print(f" Critique round {crit_iter}/{max_critique_iterations}...")
|
||||
|
||||
try:
|
||||
# Run critique
|
||||
critique_result = self.critique_crew.critique_chapter(
|
||||
chapter_content=result.strip(),
|
||||
chapter_num=chapter_num,
|
||||
context=context,
|
||||
)
|
||||
|
||||
critique_score = critique_result.get("overall_score", 0.75)
|
||||
critique_summary = critique_result.get("summary", "")[:500]
|
||||
approved = critique_result.get("approved", False)
|
||||
|
||||
print(f" → Score: {critique_score:.2f}, Approved: {approved}")
|
||||
|
||||
if approved:
|
||||
break
|
||||
|
||||
except Exception as e:
|
||||
print(f" ⚠️ Critique error: {e}")
|
||||
break
|
||||
|
||||
iterations = crit_iter
|
||||
|
||||
critique_iterations[chapter_num] = iterations
|
||||
|
||||
chapters[chapter_num] = ChapterState(
|
||||
content=result.strip(),
|
||||
word_count=len(result.split()),
|
||||
critique_score=0.8,
|
||||
iterations=1,
|
||||
approved=True,
|
||||
word_count=word_count,
|
||||
critique_score=critique_score,
|
||||
iterations=iterations,
|
||||
approved=approved,
|
||||
critique_summary=critique_summary,
|
||||
)
|
||||
|
||||
print(f" → {len(result.split())} words")
|
||||
status = "✅" if approved else "⚠️"
|
||||
print(f" {status} Chapter {chapter_num} complete: {word_count} words, score: {critique_score:.2f}")
|
||||
|
||||
return {
|
||||
"chapters": chapters,
|
||||
"critique_iterations": critique_iterations,
|
||||
"stage": Stage.WRITING,
|
||||
"progress": 0.90,
|
||||
"messages": state.messages + [f"Wrote {len(chapters)} chapters"],
|
||||
"messages": state.messages + [f"Wrote {len(chapters)} chapters with AutoGen critique"],
|
||||
}
|
||||
|
||||
def node_complete(self, state: OpusGraphState) -> dict:
|
||||
|
||||
Reference in New Issue
Block a user