Source code for sherpa_ai.agents.critic

from typing import List, Optional

from langchain_core.language_models import BaseChatModel
from loguru import logger

from sherpa_ai.agents.base import BaseAgent
from sherpa_ai.events import EventType
from sherpa_ai.memory import Belief, SharedMemory
from sherpa_ai.verbose_loggers.verbose_loggers import DummyVerboseLogger

DESCRIPTION_PROMPT = """
You are a Critic agent that receive a plan from the planner to execuate a task from user.
Your goal is to output the {} most necessary feedback given the corrent plan to solve the task.
"""  # noqa: E501
IMPORTANCE_PROMPT = """The plan you should be necessary and important to complete the task.
Evaluate if the content of plan and selected actions/ tools are important and necessary.
Output format:
Score: <Integer score from 1 - 10>
Evaluation: <evaluation in text>
Do not include other text in your resonse.
Output:
"""  # noqa: E501
DETAIL_PROMPT = """The plan you should be detailed enough to complete the task.
Evaluate if the content of plan and selected actions/ tools contains all the details the task needed.
Output format:
Score: <Integer score from 1 - 10>
Evaluation: <evaluation in text>
Do not include other text in your resonse.
Output:
"""  # noqa: E501
INSIGHT_PROMPT = """
What are the top 5 high-level insights you can infer from the all the memory you have?
Only output insights with high confidence.
Insight:
"""  # noqa: E501
FEEDBACK_PROMPT = """
What are the {} most important feedback for the plan received from the planner, using the\
insight you have from current observation, evaluation using the importance matrices and detail matrices.
Feedback:
"""  # noqa: E501


[docs] class Critic(BaseAgent): """ The critic agent receives a plan from the planner and evaluate the plan based on some pre-defined metrics. At the same time, it gives the feedback to the planner. """ name: str = "Critic" description: str = DESCRIPTION_PROMPT ratio: float = 0.9 num_feedback: int = 3
[docs] def get_importance_evaluation(self, task: str, plan: str): # return score in int and evaluation in string for importance matrix prompt = "Task: " + task + "\nPlan: " + plan + IMPORTANCE_PROMPT output = self.llm.predict(prompt) score = int(output.split("Score:")[1].split("Evaluation")[0]) evaluation = output.split("Evaluation: ")[1] return score, evaluation
[docs] def get_detail_evaluation(self, task: str, plan: str): # return score in int and evaluation in string for detail matrix prompt = "Task: " + task + "\nPlan: " + plan + DETAIL_PROMPT output = self.llm.predict(prompt) score = int(output.split("Score:")[1].split("Evaluation")[0]) evaluation = output.split("Evaluation: ")[1] return score, evaluation
[docs] def get_insight(self): # return a list of string: top 5 important insight given the belief and memory # (observation) observation = self.observe(self.belief) prompt = "Observation: " + observation + "\n" + INSIGHT_PROMPT result = self.llm.predict(prompt) insights = [i for i in result.split("\n") if len(i.strip()) > 0][:5] return insights
[docs] def post_process(self, feedback: str): return [i for i in feedback.split("\n") if i]
[docs] def get_feedback(self, task: str, plan: str) -> List[str]: # observation = self.observe(self.belief) i_score, i_evaluation = self.get_importance_evaluation(task, plan) d_score, d_evaluation = self.get_detail_evaluation(task, plan) # approve or not, check score/ ratio # insights = self.get_insight() logger.info(f"i_score: {i_score}, d_score: {d_score}") if i_score < 10 * self.ratio or d_score < 10 * self.ratio: prompt = ( # f"\nCurrent observation you have is: {observation}" # f"Insight you have from current observation: {insights}" f"Task: {task}" f"Evaluation in the importance matrices: {i_evaluation}" f"Evaluation in the detail matrices: {d_evaluation}" + FEEDBACK_PROMPT.format(self.num_feedback) ) feedback = self.llm.predict(self.description + prompt) self.shared_memory.add(EventType.feedback, self.name, feedback) logger.info(f"feedback: {feedback}") return self.post_process(feedback) else: return ""
[docs] def create_actions(self): pass
[docs] def synthesize_output(self) -> str: pass