Files
wehub-resource-sync 426e9eeabd
Voice Workbench / headless workbench (mocked backends) (push) Has been cancelled
Voice Workbench / real acoustic lane (nightly, provisioned only) (push) Has been cancelled
ci / test (push) Has been cancelled
ci / lint-and-format (push) Has been cancelled
ci / build (push) Has been cancelled
ci / dev-startup (push) Has been cancelled
gitleaks / gitleaks (push) Has been cancelled
Markdown Links / Relative Markdown Links (push) Has been cancelled
Quality (Extended) / Homepage Build (PR smoke) (push) Has been cancelled
Quality (Extended) / Comment-only diff guard (push) Has been cancelled
Quality (Extended) / Format + Type Safety Ratchet (push) Has been cancelled
Quality (Extended) / Develop Gate (secret scan + UI determinism) (push) Has been cancelled
Quality (Extended) / Develop Gate (lint) (push) Has been cancelled
Chat shell gestures / Chat shell gesture + parity e2e (push) Has been cancelled
Cloud Gateway Discord / Test (push) Has been cancelled
Benchmark Bridge Tests / benchmark (bunx @biomejs/biome check packages/lifeops-bench/src, benchmark-lint) (push) Has been cancelled
Benchmark Bridge Tests / benchmark (bunx vitest run --config packages/lifeops-bench/vitest.config.ts --root packages/lifeops-bench --passWithNoTests, benchmark-tests) (push) Has been cancelled
Build Agent Image / build-and-push (push) Has been cancelled
Dev Smoke / bun run dev onboarding chat (push) Has been cancelled
Dev Smoke / Vite HMR dependency-level smoke (push) Has been cancelled
Electrobun Submodule Guard / electrobun gitlink is fetchable (push) Has been cancelled
Publish @elizaos/example-code / check_npm (push) Has been cancelled
Publish @elizaos/example-code / publish_npm (push) Has been cancelled
Publish @elizaos/plugin-elizacloud / verify_version (push) Has been cancelled
Publish @elizaos/plugin-elizacloud / publish_npm (push) Has been cancelled
Sandbox Live Smoke / Sandbox live smoke (push) Has been cancelled
Snap Build & Test / Build Snap (amd64) (push) Has been cancelled
Snap Build & Test / Build Snap (arm64) (push) Has been cancelled
Test Packaging / elizaos CLI global-install smoke (node + bun) (push) Has been cancelled
Cloud Gateway Webhook / Test (push) Has been cancelled
Cloud Tests / lint-and-types (push) Has been cancelled
Cloud Tests / unit-tests (push) Has been cancelled
Cloud Tests / integration-tests (push) Has been cancelled
Cloud Tests / e2e-tests (push) Has been cancelled
CodeQL Advanced / Analyze (javascript-typescript) (push) Has been cancelled
Deploy Apps Worker (Product 2) / Determine environment (push) Has been cancelled
Deploy Apps Worker (Product 2) / Deploy apps worker to apps-control host (${{ needs.determine-env.outputs.environment }}) (push) Has been cancelled
Deploy Eliza Provisioning Worker / Determine environment (push) Has been cancelled
Deploy Eliza Provisioning Worker / Deploy worker to Hetzner host (${{ needs.determine-env.outputs.environment }} @ ${{ needs.determine-env.outputs.deployment_sha }}) (push) Has been cancelled
Dev Smoke / Classify changed paths (push) Has been cancelled
supply-chain / sbom (push) Has been cancelled
supply-chain / vulnerability-scan (push) Has been cancelled
Build, Push & Deploy to Phala Cloud / build-and-push (push) Has been cancelled
Test Packaging / Validate Packaging Configs (push) Has been cancelled
Test Packaging / Build & Test PyPI Package (push) Has been cancelled
Test Packaging / PyPI on Python ${{ matrix.python }} (push) Has been cancelled
Test Packaging / Pack & Test JS Tarballs (push) Has been cancelled
UI Fixture E2E / ui-fixture-e2e (push) Has been cancelled
UI Fixture E2E / fixture-e2e (push) Has been cancelled
UI Story Gate / story-gate (push) Has been cancelled
vault-ci / test (macos-latest) (push) Has been cancelled
vault-ci / test (ubuntu-latest) (push) Has been cancelled
vault-ci / test (windows-latest) (push) Has been cancelled
vault-ci / app-core wiring tests (push) Has been cancelled
verify-patches / verify patches/CHECKSUMS.sha256 (push) Has been cancelled
Voice Benchmark Smoke / voice-emotion fixture smoke (push) Has been cancelled
Voice Benchmark Smoke / voiceagentbench fixture smoke (push) Has been cancelled
Voice Benchmark Smoke / voicebench-quality unit smoke (push) Has been cancelled
Voice Benchmark Smoke / voicebench TypeScript unit (no audio) (push) Has been cancelled
Voice Benchmark Smoke / voice bench smoke summary (push) Has been cancelled
Windows CI / windows ([bun run --cwd packages/app-core test bun run --cwd packages/elizaos test bun run --cwd packages/cloud/shared test], app-and-cli) (push) Has been cancelled
Windows CI / windows ([bun run --cwd packages/scenario-runner test bun run --cwd packages/vault test bun run --cwd packages/security test bun run --cwd plugins/plugin-coding-tools test], framework-packages) (push) Has been cancelled
Windows CI / windows ([bun run --cwd plugins/plugin-elizacloud test bun run --cwd plugins/plugin-discord test bun run --cwd plugins/plugin-anthropic test bun run --cwd plugins/plugin-openai test bun run --cwd plugins/plugin-app-control test bun run --cwd plugins/pl… (push) Has been cancelled
Windows CI / windows ([node packages/scripts/run-turbo.mjs run build --filter=@elizaos/core --filter=@elizaos/shared --filter=@elizaos/agent --concurrency=4 node packages/scripts/run-bash-linux-only.mjs scripts/verify-riscv64-buildpaths.sh node packages/scripts/run… (push) Has been cancelled
Windows CI / windows ([node packages/scripts/run-turbo.mjs run typecheck --filter=@elizaos/core --filter=@elizaos/shared --filter=@elizaos/cloud-shared --concurrency=4 bun run --cwd packages/core test bun run --cwd packages/shared test], core-runtime, 75) (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:43:05 +08:00

364 lines
11 KiB
Python

#!/usr/bin/env python3
"""
BFCL Integration Test Script
Tests the full BFCL benchmark pipeline with a real LLM provider.
Requires API keys to be set in environment or .env file.
Usage:
python -m benchmarks.bfcl.scripts.test_integration
Environment Variables:
OPENAI_API_KEY - OpenAI API key (preferred)
ANTHROPIC_API_KEY - Anthropic API key
GOOGLE_GENERATIVE_AI_API_KEY - Google AI API key
"""
from __future__ import annotations
import asyncio
import logging
import os
import sys
from pathlib import Path
# Add project root to path
project_root = Path(__file__).parent.parent.parent.parent
sys.path.insert(0, str(project_root))
# Load .env file if present
try:
from dotenv import load_dotenv
env_path = project_root / ".env"
if env_path.exists():
load_dotenv(env_path)
print(f"✅ Loaded environment from {env_path}")
except ImportError:
print("⚠️ python-dotenv not installed, using system environment")
from benchmarks.bfcl.agent import BFCLAgent, get_model_provider_plugin, ELIZAOS_AVAILABLE # noqa: E402
from benchmarks.bfcl.types import ( # noqa: E402
BFCLCategory,
BFCLConfig,
BFCLTestCase,
FunctionCall,
FunctionDefinition,
FunctionParameter,
)
from benchmarks.bfcl.parser import FunctionCallParser # noqa: E402
from benchmarks.bfcl.evaluators import ASTEvaluator # noqa: E402
logging.basicConfig(level=logging.INFO, format="%(levelname)s: %(message)s")
logger = logging.getLogger(__name__)
def create_test_case() -> BFCLTestCase:
"""Create a simple test case for integration testing."""
return BFCLTestCase(
id="integration_test_1",
category=BFCLCategory.SIMPLE,
question="What's the weather like in San Francisco?",
functions=[
FunctionDefinition(
name="get_weather",
description="Get the current weather for a location",
parameters={
"location": FunctionParameter(
name="location",
param_type="string",
description="The city and state, e.g. San Francisco, CA",
required=True,
),
"unit": FunctionParameter(
name="unit",
param_type="string",
description="Temperature unit: 'celsius' or 'fahrenheit'",
required=False,
enum=["celsius", "fahrenheit"],
default="fahrenheit",
),
},
required_params=["location"],
),
],
expected_calls=[
FunctionCall(
name="get_weather",
arguments={"location": "San Francisco, CA"},
),
],
)
def check_environment() -> dict[str, bool]:
"""Check which API keys are available."""
keys = {
"OPENAI_API_KEY": bool(os.environ.get("OPENAI_API_KEY")),
"ANTHROPIC_API_KEY": bool(os.environ.get("ANTHROPIC_API_KEY")),
"GOOGLE_GENERATIVE_AI_API_KEY": bool(os.environ.get("GOOGLE_GENERATIVE_AI_API_KEY")),
}
return keys
async def test_parser() -> bool:
"""Test the function call parser."""
print("\n" + "=" * 60)
print("TESTING: Function Call Parser")
print("=" * 60)
parser = FunctionCallParser()
# Test cases
test_responses = [
('{"name": "get_weather", "arguments": {"location": "San Francisco"}}', 1),
('[{"name": "func1", "arguments": {}}, {"name": "func2", "arguments": {}}]', 2),
('```json\n{"name": "test", "arguments": {"x": 1}}\n```', 1),
('No function needed', 0),
]
all_passed = True
for response, expected_count in test_responses:
calls = parser.parse(response)
if len(calls) == expected_count:
print(f" ✅ Parser correctly extracted {expected_count} calls")
else:
print(f" ❌ Parser error: expected {expected_count}, got {len(calls)}")
all_passed = False
return all_passed
async def test_evaluator() -> bool:
"""Test the AST evaluator."""
print("\n" + "=" * 60)
print("TESTING: AST Evaluator")
print("=" * 60)
evaluator = ASTEvaluator()
# Test exact match
predicted = [FunctionCall(name="get_weather", arguments={"location": "NYC"})]
expected = [FunctionCall(name="get_weather", arguments={"location": "NYC"})]
if evaluator.evaluate(predicted, expected):
print(" ✅ Exact match test passed")
else:
print(" ❌ Exact match test failed")
return False
# Test case-insensitive
predicted = [FunctionCall(name="GetWeather", arguments={"Location": "NYC"})]
expected = [FunctionCall(name="get_weather", arguments={"location": "NYC"})]
if evaluator.evaluate(predicted, expected):
print(" ✅ Case-insensitive match test passed")
else:
print(" ❌ Case-insensitive match test failed")
return False
return True
async def test_agent_mock_mode() -> bool:
"""Test the agent in mock mode (no LLM)."""
print("\n" + "=" * 60)
print("TESTING: Agent Mock Mode")
print("=" * 60)
config = BFCLConfig()
agent = BFCLAgent(config)
await agent.initialize()
test_case = create_test_case()
calls, response, latency = await agent.query(test_case)
print(f" Response: {response[:100]}...")
print(f" Latency: {latency:.2f}ms")
print(f" Calls extracted: {len(calls)}")
await agent.close()
# In mock mode, we expect MOCK_MODE response
if "MOCK" in response:
print(" ✅ Mock mode working correctly")
return True
else:
print(" ⚠️ Unexpected response in mock mode")
return True # Still pass, might have model available
async def test_agent_with_llm() -> bool:
"""Test the agent with a real LLM provider."""
print("\n" + "=" * 60)
print("TESTING: Agent with LLM Provider")
print("=" * 60)
# Check if any model provider is available
model_plugin, model_name = get_model_provider_plugin()
if model_plugin is None:
print(" ⚠️ No model provider available, skipping LLM test")
print(" Set GROQ_API_KEY, OPENAI_API_KEY, ANTHROPIC_API_KEY, or GOOGLE_GENERATIVE_AI_API_KEY")
return True # Not a failure, just skipped
print(f" Using model: {model_name}")
print(f" Plugin: {model_plugin.name}")
config = BFCLConfig(temperature=0.0)
agent = BFCLAgent(config, model_plugin=model_plugin)
try:
await agent.initialize()
test_case = create_test_case()
calls, response, latency = await agent.query(test_case)
print(f"\n Raw Response:\n {response[:500]}")
print(f"\n Latency: {latency:.2f}ms")
print(f" Calls extracted: {len(calls)}")
if calls:
for i, call in enumerate(calls):
print(f" Call {i+1}: {call.name}({call.arguments})")
# Evaluate the result
evaluator = ASTEvaluator()
# Check if we got a function call with "get_weather"
has_weather_call = any(
"weather" in call.name.lower() for call in calls
)
# Check if location argument contains San Francisco
has_sf_location = any(
"san francisco" in str(call.arguments).lower() for call in calls
)
if has_weather_call and has_sf_location:
print("\n ✅ LLM correctly identified function and arguments!")
# Full AST evaluation
ast_match = evaluator.evaluate(calls, test_case.expected_calls)
if ast_match:
print(" ✅ Full AST match!")
else:
print(" ⚠️ Partial match (function correct, arguments may differ)")
details = evaluator.get_match_details(calls, test_case.expected_calls)
print(f" Details: {details}")
return True
else:
print("\n ❌ LLM did not correctly identify the function call")
return False
finally:
await agent.close()
async def run_mini_benchmark() -> bool:
"""Run a mini benchmark with a few test cases."""
print("\n" + "=" * 60)
print("TESTING: Mini Benchmark (3 test cases)")
print("=" * 60)
model_plugin = get_model_provider_plugin()
if model_plugin is None:
print(" ⚠️ No model provider available, skipping mini benchmark")
return True
from benchmarks.bfcl.runner import BFCLRunner
from benchmarks.bfcl.types import BFCLConfig
config = BFCLConfig(
max_tests_per_category=1,
temperature=0.0,
generate_report=False,
)
runner = BFCLRunner(config, use_mock_agent=False)
try:
# Try to run a small sample
results = await runner.run_sample(n=3)
print("\n Results:")
print(f" Overall Score: {results.metrics.overall_score:.2%}")
print(f" AST Accuracy: {results.metrics.ast_accuracy:.2%}")
print(f" Tests: {results.metrics.passed_tests}/{results.metrics.total_tests}")
return results.metrics.overall_score > 0
except Exception as e:
print(f" ❌ Mini benchmark failed: {e}")
import traceback
traceback.print_exc()
return False
async def main() -> int:
"""Run all integration tests."""
print("=" * 60)
print("BFCL INTEGRATION TEST SUITE")
print("=" * 60)
# Check environment
print("\n📋 Environment Check:")
print(f" ElizaOS Available: {ELIZAOS_AVAILABLE}")
keys = check_environment()
for key, available in keys.items():
status = "✅" if available else "❌"
print(f" {key}: {status}")
has_any_key = any(keys.values())
if not has_any_key:
print("\n⚠️ No API keys found. Set one of the following:")
print(" - OPENAI_API_KEY")
print(" - ANTHROPIC_API_KEY")
print(" - GOOGLE_GENERATIVE_AI_API_KEY")
print("\n Or create a .env file in the project root.")
# Run tests
results = []
# Test 1: Parser
results.append(("Parser", await test_parser()))
# Test 2: Evaluator
results.append(("Evaluator", await test_evaluator()))
# Test 3: Mock Agent
results.append(("Mock Agent", await test_agent_mock_mode()))
# Test 4: LLM Agent (only if keys available)
if has_any_key:
results.append(("LLM Agent", await test_agent_with_llm()))
# Test 5: Mini benchmark
# results.append(("Mini Benchmark", await run_mini_benchmark()))
# Summary
print("\n" + "=" * 60)
print("TEST SUMMARY")
print("=" * 60)
all_passed = True
for name, passed in results:
status = "✅ PASS" if passed else "❌ FAIL"
print(f" {name}: {status}")
if not passed:
all_passed = False
if all_passed:
print("\n🎉 All tests passed!")
return 0
else:
print("\n❌ Some tests failed")
return 1
if __name__ == "__main__":
exit_code = asyncio.run(main())
sys.exit(exit_code)