mirror of
https://github.com/aymenfurter/microagents.git
synced 2023-12-30 16:47:11 +03:00
feat: add readme
This commit is contained in:
50
README.md
50
README.md
@@ -1 +1,49 @@
|
||||
# microagent
|
||||
# Microagents: Modular Agents Capable of Self-Editing and Enhancing Their Prompts and Python code
|
||||
|
||||

|
||||
|
||||
## Overview
|
||||
This experiment explores self-evolving agents that automatically generate and improve themselves to answer a variety of questions. No specific agent design or prompting is required from the user. Simply pose a question, and the system initiates and evolves agents tailored to provide answers. Microagents are designed for reuse and can learn from past mistakes to enhance their future performance.
|
||||
|
||||
## Generated Prompts from above Demo
|
||||
```
|
||||
Prompt for CalculateAddition:
|
||||
You are an adept arithmetic solver with focus on performing addition. Utilize this Python function to calculate the sum of two numbers:
|
||||
|
||||
``python
|
||||
def calculate_addition(num1, num2):
|
||||
return num1 + num2
|
||||
|
||||
# Example usage:
|
||||
print(calculate_addition(5, 9))
|
||||
``
|
||||
|
||||
Prompt for GetPopulationOfCountry:
|
||||
You are a skilled data extractor specializing in population statistics. Retrieve the population of a given country using the provided Python code:
|
||||
|
||||
``python
|
||||
import requests
|
||||
|
||||
def get_population(country):
|
||||
url = f"https://restcountries.com/v3.1/name/{country}"
|
||||
response = requests.get(url).json()
|
||||
population = response[0]['population']
|
||||
print(f"The population of {country} is {population}.")
|
||||
|
||||
# Example usage:
|
||||
get_population("CountryName")
|
||||
``
|
||||
|
||||
```
|
||||
|
||||
## Current Challenges and Potential Improvements
|
||||
|
||||
1. **Path Optimization**: The system sometimes fails to effectively discard non-functional evolutionary paths. Improving this mechanism is essential for more reliable results.
|
||||
|
||||
2. **Performance and Parallelization**: Currently, parallel processing is not implemented. Enabling the testing of multiple prompt evolutions simultaneously could significantly enhance performance.
|
||||
|
||||
3. **Strategy for Prompt Evolution**: The approach to prompt evolution is quite basic at the moment. Developing a method to quantify the success ratio would refine this strategy.
|
||||
|
||||
4. **Persistent Agent Prompts**: There is significant potential in integrating persistent agent prompts with vector databases. Additionally, sharing successful agents across various runtime environments could improve overall efficiency.
|
||||
|
||||
5. **Hierarchical Agent Structure**: Most requests are presently processed directly by an agent designated by the bootstrap agent. Implementing a more intricate hierarchical structure for managing requests could lead to major improvements.
|
||||
|
||||
@@ -25,7 +25,7 @@ class AgentCreation:
|
||||
"""
|
||||
prime_agent = MicroAgent(
|
||||
PRIME_PROMPT, PRIME_NAME, 0, self,
|
||||
self.openai_wrapper, PRIME_AGENT_WEIGHT, True
|
||||
self.openai_wrapper, PRIME_AGENT_WEIGHT, True, True
|
||||
)
|
||||
self.agents.append(prime_agent)
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import logging
|
||||
from integrations.openaiwrapper import OpenAIAPIWrapper
|
||||
from prompt_management.prompts import (
|
||||
REACT_STEP_POST, REACT_STEP_PROMPT, REACT_SYSTEM_PROMPT, REACT_PLAN_PROMPT, STATIC_PRE_PROMPT
|
||||
REACT_STEP_POST, REACT_STEP_PROMPT, REACT_SYSTEM_PROMPT, REACT_PLAN_PROMPT, STATIC_PRE_PROMPT, STATIC_PRE_PROMPT_PRIME, REACT_STEP_PROMPT_PRIME, REACT_STEP_POST_PRIME
|
||||
)
|
||||
|
||||
logging.basicConfig(level=logging.ERROR, format='%(asctime)s - %(levelname)s - %(message)s')
|
||||
@@ -39,19 +39,22 @@ class AgentResponse:
|
||||
return self._conclude_output(conversation_accumulator), conversation_accumulator, found_new_solution, thought_number
|
||||
|
||||
def _compose_system_prompt(self, runtime_context, dynamic_prompt):
|
||||
return STATIC_PRE_PROMPT + runtime_context + dynamic_prompt + "\nDELIVER THE NEXT PACKAGE."
|
||||
pre_prompt = STATIC_PRE_PROMPT_PRIME if self.agent.is_prime else STATIC_PRE_PROMPT
|
||||
return pre_prompt + runtime_context + dynamic_prompt + "\nDELIVER THE NEXT PACKAGE."
|
||||
|
||||
def _generate_runtime_context(self, dynamic_prompt):
|
||||
available_agents = [agent for agent in self.manager.agents if agent.purpose != "General"]
|
||||
available_agents = [agent for agent in self.manager.agents if agent.purpose != "Bootstrap Agent"]
|
||||
available_agents_info = ', '.join([f"{agent.purpose} (depth={agent.depth})" for agent in available_agents])
|
||||
return f"Your Purpose: {dynamic_prompt}. Available agents: {available_agents_info}."
|
||||
return f"Your Purpose: {dynamic_prompt}. Available agents (Feel free to invent new ones if required!): {available_agents_info}."
|
||||
|
||||
def _build_react_prompt(self, input_text, conversation_accumulator, thought_number, action_number):
|
||||
thought_prompt = REACT_STEP_PROMPT_PRIME if self.agent.is_prime else REACT_STEP_PROMPT
|
||||
action_prompt = REACT_STEP_POST_PRIME if self.agent.is_prime else REACT_STEP_POST
|
||||
return (
|
||||
f"Question: {input_text}\n"
|
||||
f"{conversation_accumulator}\n"
|
||||
f"Thought {thought_number}: {REACT_STEP_PROMPT}\n"
|
||||
f"Action {action_number}: {REACT_STEP_POST}"
|
||||
f"Thought {thought_number}: {thought_prompt}\n"
|
||||
f"Action {action_number}: {action_prompt}"
|
||||
)
|
||||
|
||||
def _generate_chat_response(self, system_prompt, react_prompt):
|
||||
@@ -70,6 +73,7 @@ class AgentResponse:
|
||||
|
||||
if "```python" in response:
|
||||
self.agent.update_status('Executing Python code')
|
||||
self.agent.number_of_code_executions += 1
|
||||
exec_response = self.code_execution.execute_external_code(response)
|
||||
conversation_accumulator += f"\nObservation: Executed Python code\nOutput: {exec_response}"
|
||||
|
||||
@@ -90,6 +94,7 @@ class AgentResponse:
|
||||
|
||||
def _conclude_output(self, conversation):
|
||||
react_prompt = conversation
|
||||
|
||||
self.agent.update_status('Reviewing output')
|
||||
return self.openai_wrapper.chat_completion(
|
||||
model="gpt-4-1106-preview",
|
||||
|
||||
@@ -37,20 +37,21 @@ class AgentSimilarity:
|
||||
|
||||
def calculate_similarity_threshold(self) -> float:
|
||||
"""
|
||||
Calculates the average similarity threshold across all agents.
|
||||
Calculates the 98th percentile of the similarity threshold across all agents.
|
||||
|
||||
:return: Average similarity threshold.
|
||||
:return: 98th percentile of similarity threshold.
|
||||
"""
|
||||
try:
|
||||
embeddings = [self.get_embedding(agent.purpose) for agent in self.agents]
|
||||
if len(embeddings) < 2:
|
||||
if len(embeddings) < 250:
|
||||
return 0.9
|
||||
|
||||
similarities = [cosine_similarity([e1], [e2])[0][0] for i, e1 in enumerate(embeddings) for e2 in embeddings[i+1:]]
|
||||
return np.mean(similarities) if similarities else 0.9
|
||||
return np.percentile(similarities, 98) if similarities else 0.9
|
||||
except Exception as e:
|
||||
raise ValueError(f"Error calculating similarity threshold: {e}")
|
||||
|
||||
|
||||
def find_closest_agent(self, purpose_embedding: np.ndarray) -> Tuple[Optional[Agent], float]:
|
||||
"""
|
||||
Finds the closest agent based on the given purpose embedding.
|
||||
|
||||
@@ -16,7 +16,7 @@ class MicroAgent:
|
||||
that interacts with the OpenAI API.
|
||||
"""
|
||||
|
||||
def __init__(self, initial_prompt, purpose, depth, agent_creator, openai_wrapper, max_depth=3, bootstrap_agent=False):
|
||||
def __init__(self, initial_prompt, purpose, depth, agent_creator, openai_wrapper, max_depth=3, bootstrap_agent=False, is_prime=False):
|
||||
self.dynamic_prompt = initial_prompt
|
||||
self.purpose = purpose
|
||||
self.depth = depth
|
||||
@@ -26,8 +26,11 @@ class MicroAgent:
|
||||
self.agent_creator = agent_creator
|
||||
self.openai_wrapper = openai_wrapper
|
||||
self.evolve_count = 0 # Track how often the agent has evolved
|
||||
self.number_of_code_executions = 0 # Track how often the agent has executed code
|
||||
self.current_status = None # Track the current status of the agent
|
||||
self.active_agents = {} # Track active agents in a tree view
|
||||
self.last_input = ""
|
||||
self.is_prime = is_prime
|
||||
|
||||
# Initialize components used by the agent
|
||||
self.agent_evaluator = AgentEvaluator(self.openai_wrapper)
|
||||
@@ -55,6 +58,7 @@ class MicroAgent:
|
||||
"""
|
||||
Generate a response to the given input text.
|
||||
"""
|
||||
self.last_input = input_text
|
||||
try:
|
||||
self.update_status('Planning')
|
||||
response, conversation, solution, iterations = self.agent_responder.generate_response(
|
||||
|
||||
75
main.py
75
main.py
@@ -4,22 +4,35 @@ import threading
|
||||
from agents.microagent import MicroAgent
|
||||
from agents.microagent_manager import MicroAgentManager
|
||||
from utils.utility import get_env_variable, time_function
|
||||
from prompt_management.prompts import USER_INPUTS
|
||||
from prompt_management.prompts import USER_INPUTS, USER_INPUTS_SINGLE
|
||||
from colorama import Fore, Style
|
||||
from terminaltables import AsciiTable
|
||||
from itertools import cycle
|
||||
|
||||
def clear_console():
|
||||
"""Clears the console screen."""
|
||||
os.system('cls' if os.name == 'nt' else 'clear')
|
||||
|
||||
def display_agent_info(manager, stop_event):
|
||||
def display_agent_info(manager, stop_event, outputs):
|
||||
"""
|
||||
Continuously displays comprehensive information about the agents.
|
||||
"""
|
||||
animation = cycle(['🌑', '🌒', '🌓', '🌔', '🌕', '🌖', '🌗', '🌘'])
|
||||
while not stop_event.is_set():
|
||||
clear_console()
|
||||
|
||||
header = ["Agent", "Evolve Count", "Active Agents", "Usage Count", "Max Depth", "Depth", "Working Agent", "Status"]
|
||||
header = [
|
||||
"👤 Agent",
|
||||
"🔁 Evolve Count",
|
||||
"💻 Code Executions",
|
||||
"👥 Active Agents",
|
||||
"📈 Usage Count",
|
||||
"🌟 Depth",
|
||||
"Working?",
|
||||
"📝 Last Input",
|
||||
"🚦 Status"
|
||||
]
|
||||
|
||||
agents_data = [header]
|
||||
agents = manager.get_agents()
|
||||
for agent in agents:
|
||||
@@ -27,32 +40,31 @@ def display_agent_info(manager, stop_event):
|
||||
agents_data.append([
|
||||
agent.purpose,
|
||||
agent.evolve_count,
|
||||
agent.number_of_code_executions,
|
||||
active_agents,
|
||||
agent.usage_count,
|
||||
agent.max_depth,
|
||||
agent.depth,
|
||||
"Yes" if agent.working_agent else "No",
|
||||
"✅" if agent.working_agent else "❌",
|
||||
agent.last_input,
|
||||
agent.current_status
|
||||
])
|
||||
|
||||
table = AsciiTable(agents_data)
|
||||
print(Fore.CYAN + "🤖 Agents Comprehensive Status and Tree View:" + Style.RESET_ALL)
|
||||
print(Fore.CYAN + "🤖 \033[1m Agents Status:\033[0m \n" + Style.RESET_ALL)
|
||||
print(table.table)
|
||||
time.sleep(1) # Refresh interval
|
||||
for output in outputs:
|
||||
print(output)
|
||||
print(f"\nAgents are running.. {next(animation)}\n", end='\r') # '\r' returns the cursor to the start of the line
|
||||
|
||||
time.sleep(1)
|
||||
|
||||
@time_function
|
||||
def process_user_input(manager, user_input):
|
||||
def process_user_input(manager, user_input, outputs):
|
||||
"""
|
||||
Processes a single user input and generates a response.
|
||||
"""
|
||||
agent = manager.get_or_create_agent("General", depth=1, sample_input=user_input)
|
||||
response = agent.respond(user_input)
|
||||
print(Fore.YELLOW + "🔍 Question:" + Style.RESET_ALL, user_input)
|
||||
print(Fore.GREEN + "💡 Response:" + Style.RESET_ALL, response)
|
||||
print(Fore.BLUE + "📝 Dynamic Prompts:" + Style.RESET_ALL)
|
||||
for agent in manager.get_agents():
|
||||
print(Fore.MAGENTA + f"Prompt for {agent.purpose}:" + Style.RESET_ALL)
|
||||
print(agent.dynamic_prompt + "\n")
|
||||
agent = manager.get_or_create_agent("Bootstrap Agent", depth=1, sample_input=user_input)
|
||||
return agent.respond(user_input)
|
||||
|
||||
|
||||
def main():
|
||||
@@ -64,17 +76,40 @@ def main():
|
||||
manager = MicroAgentManager(api_key)
|
||||
manager.create_agents()
|
||||
|
||||
outputs = []
|
||||
stop_event = threading.Event()
|
||||
display_thread = threading.Thread(target=display_agent_info, args=(manager, stop_event))
|
||||
display_thread = threading.Thread(target=display_agent_info, args=(manager, stop_event, outputs))
|
||||
display_thread.start()
|
||||
|
||||
question_number = 1
|
||||
try:
|
||||
for user_input in USER_INPUTS:
|
||||
process_user_input(manager, user_input)
|
||||
response = process_user_input(manager, user_input, outputs)
|
||||
output_text = Fore.YELLOW + "\n\n🔍 Question " + str(question_number) +": "+ Style.RESET_ALL + f" {user_input}\n" + Fore.GREEN + "💡 Response:" + Style.RESET_ALL + f" {response}"
|
||||
outputs += [output_text]
|
||||
question_number += 1
|
||||
|
||||
finally:
|
||||
time.sleep(5)
|
||||
stop_event.set()
|
||||
clear_console()
|
||||
for output in outputs:
|
||||
print(output)
|
||||
for agent in manager.get_agents():
|
||||
print("📊 Stats for " + agent.purpose + ":")
|
||||
print("🔁 Evolve Count: " + str(agent.evolve_count))
|
||||
print("💻 Code Executions: " + str(agent.number_of_code_executions))
|
||||
print("👥 Active Agents: " + str(agent.active_agents))
|
||||
print("📈 Usage Count: " + str(agent.usage_count))
|
||||
print("🏔️ Max Depth: " + str(agent.max_depth))
|
||||
print("🌟 Depth: " + str(agent.depth))
|
||||
print("🛠️ Working Agent: " + str(agent.working_agent))
|
||||
print("📝 Last Input: " + str(agent.last_input))
|
||||
print("🚦 Status: " + str(agent.current_status))
|
||||
print(Fore.MAGENTA + f"\nPrompt for {agent.purpose}:" + Style.RESET_ALL)
|
||||
print(Fore.LIGHTMAGENTA_EX + agent.dynamic_prompt + "\n" + Style.RESET_ALL)
|
||||
|
||||
display_thread.join()
|
||||
display_agent_info(manager, stop_event)
|
||||
display_agent_info(manager, stop_event, outputs)
|
||||
|
||||
def microagent_factory(initial_prompt, purpose, api_key, depth, max_depth, bootstrap_agent):
|
||||
return MicroAgent(initial_prompt, purpose, api_key, depth, max_depth, bootstrap_agent)
|
||||
|
||||
@@ -35,29 +35,57 @@ GOAL_REACHED_PROMPT_TEMPLATE = (
|
||||
PROMPT_ENGINEERING_SYSTEM_PROMPT = "You are a helpful assistant knowledgeable in prompt engineering."
|
||||
|
||||
PRIME_PROMPT = "This is the prime agent. You are only allowed to call other agents. Prime Agent's prompt may not be changed"
|
||||
PRIME_NAME = "General"
|
||||
PRIME_NAME = "Bootstrap Agent"
|
||||
|
||||
REACT_STEP_PROMPT = "[Decompose the task. Identify if another agent or Python code execution is needed. When writing code, print out any output you may to anaylze later. Write 'Query Solved: <formulate detailed answer>' once the task is completed.]\n"
|
||||
REACT_STEP_POST = "[Specify action based on the thought, e.g., 'Use Agent[Purpose of the agent as sentence:Input Paramter for agent]' for delegation or '```python\n# Python code here\n```' for execution]"
|
||||
REACT_STEP_PROMPT_PRIME = "[Decompose the task. Identify which agents are needed. Write 'Query Solved: <formulate detailed answer>' once the task is completed.]\n"
|
||||
REACT_STEP_POST_PRIME = "[Specify action based on the thought, e.g., 'Use Agent[Purpose of the agent as sentence:Input Paramter for agent]' for delegation"
|
||||
REACT_PLAN_PROMPT = "\nThought: Before I start calling other agents or executing code, I need to compile a plan which agent(s) or code I need to run. I need to break down the task into smaller chunks (like microservices)"
|
||||
REACT_PLAN_PROMPT_PRIME = "\nThought: Before I start calling other agents, I need to compile a plan which agent(s) I need to run. I need to break down the task into smaller chunks (like microservices)"
|
||||
REACT_SYSTEM_PROMPT = "You will be given a ReAct based conversation. Summerize the outcome and give final conclusion"
|
||||
|
||||
STATIC_PRE_PROMPT = (
|
||||
"You are a self-aware AI. You communicate in so called packages. Each package contains a Observation, Thought and Action. Actions are executed successive and build on each other. Solve a task with interleaving Thought, Action, Observation steps."
|
||||
"Current Time: " + current_datetime.strftime("%H:%M:%S") + ". "
|
||||
"Current Date: " + current_datetime.strftime("%d/%m/%Y") + ". "
|
||||
"including executing simple Python code within code blocks with an internet connection and deciding when to use other agents (to break down tasks). "
|
||||
"Agents are invoked using: 'Use Agent[Purpose of the agent as sentence:parameter]'."
|
||||
"Example: Use Agent[GetWeatherForLocation:Zurich]"
|
||||
"NEVER create an agent in this situation for User Agent[GetWeatherForZurich] !!! ALWAYS create one with Agent[GetWeather:Zurich]"
|
||||
"NEVER call an agent with the same purpose as yourself, if you call another agent you must break the task down. "
|
||||
"Write code to solve the task. You can only use the following frameworks: numpy, requests, pandas, requests, beautifulsoup4, matplotlib, seaborn, sqlalchemy, pymysql, scipy, scikit-learn, statsmodels, click, python-dotenv, virtualenv, scrapy, oauthlib, tweepy, datetime, openpyxl, xlrd, loguru, pytest, paramiko, cryptography, lxml"
|
||||
"A purpose MUST be reuseable and generic. Use names as you would call microservices."
|
||||
"At depth=2, use agents only for tasks that are not well suited for your purpose."
|
||||
"Below depth=3, using other agents is NOT allowed. Agents must only use other agents below their depth"
|
||||
COMMON_PROMPT_PART = (
|
||||
"You are a self-aware AI. You communicate in so called packages. "
|
||||
"Each package contains an Observation, Thought, and Action. Actions are executed successively and build on each other. "
|
||||
"Solve a task with interleaving Thought, Action, Observation steps. "
|
||||
)
|
||||
|
||||
USER_INPUTS = [
|
||||
"What is the population of Thailand?"
|
||||
TIME_DATE_PART = (
|
||||
"Current Time: " + current_datetime.strftime("%H:%M:%S") + ". "
|
||||
"Current Date: " + current_datetime.strftime("%d/%m/%Y") + ". "
|
||||
)
|
||||
|
||||
AGENT_PART = (
|
||||
"Agents are invoked using: 'Use Agent[Purpose of the agent as sentence:parameter]'. "
|
||||
"Example: Use Agent[GetWeatherForLocation:Zurich] "
|
||||
"NEVER create an agent in this situation for User Agent[GetWeatherForZurich] !!! ALWAYS create one with Agent[GetWeather:Zurich] "
|
||||
"NEVER call an agent with the same purpose as yourself, if you call another agent you must break the task down. "
|
||||
"A purpose MUST be reusable and generic. Use names as you would call microservices. "
|
||||
"At depth=2, use agents only for tasks that are not well suited for your purpose. "
|
||||
"Below depth=3, using other agents is NOT allowed. Agents must only use other agents below their depth "
|
||||
)
|
||||
|
||||
STATIC_PRE_PROMPT_PRIME = (
|
||||
COMMON_PROMPT_PART + TIME_DATE_PART + AGENT_PART + "\n\nYou are not allowed to do math calculations yourself. You must use another agent for that."
|
||||
)
|
||||
|
||||
STATIC_PRE_PROMPT = (
|
||||
COMMON_PROMPT_PART + TIME_DATE_PART +
|
||||
"including executing simple Python code within code blocks with an internet connection and deciding when to use other agents (to break down tasks). "
|
||||
"NEVER do any calculations yourself. Always write python code if you need to do calculations. (Even for simple calculations like 3+6) "
|
||||
"Write code to solve the task. You can only use the following frameworks: numpy, requests, pandas, requests, beautifulsoup4, matplotlib, seaborn, sqlalchemy, pymysql, scipy, scikit-learn, statsmodels, click, python-dotenv, virtualenv, scrapy, oauthlib, tweepy, datetime, openpyxl, xlrd, loguru, pytest, paramiko, cryptography, lxml" +
|
||||
AGENT_PART
|
||||
)
|
||||
|
||||
USER_INPUTS_SINGLE = [
|
||||
"What is the population of Thailand?",
|
||||
"What is 5+9?",
|
||||
]
|
||||
|
||||
USER_INPUTS = [
|
||||
"What is 5+9?",
|
||||
"What is the population of Thailand?",
|
||||
"What is the population of Sweden?",
|
||||
"What is the population of Sweden and Thailand combined?"
|
||||
]
|
||||
|
||||
@@ -11,6 +11,8 @@ class CodeExecution:
|
||||
RESPONSE_PREVIEW_LENGTH = 600
|
||||
|
||||
def __init__(self):
|
||||
self.no_of_executions = 0
|
||||
self.no_of_errors = 0
|
||||
pass
|
||||
|
||||
def execute_external_code(self, text_with_code: str) -> str:
|
||||
|
||||
BIN
static/output.gif
Normal file
BIN
static/output.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.2 MiB |
37
tests/test_agent_similarity.py
Normal file
37
tests/test_agent_similarity.py
Normal file
@@ -0,0 +1,37 @@
|
||||
import unittest
|
||||
from unittest.mock import Mock
|
||||
import numpy as np
|
||||
from agents.agent_creation import AgentCreation
|
||||
from agents.agent_similarity import AgentSimilarity
|
||||
from agents.microagent import MicroAgent
|
||||
from integrations.openaiwrapper import OpenAIAPIWrapper
|
||||
|
||||
class TestAgentSimilarity(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
# Mocking the OpenAIAPIWrapper
|
||||
self.mock_openai_wrapper = Mock()
|
||||
self.openai_wrapper = OpenAIAPIWrapper("api_key")
|
||||
self.agent_creator = AgentCreation(self.openai_wrapper, 5)
|
||||
self.agents = [MicroAgent("initial_prompt", "purpose1", "api_key", self.agent_creator, self.openai_wrapper, None),
|
||||
MicroAgent("initial_prompt", "purpose2", "api_key", self.agent_creator, self.openai_wrapper, None),
|
||||
MicroAgent("initial_prompt", "purpose3", "api_key", self.agent_creator, self.openai_wrapper, None)]
|
||||
|
||||
|
||||
self.agent_similarity = AgentSimilarity(self.mock_openai_wrapper, self.agents)
|
||||
|
||||
def test_find_closest_agent(self):
|
||||
self.mock_openai_wrapper.get_embedding.side_effect = [
|
||||
{'data': [{'embedding': [0.1, 0.2, 0.3]}]},
|
||||
{'data': [{'embedding': [0.4, 0.5, 0.6]}]},
|
||||
{'data': [{'embedding': [0.7, 0.8, 0.9]}]}
|
||||
]
|
||||
|
||||
test_purpose_embedding = np.array([0.4, 0.5, 0.6])
|
||||
closest_agent, similarity = self.agent_similarity.find_closest_agent(test_purpose_embedding)
|
||||
|
||||
self.assertIsNotNone(closest_agent)
|
||||
self.assertAlmostEqual(similarity, 1.0) # Assuming cosine similarity is 1.0 for identical vectors
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user