fast-agent-mcp 0.1.13__py3-none-any.whl → 0.2.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.
- {fast_agent_mcp-0.1.13.dist-info → fast_agent_mcp-0.2.0.dist-info}/METADATA +3 -4
- fast_agent_mcp-0.2.0.dist-info/RECORD +123 -0
- mcp_agent/__init__.py +75 -0
- mcp_agent/agents/agent.py +59 -371
- mcp_agent/agents/base_agent.py +522 -0
- mcp_agent/agents/workflow/__init__.py +1 -0
- mcp_agent/agents/workflow/chain_agent.py +173 -0
- mcp_agent/agents/workflow/evaluator_optimizer.py +362 -0
- mcp_agent/agents/workflow/orchestrator_agent.py +591 -0
- mcp_agent/{workflows/orchestrator → agents/workflow}/orchestrator_models.py +27 -11
- mcp_agent/agents/workflow/parallel_agent.py +182 -0
- mcp_agent/agents/workflow/router_agent.py +307 -0
- mcp_agent/app.py +3 -1
- mcp_agent/cli/commands/bootstrap.py +18 -7
- mcp_agent/cli/commands/setup.py +12 -4
- mcp_agent/cli/main.py +1 -1
- mcp_agent/cli/terminal.py +1 -1
- mcp_agent/config.py +24 -35
- mcp_agent/context.py +3 -1
- mcp_agent/context_dependent.py +3 -1
- mcp_agent/core/agent_types.py +10 -7
- mcp_agent/core/direct_agent_app.py +179 -0
- mcp_agent/core/direct_decorators.py +443 -0
- mcp_agent/core/direct_factory.py +476 -0
- mcp_agent/core/enhanced_prompt.py +15 -20
- mcp_agent/core/fastagent.py +151 -337
- mcp_agent/core/interactive_prompt.py +424 -0
- mcp_agent/core/mcp_content.py +19 -11
- mcp_agent/core/prompt.py +6 -2
- mcp_agent/core/validation.py +89 -16
- mcp_agent/executor/decorator_registry.py +6 -2
- mcp_agent/executor/temporal.py +35 -11
- mcp_agent/executor/workflow_signal.py +8 -2
- mcp_agent/human_input/handler.py +3 -1
- mcp_agent/llm/__init__.py +2 -0
- mcp_agent/{workflows/llm → llm}/augmented_llm.py +131 -256
- mcp_agent/{workflows/llm → llm}/augmented_llm_passthrough.py +35 -107
- mcp_agent/llm/augmented_llm_playback.py +83 -0
- mcp_agent/{workflows/llm → llm}/model_factory.py +26 -8
- mcp_agent/llm/providers/__init__.py +8 -0
- mcp_agent/{workflows/llm → llm/providers}/anthropic_utils.py +5 -1
- mcp_agent/{workflows/llm → llm/providers}/augmented_llm_anthropic.py +37 -141
- mcp_agent/llm/providers/augmented_llm_deepseek.py +53 -0
- mcp_agent/{workflows/llm → llm/providers}/augmented_llm_openai.py +112 -148
- mcp_agent/{workflows/llm → llm}/providers/multipart_converter_anthropic.py +78 -35
- mcp_agent/{workflows/llm → llm}/providers/multipart_converter_openai.py +73 -44
- mcp_agent/{workflows/llm → llm}/providers/openai_multipart.py +18 -4
- mcp_agent/{workflows/llm → llm/providers}/openai_utils.py +3 -3
- mcp_agent/{workflows/llm → llm}/providers/sampling_converter_anthropic.py +3 -3
- mcp_agent/{workflows/llm → llm}/providers/sampling_converter_openai.py +3 -3
- mcp_agent/{workflows/llm → llm}/sampling_converter.py +0 -21
- mcp_agent/{workflows/llm → llm}/sampling_format_converter.py +16 -1
- mcp_agent/logging/logger.py +2 -2
- mcp_agent/mcp/gen_client.py +9 -3
- mcp_agent/mcp/interfaces.py +67 -45
- mcp_agent/mcp/logger_textio.py +97 -0
- mcp_agent/mcp/mcp_agent_client_session.py +12 -4
- mcp_agent/mcp/mcp_agent_server.py +3 -1
- mcp_agent/mcp/mcp_aggregator.py +124 -93
- mcp_agent/mcp/mcp_connection_manager.py +21 -7
- mcp_agent/mcp/prompt_message_multipart.py +59 -1
- mcp_agent/mcp/prompt_render.py +77 -0
- mcp_agent/mcp/prompt_serialization.py +20 -13
- mcp_agent/mcp/prompts/prompt_constants.py +18 -0
- mcp_agent/mcp/prompts/prompt_helpers.py +327 -0
- mcp_agent/mcp/prompts/prompt_load.py +15 -5
- mcp_agent/mcp/prompts/prompt_server.py +154 -87
- mcp_agent/mcp/prompts/prompt_template.py +26 -35
- mcp_agent/mcp/resource_utils.py +3 -1
- mcp_agent/mcp/sampling.py +24 -15
- mcp_agent/mcp_server/agent_server.py +8 -5
- mcp_agent/mcp_server_registry.py +22 -9
- mcp_agent/resources/examples/{workflows → in_dev}/agent_build.py +1 -1
- mcp_agent/resources/examples/{data-analysis → in_dev}/slides.py +1 -1
- mcp_agent/resources/examples/internal/agent.py +4 -2
- mcp_agent/resources/examples/internal/fastagent.config.yaml +8 -2
- mcp_agent/resources/examples/prompting/image_server.py +3 -1
- mcp_agent/resources/examples/prompting/work_with_image.py +19 -0
- mcp_agent/ui/console_display.py +27 -7
- fast_agent_mcp-0.1.13.dist-info/RECORD +0 -164
- mcp_agent/core/agent_app.py +0 -570
- mcp_agent/core/agent_utils.py +0 -69
- mcp_agent/core/decorators.py +0 -448
- mcp_agent/core/factory.py +0 -422
- mcp_agent/core/proxies.py +0 -278
- mcp_agent/core/types.py +0 -22
- mcp_agent/eval/__init__.py +0 -0
- mcp_agent/mcp/stdio.py +0 -114
- mcp_agent/resources/examples/data-analysis/analysis-campaign.py +0 -188
- mcp_agent/resources/examples/data-analysis/analysis.py +0 -65
- mcp_agent/resources/examples/data-analysis/fastagent.config.yaml +0 -41
- mcp_agent/resources/examples/data-analysis/mount-point/WA_Fn-UseC_-HR-Employee-Attrition.csv +0 -1471
- mcp_agent/resources/examples/mcp_researcher/researcher-eval.py +0 -53
- mcp_agent/resources/examples/researcher/fastagent.config.yaml +0 -66
- mcp_agent/resources/examples/researcher/researcher-eval.py +0 -53
- mcp_agent/resources/examples/researcher/researcher-imp.py +0 -189
- mcp_agent/resources/examples/researcher/researcher.py +0 -39
- mcp_agent/resources/examples/workflows/chaining.py +0 -45
- mcp_agent/resources/examples/workflows/evaluator.py +0 -79
- mcp_agent/resources/examples/workflows/fastagent.config.yaml +0 -24
- mcp_agent/resources/examples/workflows/human_input.py +0 -26
- mcp_agent/resources/examples/workflows/orchestrator.py +0 -74
- mcp_agent/resources/examples/workflows/parallel.py +0 -79
- mcp_agent/resources/examples/workflows/router.py +0 -54
- mcp_agent/resources/examples/workflows/sse.py +0 -23
- mcp_agent/telemetry/__init__.py +0 -0
- mcp_agent/telemetry/usage_tracking.py +0 -19
- mcp_agent/workflows/__init__.py +0 -0
- mcp_agent/workflows/embedding/__init__.py +0 -0
- mcp_agent/workflows/embedding/embedding_base.py +0 -58
- mcp_agent/workflows/embedding/embedding_cohere.py +0 -49
- mcp_agent/workflows/embedding/embedding_openai.py +0 -37
- mcp_agent/workflows/evaluator_optimizer/__init__.py +0 -0
- mcp_agent/workflows/evaluator_optimizer/evaluator_optimizer.py +0 -447
- mcp_agent/workflows/intent_classifier/__init__.py +0 -0
- mcp_agent/workflows/intent_classifier/intent_classifier_base.py +0 -117
- mcp_agent/workflows/intent_classifier/intent_classifier_embedding.py +0 -130
- mcp_agent/workflows/intent_classifier/intent_classifier_embedding_cohere.py +0 -41
- mcp_agent/workflows/intent_classifier/intent_classifier_embedding_openai.py +0 -41
- mcp_agent/workflows/intent_classifier/intent_classifier_llm.py +0 -150
- mcp_agent/workflows/intent_classifier/intent_classifier_llm_anthropic.py +0 -60
- mcp_agent/workflows/intent_classifier/intent_classifier_llm_openai.py +0 -58
- mcp_agent/workflows/llm/__init__.py +0 -0
- mcp_agent/workflows/llm/augmented_llm_playback.py +0 -111
- mcp_agent/workflows/llm/providers/__init__.py +0 -8
- mcp_agent/workflows/orchestrator/__init__.py +0 -0
- mcp_agent/workflows/orchestrator/orchestrator.py +0 -535
- mcp_agent/workflows/parallel/__init__.py +0 -0
- mcp_agent/workflows/parallel/fan_in.py +0 -320
- mcp_agent/workflows/parallel/fan_out.py +0 -181
- mcp_agent/workflows/parallel/parallel_llm.py +0 -149
- mcp_agent/workflows/router/__init__.py +0 -0
- mcp_agent/workflows/router/router_base.py +0 -338
- mcp_agent/workflows/router/router_embedding.py +0 -226
- mcp_agent/workflows/router/router_embedding_cohere.py +0 -59
- mcp_agent/workflows/router/router_embedding_openai.py +0 -59
- mcp_agent/workflows/router/router_llm.py +0 -304
- mcp_agent/workflows/swarm/__init__.py +0 -0
- mcp_agent/workflows/swarm/swarm.py +0 -292
- mcp_agent/workflows/swarm/swarm_anthropic.py +0 -42
- mcp_agent/workflows/swarm/swarm_openai.py +0 -41
- {fast_agent_mcp-0.1.13.dist-info → fast_agent_mcp-0.2.0.dist-info}/WHEEL +0 -0
- {fast_agent_mcp-0.1.13.dist-info → fast_agent_mcp-0.2.0.dist-info}/entry_points.txt +0 -0
- {fast_agent_mcp-0.1.13.dist-info → fast_agent_mcp-0.2.0.dist-info}/licenses/LICENSE +0 -0
- /mcp_agent/{workflows/orchestrator → agents/workflow}/orchestrator_prompts.py +0 -0
- /mcp_agent/{workflows/llm → llm}/memory.py +0 -0
- /mcp_agent/{workflows/llm → llm}/prompt_utils.py +0 -0
@@ -0,0 +1,362 @@
|
|
1
|
+
"""
|
2
|
+
Evaluator-Optimizer workflow implementation using the BaseAgent adapter pattern.
|
3
|
+
|
4
|
+
This workflow provides a mechanism for iterative refinement of responses through
|
5
|
+
evaluation and feedback cycles. It uses one agent to generate responses and another
|
6
|
+
to evaluate and provide feedback, continuing until a quality threshold is reached
|
7
|
+
or a maximum number of refinements is attempted.
|
8
|
+
"""
|
9
|
+
|
10
|
+
from enum import Enum
|
11
|
+
from typing import Any, List, Optional, Type
|
12
|
+
|
13
|
+
from pydantic import BaseModel, Field
|
14
|
+
|
15
|
+
from mcp_agent.agents.agent import Agent
|
16
|
+
from mcp_agent.agents.base_agent import BaseAgent
|
17
|
+
from mcp_agent.core.exceptions import AgentConfigError
|
18
|
+
from mcp_agent.core.prompt import Prompt
|
19
|
+
from mcp_agent.core.request_params import RequestParams
|
20
|
+
from mcp_agent.logging.logger import get_logger
|
21
|
+
from mcp_agent.mcp.interfaces import ModelT
|
22
|
+
from mcp_agent.mcp.prompt_message_multipart import PromptMessageMultipart
|
23
|
+
|
24
|
+
logger = get_logger(__name__)
|
25
|
+
|
26
|
+
|
27
|
+
class QualityRating(str, Enum):
|
28
|
+
"""Enum for evaluation quality ratings."""
|
29
|
+
|
30
|
+
POOR = "POOR" # Major improvements needed
|
31
|
+
FAIR = "FAIR" # Several improvements needed
|
32
|
+
GOOD = "GOOD" # Minor improvements possible
|
33
|
+
EXCELLENT = "EXCELLENT" # No improvements needed
|
34
|
+
|
35
|
+
# Map string values to integer values for comparisons
|
36
|
+
@property
|
37
|
+
def value(self) -> int:
|
38
|
+
"""Convert string enum values to integers for comparison."""
|
39
|
+
return {
|
40
|
+
"POOR": 0,
|
41
|
+
"FAIR": 1,
|
42
|
+
"GOOD": 2,
|
43
|
+
"EXCELLENT": 3,
|
44
|
+
}[self._value_]
|
45
|
+
|
46
|
+
|
47
|
+
class EvaluationResult(BaseModel):
|
48
|
+
"""Model representing the evaluation result from the evaluator agent."""
|
49
|
+
|
50
|
+
rating: QualityRating = Field(description="Quality rating of the response")
|
51
|
+
feedback: str = Field(description="Specific feedback and suggestions for improvement")
|
52
|
+
needs_improvement: bool = Field(description="Whether the output needs further improvement")
|
53
|
+
focus_areas: List[str] = Field(
|
54
|
+
default_factory=list, description="Specific areas to focus on in next iteration"
|
55
|
+
)
|
56
|
+
|
57
|
+
|
58
|
+
class EvaluatorOptimizerAgent(BaseAgent):
|
59
|
+
"""
|
60
|
+
An agent that implements the evaluator-optimizer workflow pattern.
|
61
|
+
|
62
|
+
Uses one agent to generate responses and another to evaluate and provide feedback
|
63
|
+
for refinement, continuing until a quality threshold is reached or a maximum
|
64
|
+
number of refinement cycles is completed.
|
65
|
+
"""
|
66
|
+
|
67
|
+
def __init__(
|
68
|
+
self,
|
69
|
+
config: Agent,
|
70
|
+
generator_agent: Agent,
|
71
|
+
evaluator_agent: Agent,
|
72
|
+
min_rating: QualityRating = QualityRating.GOOD,
|
73
|
+
max_refinements: int = 3,
|
74
|
+
context: Optional[Any] = None,
|
75
|
+
**kwargs,
|
76
|
+
) -> None:
|
77
|
+
"""
|
78
|
+
Initialize the evaluator-optimizer agent.
|
79
|
+
|
80
|
+
Args:
|
81
|
+
config: Agent configuration or name
|
82
|
+
generator_agent: Agent that generates the initial and refined responses
|
83
|
+
evaluator_agent: Agent that evaluates responses and provides feedback
|
84
|
+
min_rating: Minimum acceptable quality rating to stop refinement
|
85
|
+
max_refinements: Maximum number of refinement cycles to attempt
|
86
|
+
context: Optional context object
|
87
|
+
**kwargs: Additional keyword arguments to pass to BaseAgent
|
88
|
+
"""
|
89
|
+
super().__init__(config, context=context, **kwargs)
|
90
|
+
|
91
|
+
if not generator_agent:
|
92
|
+
raise AgentConfigError("Generator agent must be provided")
|
93
|
+
|
94
|
+
if not evaluator_agent:
|
95
|
+
raise AgentConfigError("Evaluator agent must be provided")
|
96
|
+
|
97
|
+
self.generator_agent = generator_agent
|
98
|
+
self.evaluator_agent = evaluator_agent
|
99
|
+
self.min_rating = min_rating
|
100
|
+
self.max_refinements = max_refinements
|
101
|
+
self.refinement_history = []
|
102
|
+
|
103
|
+
async def generate(
|
104
|
+
self,
|
105
|
+
multipart_messages: List[PromptMessageMultipart],
|
106
|
+
request_params: Optional[RequestParams] = None,
|
107
|
+
) -> PromptMessageMultipart:
|
108
|
+
"""
|
109
|
+
Generate a response through evaluation-guided refinement.
|
110
|
+
|
111
|
+
Args:
|
112
|
+
multipart_messages: Messages to process
|
113
|
+
request_params: Optional request parameters
|
114
|
+
|
115
|
+
Returns:
|
116
|
+
The optimized response after evaluation and refinement
|
117
|
+
"""
|
118
|
+
# Initialize tracking variables
|
119
|
+
refinement_count = 0
|
120
|
+
best_response = None
|
121
|
+
best_rating = QualityRating.POOR
|
122
|
+
self.refinement_history = []
|
123
|
+
|
124
|
+
# Extract the user request
|
125
|
+
request = multipart_messages[-1].all_text() if multipart_messages else ""
|
126
|
+
|
127
|
+
# Initial generation
|
128
|
+
response = await self.generator_agent.generate(multipart_messages, request_params)
|
129
|
+
best_response = response
|
130
|
+
|
131
|
+
# Refinement loop
|
132
|
+
while refinement_count < self.max_refinements:
|
133
|
+
logger.debug(f"Evaluating response (iteration {refinement_count + 1})")
|
134
|
+
|
135
|
+
# Evaluate current response
|
136
|
+
eval_prompt = self._build_eval_prompt(
|
137
|
+
request=request, response=response.all_text(), iteration=refinement_count
|
138
|
+
)
|
139
|
+
|
140
|
+
# Create evaluation message and get structured evaluation result
|
141
|
+
eval_message = Prompt.user(eval_prompt)
|
142
|
+
evaluation_result = await self.evaluator_agent.structured(
|
143
|
+
[eval_message], EvaluationResult, request_params
|
144
|
+
)
|
145
|
+
|
146
|
+
# If structured parsing failed, use default evaluation
|
147
|
+
if evaluation_result is None:
|
148
|
+
logger.warning("Structured parsing failed, using default evaluation")
|
149
|
+
evaluation_result = EvaluationResult(
|
150
|
+
rating=QualityRating.POOR,
|
151
|
+
feedback="Failed to parse evaluation",
|
152
|
+
needs_improvement=True,
|
153
|
+
focus_areas=["Improve overall quality"],
|
154
|
+
)
|
155
|
+
|
156
|
+
# Track iteration
|
157
|
+
self.refinement_history.append(
|
158
|
+
{
|
159
|
+
"attempt": refinement_count + 1,
|
160
|
+
"response": response.all_text(),
|
161
|
+
"evaluation": evaluation_result.model_dump(),
|
162
|
+
}
|
163
|
+
)
|
164
|
+
|
165
|
+
logger.debug(f"Evaluation result: {evaluation_result.rating}")
|
166
|
+
|
167
|
+
# Track best response based on rating
|
168
|
+
if evaluation_result.rating.value > best_rating.value:
|
169
|
+
best_rating = evaluation_result.rating
|
170
|
+
best_response = response
|
171
|
+
logger.debug(f"New best response (rating: {best_rating})")
|
172
|
+
|
173
|
+
# Check if we've reached acceptable quality
|
174
|
+
if not evaluation_result.needs_improvement:
|
175
|
+
logger.debug("Improvement not needed, stopping refinement")
|
176
|
+
# When evaluator says no improvement needed, use the current response
|
177
|
+
best_response = response
|
178
|
+
break
|
179
|
+
|
180
|
+
if evaluation_result.rating.value >= self.min_rating.value:
|
181
|
+
logger.debug(f"Acceptable quality reached ({evaluation_result.rating})")
|
182
|
+
break
|
183
|
+
|
184
|
+
# Generate refined response
|
185
|
+
refinement_prompt = self._build_refinement_prompt(
|
186
|
+
request=request,
|
187
|
+
response=response.all_text(),
|
188
|
+
feedback=evaluation_result,
|
189
|
+
iteration=refinement_count,
|
190
|
+
)
|
191
|
+
|
192
|
+
# Create refinement message and get refined response
|
193
|
+
refinement_message = Prompt.user(refinement_prompt)
|
194
|
+
response = await self.generator_agent.generate([refinement_message], request_params)
|
195
|
+
|
196
|
+
refinement_count += 1
|
197
|
+
|
198
|
+
return best_response
|
199
|
+
|
200
|
+
async def structured(
|
201
|
+
self,
|
202
|
+
prompt: List[PromptMessageMultipart],
|
203
|
+
model: Type[ModelT],
|
204
|
+
request_params: Optional[RequestParams] = None,
|
205
|
+
) -> Optional[ModelT]:
|
206
|
+
"""
|
207
|
+
Generate an optimized response and parse it into a structured format.
|
208
|
+
|
209
|
+
Args:
|
210
|
+
prompt: List of messages to process
|
211
|
+
model: Pydantic model to parse the response into
|
212
|
+
request_params: Optional request parameters
|
213
|
+
|
214
|
+
Returns:
|
215
|
+
The parsed response, or None if parsing fails
|
216
|
+
"""
|
217
|
+
# Generate optimized response
|
218
|
+
response = await self.generate(prompt, request_params)
|
219
|
+
|
220
|
+
# Delegate structured parsing to the generator agent
|
221
|
+
structured_prompt = Prompt.user(response.all_text())
|
222
|
+
return await self.generator_agent.structured([structured_prompt], model, request_params)
|
223
|
+
|
224
|
+
async def initialize(self) -> None:
|
225
|
+
"""Initialize the agent and its generator and evaluator agents."""
|
226
|
+
await super().initialize()
|
227
|
+
|
228
|
+
# Initialize generator and evaluator agents if not already initialized
|
229
|
+
if not getattr(self.generator_agent, "initialized", False):
|
230
|
+
await self.generator_agent.initialize()
|
231
|
+
|
232
|
+
if not getattr(self.evaluator_agent, "initialized", False):
|
233
|
+
await self.evaluator_agent.initialize()
|
234
|
+
|
235
|
+
self.initialized = True
|
236
|
+
|
237
|
+
async def shutdown(self) -> None:
|
238
|
+
"""Shutdown the agent and its generator and evaluator agents."""
|
239
|
+
await super().shutdown()
|
240
|
+
|
241
|
+
# Shutdown generator and evaluator agents
|
242
|
+
try:
|
243
|
+
await self.generator_agent.shutdown()
|
244
|
+
except Exception as e:
|
245
|
+
logger.warning(f"Error shutting down generator agent: {str(e)}")
|
246
|
+
|
247
|
+
try:
|
248
|
+
await self.evaluator_agent.shutdown()
|
249
|
+
except Exception as e:
|
250
|
+
logger.warning(f"Error shutting down evaluator agent: {str(e)}")
|
251
|
+
|
252
|
+
def _build_eval_prompt(self, request: str, response: str, iteration: int) -> str:
|
253
|
+
"""
|
254
|
+
Build the evaluation prompt for the evaluator agent.
|
255
|
+
|
256
|
+
Args:
|
257
|
+
request: The original user request
|
258
|
+
response: The current response to evaluate
|
259
|
+
iteration: The current iteration number
|
260
|
+
|
261
|
+
Returns:
|
262
|
+
Formatted evaluation prompt
|
263
|
+
"""
|
264
|
+
return f"""
|
265
|
+
You are an expert evaluator for content quality. Your task is to evaluate a response against the user's original request.
|
266
|
+
|
267
|
+
Evaluate the response for iteration {iteration + 1} and provide structured feedback on its quality and areas for improvement.
|
268
|
+
|
269
|
+
<fastagent:data>
|
270
|
+
<fastagent:request>
|
271
|
+
{request}
|
272
|
+
</fastagent:request>
|
273
|
+
|
274
|
+
<fastagent:response>
|
275
|
+
{response}
|
276
|
+
</fastagent:response>
|
277
|
+
</fastagent:data>
|
278
|
+
|
279
|
+
<fastagent:instruction>
|
280
|
+
Your response MUST be valid JSON matching this exact format (no other text, markdown, or explanation):
|
281
|
+
|
282
|
+
{{
|
283
|
+
"rating": "RATING",
|
284
|
+
"feedback": "DETAILED FEEDBACK",
|
285
|
+
"needs_improvement": BOOLEAN,
|
286
|
+
"focus_areas": ["FOCUS_AREA_1", "FOCUS_AREA_2", "FOCUS_AREA_3"]
|
287
|
+
}}
|
288
|
+
|
289
|
+
Where:
|
290
|
+
- RATING: Must be one of: "EXCELLENT", "GOOD", "FAIR", or "POOR"
|
291
|
+
- EXCELLENT: No improvements needed
|
292
|
+
- GOOD: Only minor improvements possible
|
293
|
+
- FAIR: Several improvements needed
|
294
|
+
- POOR: Major improvements needed
|
295
|
+
- DETAILED FEEDBACK: Specific, actionable feedback (as a single string)
|
296
|
+
- BOOLEAN: true or false (lowercase, no quotes) indicating if further improvement is needed
|
297
|
+
- FOCUS_AREAS: Array of 1-3 specific areas to focus on (empty array if no improvement needed)
|
298
|
+
|
299
|
+
Example of valid response (DO NOT include the triple backticks in your response):
|
300
|
+
{{
|
301
|
+
"rating": "GOOD",
|
302
|
+
"feedback": "The response is clear but could use more supporting evidence.",
|
303
|
+
"needs_improvement": true,
|
304
|
+
"focus_areas": ["Add more examples", "Include data points"]
|
305
|
+
}}
|
306
|
+
|
307
|
+
IMPORTANT: Your response should be ONLY the JSON object without any code fences, explanations, or other text.
|
308
|
+
</fastagent:instruction>
|
309
|
+
"""
|
310
|
+
|
311
|
+
def _build_refinement_prompt(
|
312
|
+
self,
|
313
|
+
request: str,
|
314
|
+
response: str,
|
315
|
+
feedback: EvaluationResult,
|
316
|
+
iteration: int,
|
317
|
+
) -> str:
|
318
|
+
"""
|
319
|
+
Build the refinement prompt for the generator agent.
|
320
|
+
|
321
|
+
Args:
|
322
|
+
request: The original user request
|
323
|
+
response: The current response to refine
|
324
|
+
feedback: The evaluation feedback
|
325
|
+
iteration: The current iteration number
|
326
|
+
|
327
|
+
Returns:
|
328
|
+
Formatted refinement prompt
|
329
|
+
"""
|
330
|
+
focus_areas = ", ".join(feedback.focus_areas) if feedback.focus_areas else "None specified"
|
331
|
+
|
332
|
+
return f"""
|
333
|
+
You are tasked with improving a response based on expert feedback. This is iteration {iteration + 1} of the refinement process.
|
334
|
+
|
335
|
+
Your goal is to address all feedback points while maintaining accuracy and relevance to the original request.
|
336
|
+
|
337
|
+
<fastagent:data>
|
338
|
+
<fastagent:request>
|
339
|
+
{request}
|
340
|
+
</fastagent:request>
|
341
|
+
|
342
|
+
<fastagent:previous-response>
|
343
|
+
{response}
|
344
|
+
</fastagent:previous-response>
|
345
|
+
|
346
|
+
<fastagent:feedback>
|
347
|
+
<rating>{feedback.rating}</rating>
|
348
|
+
<details>{feedback.feedback}</details>
|
349
|
+
<focus-areas>{focus_areas}</focus-areas>
|
350
|
+
</fastagent:feedback>
|
351
|
+
</fastagent:data>
|
352
|
+
|
353
|
+
<fastagent:instruction>
|
354
|
+
Create an improved version of the response that:
|
355
|
+
1. Directly addresses each point in the feedback
|
356
|
+
2. Focuses on the specific areas mentioned for improvement
|
357
|
+
3. Maintains all the strengths of the original response
|
358
|
+
4. Remains accurate and relevant to the original request
|
359
|
+
|
360
|
+
Provide your complete improved response without explanations or commentary.
|
361
|
+
</fastagent:instruction>
|
362
|
+
"""
|