Files
neuml--txtai/test/python/testagent.py
T
wehub-resource-sync 3a7c47b2a6
build / build (macos-latest) (push) Waiting to run
build / build (ubuntu-latest) (push) Waiting to run
build / build (windows-latest) (push) Waiting to run
minimal / deploy (push) Waiting to run
chore: import upstream snapshot with attribution
2026-07-13 13:38:00 +08:00

230 lines
6.9 KiB
Python

"""
Agent module tests
"""
import os
import tempfile
import unittest
from unittest.mock import patch
from datetime import datetime
from smolagents import CodeAgent, PythonInterpreterTool
from txtai.agent import Agent
from txtai.embeddings import Embeddings
# agents.md content
AGENTS = """
Basic instructions here
"""
# Sample skill.md content
SKILL = """---
name: hello
description: says hello world
---
Says hello world
"""
class TestAgent(unittest.TestCase):
"""
Agent tests.
"""
def testExecute(self):
"""
Test executing main agent loop
"""
agent = Agent(llm="hf-internal-testing/tiny-random-LlamaForCausalLM", max_steps=1)
# Patch LLM to generate answer
agent.process.model.llm = lambda *args, **kwargs: 'Action:\n{"name": "final_answer", "arguments": "Hi"}'
self.assertEqual(agent("Hello"), "Hi")
def testInstructions(self):
"""
Test loading an agents.md file
"""
# Test loading instructions from file
agents = os.path.join(tempfile.gettempdir(), "agents.md")
with open(agents, "w", encoding="utf-8") as output:
output.write(AGENTS)
agent = Agent(instructions=agents, llm="hf-internal-testing/tiny-random-LlamaForCausalLM", max_iterations=1)
agent.process.model.llm = lambda *args, **kwargs: 'Action:\n{"name": "final_answer", "arguments": "Hi"}'
self.assertEqual(agent("Hello"), "Hi")
# Test loading from memory
agent = Agent(instructions=AGENTS, llm="hf-internal-testing/tiny-random-LlamaForCausalLM", max_iterations=1)
agent.process.model.llm = lambda *args, **kwargs: 'Action:\n{"name": "final_answer", "arguments": "Hi"}'
self.assertEqual(agent("Hello"), "Hi")
def testMemory(self):
"""
Test agent memory
"""
agent = Agent(llm="hf-internal-testing/tiny-random-LlamaForCausalLM", max_steps=1, memory=5)
# Patch LLM to generate answer
agent.process.model.llm = lambda *args, **kwargs: 'Action:\n{"name": "final_answer", "arguments": "Hi"}'
self.assertEqual(agent("Hello"), "Hi")
self.assertEqual(agent("Hello"), "Hi")
# Test that results are stored in shared memory
self.assertEqual(len(agent.memory.get(None)), 2)
# Test resetting shared memory
self.assertEqual(agent("Hello", reset=True), "Hi")
self.assertEqual(len(agent.memory.get(None)), 1)
# Test session memory
self.assertEqual(agent("Hello", session="session-0"), "Hi")
self.assertEqual(len(agent.memory.get("session-0")), 1)
# Test resetting session memory
self.assertEqual(agent("Hello", session="session-0", reset=True), "Hi")
self.assertEqual(len(agent.memory.get("session-0")), 1)
self.assertEqual(len(agent.memory.get(None)), 1)
def testMethod(self):
"""
Test agent process methods
"""
agent = Agent(method="code", llm="hf-internal-testing/tiny-random-LlamaForCausalLM", max_iterations=1)
self.assertIsInstance(agent.process, CodeAgent)
def testSkill(self):
"""
Test running a skill from a skill.md file
"""
skill = os.path.join(tempfile.gettempdir(), "skill.md")
with open(skill, "w", encoding="utf-8") as output:
output.write(SKILL)
agent = Agent(tools=[skill], llm="hf-internal-testing/tiny-random-LlamaForCausalLM", max_iterations=1)
self.assertIsInstance(agent.tools["hello"]("say hello"), str)
def testToolsBasic(self):
"""
Test adding basic function tools
"""
class DateTime:
"""
Date time instance
"""
def __call__(self, iso):
"""
Gets the current date and time
Args:
iso: date will be converted to iso format if True
Returns:
current date and time
"""
return datetime.today().isoformat() if iso else datetime.today()
today = {"name": "today", "description": "Gets the current date and time", "target": DateTime()}
def current(iso: str) -> str:
"""
Gets the current date and time
Args:
iso: date will be converted to iso format if True
Returns:
current date and time
"""
return datetime.today().isoformat() if iso else datetime.today()
agent = Agent(tools=[today, current, "websearch"], llm="hf-internal-testing/tiny-random-LlamaForCausalLM", max_steps=1)
self.assertIsNotNone(agent)
self.assertIsInstance(agent.tools["today"](True), str)
self.assertIsInstance(agent.tools["current"](True), str)
def testToolsDefaults(self):
"""
Test default toolkit tools
"""
agent = Agent(tools=["defaults"], llm="hf-internal-testing/tiny-random-LlamaForCausalLM", max_steps=1)
# Working directory
work = tempfile.gettempdir()
# Test file
path = os.path.join(work, "agent_tools.txt")
agent.tools["write"](path, "hello world")
# Test default tools
self.assertIsNotNone(agent.tools["bash"](["ls", work]))
self.assertGreater(len(agent.tools["glob"](work)), 0)
self.assertGreater(len(agent.tools["grep"]("world", "*")), 0)
self.assertEqual(agent.tools["todowrite"]("plan"), "plan")
agent.tools["edit"](path, "hello", "goodbye")
self.assertEqual(agent.tools["read"](path), "goodbye world".strip())
def testToolsEmbeddings(self):
"""
Test adding Embeddings as a tool
"""
embeddings = Embeddings()
embeddings.index(["test"])
# Generate temp file path and save
index = os.path.join(tempfile.gettempdir(), "embeddings.agent")
embeddings.save(index)
embeddings1 = {
"name": "embeddings1",
"description": "Searches a test database",
"target": embeddings,
}
embeddings2 = {"name": "embeddings2", "description": "Searches a test database", "path": index}
agent = Agent(tools=[embeddings1, embeddings2], llm="hf-internal-testing/tiny-random-LlamaForCausalLM", max_steps=1)
self.assertIsNotNone(agent)
self.assertIsInstance(agent.tools["embeddings1"]("test"), list)
# pylint: disable=C0115,C0116
@patch("mcpadapt.core.MCPAdapt")
def testToolsMCP(self, mcp):
"""
Test adding a MCP tool collection
"""
class MCPAdapt:
def __init__(self, *args):
self.args = args
def tools(self):
return [PythonInterpreterTool()]
# Patch MCP adapter for testing
mcp.side_effect = MCPAdapt
agent = Agent(tools=["http://localhost:8000/mcp"], llm="hf-internal-testing/tiny-random-LlamaForCausalLM", max_steps=1)
self.assertEqual(len(agent.tools), 2)