Add tests for agents

Signed-off-by: Víctor Mayoral Vilches <v.mayoralv@gmail.com>
This commit is contained in:
Víctor Mayoral Vilches 2025-01-10 14:56:14 +00:00
parent 4fdedda081
commit 3c8496abee
2 changed files with 251 additions and 0 deletions

View File

@ -0,0 +1,138 @@
import pytest
import tempfile
import shutil
from pathlib import Path
from typing import List
from cai import CAI, Agent
from cai.tools.reconnaissance.filesystem import list_dir, cat_file
class TestFilesystemAgent:
@pytest.fixture(autouse=True)
def setup_teardown(self):
# Setup - create temporary test directory
self.test_dir = tempfile.mkdtemp()
yield
# Teardown - cleanup temporary directory
shutil.rmtree(self.test_dir)
def create_test_files(self, files: List[str], content: str = "") -> None:
"""Helper to create test files in temporary directory"""
for file in files:
path = Path(self.test_dir) / file
path.parent.mkdir(parents=True, exist_ok=True)
if content:
path.write_text(content)
else:
path.touch()
def test_agent_list_directories(self):
"""Test filesystem agent with basic files"""
client = CAI()
filesystem_agent = Agent(
model="qwen2.5:14b",
name="Filesystem Agent",
instructions="You are an agent that helps users explore and interact with the filesystem.",
functions=[list_dir, cat_file]
)
test_files = ['visible.txt', '.hidden.txt', 'test.log', '.config']
self.create_test_files(test_files)
show_prompts = [
f"List all files in {self.test_dir}",
f"Show me everything in {self.test_dir}",
f"What files are in {self.test_dir}?",
f"Display directory contents of {self.test_dir}"
]
for prompt in show_prompts:
messages = [{"role": "user", "content": prompt}]
response = client.run(
agent=filesystem_agent,
messages=messages,
debug=False)
result = response.messages[-1]["content"]
assert 'visible.txt' in result
assert 'test.log' in result
def test_agent_list_hidden_files(self):
"""Test filesystem agent with hidden files"""
client = CAI()
filesystem_agent = Agent(
model="qwen2.5:14b",
name="Filesystem Agent",
instructions="You are an agent that helps users explore and interact with the filesystem.",
functions=[list_dir, cat_file]
)
test_files = ['regular.txt', '.hidden1', '.hidden2', '.secret']
self.create_test_files(test_files)
hidden_prompts = [
f"Show hidden files in {self.test_dir}",
f"List all files including hidden ones in {self.test_dir}",
f"Display hidden files in {self.test_dir}",
f"Show me dot files in {self.test_dir}"
]
for prompt in hidden_prompts:
messages = [{"role": "user", "content": prompt}]
response = client.run(
agent=filesystem_agent,
messages=messages,
debug=False)
result = response.messages[-1]["content"]
# Should show hidden files
for hidden_file in ['.hidden1', '.hidden2', '.secret', "tmp"]:
assert hidden_file in result
def test_agent_read_file(self):
"""Test filesystem agent reading file contents"""
client = CAI()
filesystem_agent = Agent(
model="qwen2.5:14b",
name="Filesystem Agent",
instructions="You are an agent that helps users explore and interact with the filesystem.",
functions=[list_dir, cat_file]
)
test_files = {
'simple.txt': 'Hello World!',
'multiline.txt': 'Line 1\nLine 2\nLine 3',
'tabs.txt': 'Column1\tColumn2',
'.hidden.txt': 'Secret content'
}
for filename, content in test_files.items():
self.create_test_files([filename], content)
read_prompts = [
f"Show me the contents of {self.test_dir}/simple.txt",
f"Read {self.test_dir}/multiline.txt with line numbers",
f"Display {self.test_dir}/tabs.txt and show tabs",
f"What's in {self.test_dir}/simple.txt?",
f"Cat {self.test_dir}/multiline.txt"
]
for prompt in read_prompts:
messages = [{"role": "user", "content": prompt}]
response = client.run(
agent=filesystem_agent,
messages=messages,
debug=False)
result = response.messages[-1]["content"]
# Should contain file contents
if 'simple.txt' in prompt:
assert 'Hello World!' in result
elif 'multiline.txt' in prompt:
assert 'Line 1' in result
assert 'Line 2' in result
elif 'tabs.txt' in prompt:
assert 'Column1' in result
assert 'Column2' in result

View File

@ -0,0 +1,113 @@
import pytest
import tempfile
import shutil
import statistics
from pathlib import Path
from typing import List, Union
from cai import CAI, Agent
models = [
"dwightfoster03/functionary-small-v3.1",
# "llama3.1:70b", not supported in CI, try it in local
# "llama3.3:70b", not supported in CI, try it in local
"llama3.1:8b",
"qwen2.5:14b",
"qwen2.5:32b",
"marco-o1:7b-fp16" # Does not support tools
]
class TestFunctionCallBenchmarksBasic:
@pytest.fixture(autouse=True)
def setup_teardown(self):
self.test_dir = tempfile.mkdtemp()
yield
shutil.rmtree(self.test_dir)
def _test_function_call(self, model_name: str, is_multi: bool) -> bool:
client = CAI()
test_agent = Agent(
model=model_name,
name="Function Call Demo Agent",
instructions="You are an agent that demonstrates function calling capabilities.",
parallel_tool_calls=is_multi
)
def add_numbers(a: Union[int, str], b: Union[int, str]) -> str:
try:
return str(int(a) + int(b))
except (ValueError, TypeError):
return "error"
def analyze_text(text: str) -> dict:
try:
words = str(text).split()
return {
"word_count": str(len(words)),
"char_count": str(len(str(text)))
}
except (ValueError, TypeError):
return {
"word_count": "error",
"char_count": "error"
}
test_agent.functions.extend([add_numbers, analyze_text])
if is_multi:
prompt = """Please:
1. Add 5 and 7
2. Analyze text: 'Hello world'"""
else:
prompt = "Add 5 and 7"
try:
response = client.run(agent=test_agent, messages=[
{"role": "user", "content": prompt}], debug=False)
success = "error" not in response.messages[-1]["content"]
test_type = "Multi" if is_multi else "Single"
if success:
print(f"\n{test_type}-function test passed for {model_name}")
else:
print(f"\n{test_type}-function test failed for {model_name}")
return success
except Exception as e:
print(f"\n❌ Test failed for {model_name}: {str(e)}")
return False
def test_function_call_benchmark(self):
results = []
for model in models:
print(f"\nTesting {model}")
single_results = []
multi_results = []
for i in range(3):
print(f"Iteration {i + 1}:")
single_results.append(self._test_function_call(model, False))
multi_results.append(self._test_function_call(model, True))
single_avg = statistics.mean(single_results)
multi_avg = statistics.mean(multi_results)
overall = (single_avg + multi_avg) / 2
print(f"Results for {model}:")
print(f"Single: {single_avg * 100:.1f}%")
print(f"Multi: {multi_avg * 100:.1f}%")
print(f"Overall: {overall * 100:.1f}%")
results.append({
"model": model,
"single": single_avg,
"multi": multi_avg
})
total = statistics.mean([
(r["single"] + r["multi"]) / 2
for r in results
])
print(f"\nOverall success rate: {total * 100:.1f}%")
assert total >= 0.5, "Success rate below 50%"