33from __future__ import annotations
44
55import json
6+ import re
67from typing import Optional
78
89import structlog
@@ -22,8 +23,10 @@ class CriticAgent(BaseAgent):
2223 faithfulness, conciseness, readability, and aesthetic issues.
2324 """
2425
25- def __init__ (self , vlm_provider : VLMProvider , prompt_dir : str = "prompts" ):
26- super ().__init__ (vlm_provider , prompt_dir )
26+ def __init__ (
27+ self , vlm_provider : VLMProvider , prompt_dir : str = "prompts" , prompt_recorder = None
28+ ):
29+ super ().__init__ (vlm_provider , prompt_dir , prompt_recorder = prompt_recorder )
2730
2831 @property
2932 def agent_name (self ) -> str :
@@ -56,8 +59,9 @@ async def run(
5659
5760 prompt_type = "diagram" if diagram_type == DiagramType .METHODOLOGY else "plot"
5861 template = self .load_prompt (prompt_type )
59- prompt = self .format_prompt (
60- template ,
62+ prompt_label = self ._prompt_label_from_image_path (image_path ) or "critic"
63+ # Build prompt manually so we record once after appending user_feedback.
64+ prompt = template .format (
6165 source_context = source_context ,
6266 caption = caption ,
6367 description = description ,
@@ -68,6 +72,17 @@ async def run(
6872 f"\n \n Additional user feedback to consider in your evaluation:\n { user_feedback } "
6973 )
7074
75+ # Record the exact prompt sent to the model (including user_feedback in continue-run flows)
76+ if self ._prompt_recorder is not None :
77+ try :
78+ self ._prompt_recorder .record (
79+ agent_name = self .agent_name ,
80+ label = prompt_label ,
81+ prompt = prompt ,
82+ )
83+ except Exception :
84+ logger .warning ("Prompt recording failed" , agent = self .agent_name , label = prompt_label )
85+
7186 logger .info ("Running critic agent" , image_path = image_path )
7287
7388 response = await self .vlm .generate (
@@ -86,6 +101,14 @@ async def run(
86101 )
87102 return critique
88103
104+ @staticmethod
105+ def _prompt_label_from_image_path (image_path : str ) -> str | None :
106+ """Best-effort label (e.g. critic_iter_3) derived from output image filename."""
107+ m = re .search (r"(?:diagram|plot)_iter_(\d+)\." , image_path )
108+ if not m :
109+ return None
110+ return f"critic_iter_{ m .group (1 )} "
111+
89112 def _parse_response (self , response : str ) -> CritiqueResult :
90113 """Parse the VLM response into a CritiqueResult."""
91114 try :
0 commit comments