From aaf5bb63c476a87574e91c554628ee010e364278 Mon Sep 17 00:00:00 2001 From: sridharswain Date: Wed, 18 Mar 2026 13:14:39 +0530 Subject: [PATCH 1/5] domain changes so release --- .github/ISSUE_TEMPLATE/config.yml | 2 +- CONTRIBUTING.md | 37 +- README.md | 114 ++++- docs/assets/fasteval-overview.svg | 4 +- fasteval-overview.png | Bin 0 -> 99144 bytes hero-evaluation-journey.png | Bin 0 -> 98576 bytes medium-article.md | 258 +++++++++++ pyproject.toml | 35 +- testing-pyramid-agents.png | Bin 0 -> 124215 bytes tests/test_async_helpers.py | 33 ++ tests/test_base_metric.py | 53 +++ tests/test_cache.py | 171 +++++++ tests/test_collector.py | 220 +++++++++ tests/test_conversation_metrics.py | 105 +++++ tests/test_decorators_extended.py | 343 ++++++++++++++ tests/test_deterministic_metrics.py | 695 ++++++++++++++++++++++++++++ tests/test_evaluator.py | 324 +++++++++++++ tests/test_formatting.py | 88 ++++ tests/test_json_parsing.py | 113 +++++ tests/test_llm_metrics.py | 412 +++++++++++++++++ tests/test_plugin.py | 217 +++++++++ tests/test_providers.py | 192 ++++++++ tests/test_reporters.py | 155 +++++++ tests/test_scoring.py | 191 ++++++++ tests/test_text_utils.py | 39 ++ uv.lock | 9 +- 26 files changed, 3773 insertions(+), 37 deletions(-) create mode 100644 fasteval-overview.png create mode 100644 hero-evaluation-journey.png create mode 100644 medium-article.md create mode 100644 testing-pyramid-agents.png create mode 100644 tests/test_async_helpers.py create mode 100644 tests/test_base_metric.py create mode 100644 tests/test_cache.py create mode 100644 tests/test_collector.py create mode 100644 tests/test_conversation_metrics.py create mode 100644 tests/test_decorators_extended.py create mode 100644 tests/test_deterministic_metrics.py create mode 100644 tests/test_evaluator.py create mode 100644 tests/test_formatting.py create mode 100644 tests/test_json_parsing.py create mode 100644 tests/test_llm_metrics.py create mode 100644 tests/test_plugin.py create mode 100644 tests/test_providers.py create mode 100644 tests/test_reporters.py create mode 100644 tests/test_scoring.py create mode 100644 tests/test_text_utils.py diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index 959074c..9318b74 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -1,7 +1,7 @@ blank_issues_enabled: true contact_links: - name: Documentation - url: https://github.com/intuit/fasteval/tree/main/docs + url: https://fasteval.io about: Browse the documentation for guides and API reference. - name: Discussions url: https://github.com/intuit/fasteval/discussions diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index b7c0e99..c783e3a 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -30,10 +30,10 @@ Thank you for your interest in contributing to fasteval! Whether it's fixing a b cd fasteval ``` -2. Install dependencies: +2. Install all dependencies (including dev and test groups): ```bash - uv sync --all-extras + uv sync --all-extras --group dev --group test ``` 3. Verify everything works: @@ -97,8 +97,9 @@ uv run mypy . ## Testing - All new functionality must have corresponding tests -- Maintain code coverage at or above 80% +- Maintain code coverage at or above **85%** - Tests live in `tests/` for the core package and `plugins/*/tests/` for plugins +- Coverage configuration is in `pyproject.toml` under `[tool.coverage.run]` and `[tool.coverage.report]` -- models, vision/audio/multimodal metrics, and other non-logic files are excluded from measurement Run tests: @@ -106,17 +107,23 @@ Run tests: # Full test suite across Python versions uv run tox -# Quick single-version test -uv run pytest tests/ -v --cov=fasteval +# Quick single-version test with coverage +uv run --group test pytest tests/ --cov=fasteval --cov-report=term -v # Run a specific test -uv run pytest tests/test_example.py::test_name -v +uv run --group test pytest tests/test_example.py::test_name -v + +# Run plugin tests (from plugin directory) +cd plugins/fasteval-langgraph +uv run pytest tests/ -v ``` +> **Note**: The project includes a custom pytest plugin (`fasteval.testing.plugin`). When running tests with coverage, the plugin is automatically disabled via `addopts` in `pyproject.toml` (`-p no:fasteval`) to ensure accurate coverage tracking. + ## Pull Request Process 1. Ensure all tests pass and linting is clean. -2. Update documentation if your change affects user-facing behavior (see `docs/`). +2. Update documentation if your change affects user-facing behavior. Docs are published at [fasteval.io](https://fasteval.io) and source lives in `docs/`. 3. Open a pull request against `main` with a clear description of your changes. 4. A maintainer will review your PR, typically within a few business days. 5. Once approved, a maintainer will merge your contribution. @@ -129,6 +136,14 @@ uv run pytest tests/test_example.py::test_name -v - Adherence to the existing code style - Clear, focused commits (one logical change per commit) +### Writing Custom Metrics + +If you're contributing a new metric, see the [Custom Metrics guide](https://fasteval.io/docs/advanced/custom-metrics) for the expected patterns. All metrics should: +- Extend `Metric` (deterministic) or `BaseLLMMetric` (LLM-based) +- Include a corresponding decorator in `fasteval/core/decorators.py` +- Be registered in `METRIC_REGISTRY` in `fasteval/core/evaluator.py` +- Have tests with >85% coverage + ## Project Structure ``` @@ -137,16 +152,18 @@ fasteval/ ├── metrics/ # Metric implementations (LLM, deterministic, conversation) ├── models/ # Pydantic models (EvalInput, EvalResult, MetricResult) ├── providers/ # LLM provider clients (OpenAI, Anthropic) -├── cache/ # Caching utilities +├── cache/ # In-memory LRU caching +├── collectors/ # Result collection and reporting +│ └── reporters/ # Output reporters (JSON, HTML) ├── utils/ # Helpers (formatting, JSON parsing, async) -└── testing/ # pytest plugin +└── testing/ # pytest plugin (--fe-output, --fe-summary, --no-interactive) plugins/ ├── fasteval-langfuse/ # Langfuse production trace evaluation ├── fasteval-langgraph/ # LangGraph agent testing └── fasteval-observe/ # Runtime monitoring -docs/ # MDX documentation +docs/ # MDX documentation (published at fasteval.io) tests/ # Core package tests ``` diff --git a/README.md b/README.md index 95b9459..ce3cadb 100644 --- a/README.md +++ b/README.md @@ -7,19 +7,34 @@ ![Python versions](https://img.shields.io/badge/python-3.10_|_3.11_|_3.12_|_3.13_|_3.14-blue?logo=python) [![CI](https://github.com/intuit/fasteval/actions/workflows/ci.yml/badge.svg)](https://github.com/intuit/fasteval/actions/workflows/ci.yml) [![License](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) +[![Docs](https://img.shields.io/badge/docs-fasteval.io-blue)](https://fasteval.io) -A **decorator-first LLM evaluation library** for testing AI agents and LLMs. Stack decorators to define evaluation criteria, run with pytest. +A **decorator-first LLM evaluation library** for testing AI agents and LLMs. Stack decorators to define evaluation criteria, run with pytest. [Read the docs](https://fasteval.io). + +

+ The Evaluation Journey -- from non-deterministic LLM outputs to reliable engineering metrics +

## Features -- **Decorator-based metrics** -- stack `@fe.correctness`, `@fe.relevance`, `@fe.hallucination`, and 30+ more +- **50+ built-in metrics** -- stack `@fe.correctness`, `@fe.relevance`, `@fe.hallucination`, and more - **pytest native** -- run evaluations with `pytest`, get familiar pass/fail output - **LLM-as-judge + deterministic** -- semantic LLM metrics alongside ROUGE, exact match, JSON schema, regex +- **Custom criteria** -- `@fe.criteria("Is the response empathetic?")` for any evaluation you can describe in plain English - **Multi-modal** -- evaluate vision, audio, and image generation models - **Conversation metrics** -- context retention, topic drift, consistency for multi-turn agents - **RAG metrics** -- faithfulness, contextual precision, contextual recall, answer correctness - **Tool trajectory** -- verify agent tool calls, argument matching, call sequences -- **Pluggable providers** -- OpenAI (default), Anthropic, Azure OpenAI, Ollama +- **Reusable metric stacks** -- `@fe.stack()` to compose and reuse metric sets across tests +- **Human-in-the-loop** -- `@fe.human_review()` for manual review alongside automated metrics +- **Data-driven testing** -- `@fe.csv("test_data.csv")` to load test cases from CSV files +- **Pluggable providers** -- OpenAI (default), Anthropic, or bring your own `LLMClient` + +## How It Works + +

+ How fasteval works -- Decorate, Test, Score, Evaluate, Result +

## Quick Start @@ -96,6 +111,23 @@ def test_summary_quality(): fe.score(actual_output=summary, expected_output=reference) ``` +### Custom Criteria + +```python +@fe.criteria("Is the response empathetic and professional?") +def test_tone(): + response = agent("I'm frustrated with this product!") + fe.score(response) + +@fe.criteria( + "Does the response include a legal disclaimer?", + threshold=0.9, +) +def test_compliance(): + response = agent("Can I break my lease?") + fe.score(response) +``` + ### RAG Evaluation ```python @@ -117,7 +149,8 @@ def test_rag_pipeline(): def test_agent_tools(): result = agent.run("Book a flight to Paris") fe.score( - actual_tools=result.tool_calls, + result.response, + tool_calls=result.tool_calls, expected_tools=[ {"name": "search_flights", "args": {"destination": "Paris"}}, {"name": "book_flight"}, @@ -125,24 +158,54 @@ def test_agent_tools(): ) ``` +### Multi-Turn Conversations + +```python +@fe.context_retention(threshold=0.8) +@fe.conversation([ + {"query": "My name is Alice and I'm a vegetarian"}, + {"query": "Suggest a restaurant for me"}, + {"query": "What dietary restriction should they accommodate?"}, +]) +async def test_memory(query, expected, history): + response = await agent(query, history=history) + fe.score(response, input=query, history=history) +``` + ### Metric Stacks ```python +# Define a reusable metric stack +@fe.stack() @fe.correctness(threshold=0.8, weight=2.0) @fe.relevance(threshold=0.7, weight=1.0) @fe.coherence(threshold=0.6, weight=1.0) -def test_comprehensive(): +def quality_metrics(): + pass + +# Apply to multiple tests +@quality_metrics +def test_chatbot(): response = agent("Explain quantum computing") fe.score(response, expected_output=reference_answer, input="Explain quantum computing") + +@quality_metrics +def test_summarizer(): + summary = summarize(long_article) + fe.score(summary, expected_output=reference_summary) ``` ## Plugins | Plugin | Description | Install | |--------|-------------|---------| -| [fasteval-langfuse](./plugins/fasteval-langfuse/) | Evaluate Langfuse production traces with fasteval metrics | `pip install fasteval-langfuse` | -| [fasteval-langgraph](./plugins/fasteval-langgraph/) | Test harness for LangGraph agents | `pip install fasteval-langgraph` | -| [fasteval-observe](./plugins/fasteval-observe/) | Runtime monitoring with async sampling | `pip install fasteval-observe` | +| [fasteval-langfuse](https://fasteval.io/docs/plugins/langfuse/overview) | Evaluate Langfuse production traces with fasteval metrics | `pip install fasteval-langfuse` | +| [fasteval-langgraph](https://fasteval.io/docs/plugins/langgraph/overview) | Test harness for LangGraph agents | `pip install fasteval-langgraph` | +| [fasteval-observe](https://fasteval.io/docs/plugins/observe/overview) | Runtime monitoring with async sampling | `pip install fasteval-observe` | + +

+ Testing Pyramid for Agents -- layered testing strategy with fasteval-langgraph +

## Local Development @@ -150,12 +213,15 @@ def test_comprehensive(): # Install uv brew install uv -# Create virtual environment and install dependencies -uv sync --all-extras +# Create virtual environment and install all dependencies +uv sync --all-extras --group dev --group test # Run the test suite uv run tox +# Run tests with coverage +uv run pytest tests/ --cov=fasteval --cov-report=term -v + # Format code uv run black . uv run isort . @@ -166,17 +232,23 @@ uv run mypy . ## Documentation -Full documentation is available in the [docs/](./docs/) directory, covering: - -- [Getting Started](./docs/getting-started/) -- installation, quickstart -- [Core Concepts](./docs/core-concepts/) -- decorators, metrics, scoring, data sources -- [LLM Metrics](./docs/llm-metrics/) -- correctness, relevance, hallucination, and more -- [Deterministic Metrics](./docs/deterministic-metrics/) -- ROUGE, exact match, regex, JSON schema -- [RAG Metrics](./docs/rag-metrics/) -- faithfulness, contextual precision/recall -- [Conversation Metrics](./docs/conversation-metrics/) -- context retention, consistency -- [Multi-Modal](./docs/multimodal/) -- vision, audio, image generation evaluation -- [Plugins](./docs/plugins/) -- Langfuse, LangGraph, Observe -- [API Reference](./docs/api-reference/) -- decorators, evaluator, models, score +Full documentation is available at **[fasteval.io](https://fasteval.io)**. + +- [Getting Started](https://fasteval.io/docs/getting-started/quickstart) -- installation and quickstart guide +- [Why FastEval](https://fasteval.io/docs/getting-started/introduction/why-fasteval) -- motivation and design philosophy +- [Core Concepts](https://fasteval.io/docs/core-concepts/decorators) -- decorators, metrics, scoring, data sources +- [Concepts](https://fasteval.io/docs/concepts/llm-as-judge) -- LLM-as-judge, scoring thresholds, evaluation strategies +- [LLM Metrics](https://fasteval.io/docs/llm-metrics/correctness) -- correctness, relevance, hallucination, and more +- [Deterministic Metrics](https://fasteval.io/docs/deterministic-metrics/exact-match) -- ROUGE, exact match, regex, JSON schema +- [RAG Metrics](https://fasteval.io/docs/rag-metrics/faithfulness) -- faithfulness, contextual precision/recall +- [Tool Trajectory](https://fasteval.io/docs/tool-tranjectory-metrics/tool-call-accuracy) -- tool call accuracy, sequence, argument matching +- [Conversation Metrics](https://fasteval.io/docs/conversation-metrics/context-retention) -- context retention, consistency, topic drift +- [Multi-Modal](https://fasteval.io/docs/multimodal/overview) -- vision, audio, image generation evaluation +- [Human Review](https://fasteval.io/docs/human-review/overview) -- human-in-the-loop evaluation +- [Cookbooks](https://fasteval.io/docs/cookbooks/rag-pipeline) -- RAG pipelines, CI/CD setup, prompt regression, production monitoring +- [Plugins](https://fasteval.io/docs/plugins/langfuse/overview) -- Langfuse, LangGraph, Observe +- [Advanced](https://fasteval.io/docs/advanced/custom-metrics) -- custom metrics, providers, output collectors, traces +- [API Reference](https://fasteval.io/docs/api-reference/decorators) -- decorators, evaluator, models, score ## Contributing diff --git a/docs/assets/fasteval-overview.svg b/docs/assets/fasteval-overview.svg index cd5c336..27089bd 100644 --- a/docs/assets/fasteval-overview.svg +++ b/docs/assets/fasteval-overview.svg @@ -71,9 +71,9 @@ import fasteval as fe - @fe.correctness(threshold=0.8) + @fe.correctness(threshold=0.8) def test_my_agent(): - fe.score(response, "Expected Output") + fe.score(response, "Expected Output") diff --git a/fasteval-overview.png b/fasteval-overview.png new file mode 100644 index 0000000000000000000000000000000000000000..a97942f1f3fc5d167f7bcbf96ec4ab1e2bcef0f1 GIT binary patch literal 99144 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�Fyw#-ar#*?VIc@xcV-$m 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»-)%w$P@GZKszvm|=e|s7| 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 literal 0 HcmV?d00001 diff --git a/medium-article.md b/medium-article.md new file mode 100644 index 0000000..a445b20 --- /dev/null +++ b/medium-article.md @@ -0,0 +1,258 @@ +# We Got Tired of Writing the Same LLM Evaluation Code Over and Over, So We Open-Sourced Ours + +## Introducing fasteval, a decorator-first library that makes LLM testing feel like regular pytest + +![The evaluation journey: from non-deterministic LLM outputs to reliable engineering metrics](hero-evaluation-journey.png) + +--- + +I need to tell you about a problem that drove us crazy for months before we finally did something about it. + +Every team building with LLMs eventually hits the same wall. You ship your first agent or chatbot, it works great in demos, and then someone asks the obvious question: "How do we know this is actually good?" Not vibes-good. Measurably good. Good enough to not embarrass us in production. + +That question sent us down a rabbit hole. What we found at the bottom was a mess. + +## The testing problem that kept showing up + +Every team we talked to was solving this the same way, and badly. Someone would write a one-off script that calls the model a hundred times and dumps results into a spreadsheet. Someone else would build a custom evaluator with hard-coded prompts for LLM-as-judge. A third person would slap together some ROUGE scores and call it a day. + +None of it talked to each other. None of it ran in CI. And none of it caught the regression that shipped to production last Thursday. + +Testing LLMs is fundamentally weird compared to testing normal software. You can't just assert that output equals expected. Ask a model "What's the capital of France?" and you'll get "Paris" one time and "The capital of France is Paris, a city in Western Europe" the next. Both correct. Completely different strings. + +So teams end up building custom evaluation frameworks. We did too. Multiple times, actually. And each time we found ourselves writing the same patterns: prompt templates for LLM-as-judge, score parsing, threshold logic, result aggregation. Over and over, in slightly different shapes. + +At some point we looked at each other and said: why are we doing this? + +## What we actually wanted + +We had a pretty clear picture of the ideal tool. Something that felt like pytest, not like a new platform to learn. We wanted to stack evaluation criteria the way you stack decorators: readable, composable, obvious at a glance. Both LLM-based and deterministic evaluation in the same framework, because sometimes you need semantic judgment and sometimes you just need to check if the output is valid JSON. + +Nothing we found checked all those boxes. So we built it. + +## How fasteval works + +![How fasteval works: Decorate → Test → Score → Evaluate → Result](fasteval-overview.png) + +You decorate a test function with the metrics you care about, then call `fe.score()` with your model's output. + +```python +import fasteval as fe + +@fe.correctness(threshold=0.8) +@fe.relevance(threshold=0.7) +def test_qa_agent(): + response = my_agent("What is the capital of France?") + fe.score(response, expected_output="Paris", input="What is the capital of France?") +``` + +Run it with `pytest -v` and you get pass/fail for each metric, with scores and reasoning. No config files. No dashboard setup. No new CLI to learn. + +We went with decorators because they make the evaluation criteria visible right where the test is defined. When someone new joins the team and opens the test file, they can immediately tell what quality bar each test enforces. People mention this more than anything else when they try the library, so I think we got that decision right. + +## Stacking metrics is where it gets interesting + +Real-world evaluation is never one-dimensional. You don't just care about correctness. You also care about relevance, whether the response is toxic, whether it follows instructions. fasteval lets you stack all of that: + +```python +@fe.correctness(threshold=0.8, weight=2.0) +@fe.relevance(threshold=0.7, weight=1.0) +@fe.toxicity(threshold=0.95) +def test_customer_support_bot(): + response = support_bot("I want to cancel my subscription") + fe.score( + response, + expected_output="Acknowledge the request and provide cancellation steps", + input="I want to cancel my subscription" + ) +``` + +Each metric evaluates independently. Weights let you prioritize what matters most. The test fails if any metric drops below its threshold. + +We've got over 30 built-in metrics at this point: correctness, hallucination, coherence, conciseness, bias, instruction following, and a bunch more. We kept adding them because every time we thought "okay that's enough," someone on the team would need one more. + +## Not everything needs an LLM to evaluate + +This was an important design decision. LLM-as-judge is powerful but it's slow and it costs money. For a lot of checks you genuinely don't need it. Does the output contain a required keyword? Is it valid JSON? Does it match a regex pattern? You don't need GPT-4 to tell you that. + +We built deterministic metrics right into the same decorator system: + +```python +from pydantic import BaseModel + +class UserResponse(BaseModel): + name: str + age: int + email: str + +@fe.json(model=UserResponse) +def test_structured_output(): + output = my_agent("Create a user profile for Alice, age 30") + result = fe.score(output) + assert result.passed +``` + +No API key needed. Runs instantly. We use these for fast sanity checks on every commit, and save the heavier LLM evaluations for nightly runs. Having fast deterministic tests and thorough semantic tests living in the same framework, sharing the same decorator API, was something we didn't find in other tools. + +There's also `@fe.exact_match`, `@fe.contains`, `@fe.rouge`, and `@fe.regex`. Mix and match with LLM metrics however you want. + +## RAG evaluation was a big motivator + +Half the teams we work with are building RAG pipelines, and RAG is especially tricky to test. You need to evaluate retrieval quality and generation quality at the same time. Is the model sticking to the retrieved context or making stuff up? Are the right documents being pulled in the first place? + +```python +@fe.faithfulness(threshold=0.8) +@fe.contextual_precision(threshold=0.7) +def test_rag_pipeline(): + result = rag_pipeline("How does photosynthesis work?") + fe.score( + actual_output=result.answer, + context=result.retrieved_docs, + input="How does photosynthesis work?", + ) +``` + +Faithfulness measures whether the answer is grounded in the retrieved context. Contextual precision checks whether the retriever pulled the right documents. Throw `@fe.hallucination` on top and you've got a solid RAG evaluation suite in about ten lines of code. + +We've actually seen teams catch retrieval regressions with this setup that they'd been missing for weeks. One team had a broken chunking config that degraded recall by 15%, and their existing tests never flagged it because they were only checking the final answer. + +## Testing agent tool calls + +If your agent is supposed to search for flights and then book one, you need to verify it actually called those tools, in the right order, with the right arguments. Doing that by hand gets old fast. + +```python +@fe.tool_call_accuracy(threshold=0.9) +def test_booking_agent(): + result = agent.run("Book a flight to Paris") + fe.score( + actual_tools=result.tool_calls, + expected_tools=[ + {"name": "search_flights", "args": {"destination": "Paris"}}, + {"name": "book_flight"}, + ], + ) +``` + +Tool name matching, argument validation, sequence verification. We also have `@fe.tool_sequence` and `@fe.tool_args_match` for more granular control. + +## Testing LangGraph agents without losing your mind + +![Testing pyramid for agents: unit tests, integration tests, and end-to-end evaluation layers](testing-pyramid-agents.png) + +Okay, this one is close to my heart. + +If you're building agents with LangGraph, you know the pain. You've got a state graph with five or six nodes, a classifier, a retriever, a responder, maybe some routing logic, and testing the whole thing end-to-end is slow, flaky, and expensive. But testing nodes individually means ripping apart the graph and manually wiring up state. Nobody wants to do that. + +We built a test harness specifically for this. It wraps any compiled `StateGraph` and gives you a clean API to test the full flow, individual nodes, or anything in between. + +Full conversation testing is just `.chat()`: + +```python +from fasteval_langgraph import harness +import fasteval as fe + +graph = harness(compiled_graph) + +@fe.correctness(threshold=0.8) +async def test_support_agent(): + result = await graph.chat("How do I configure OAuth?") + fe.score(result.response, "Use OAuth 2.0...", input="How do I configure OAuth?") +``` + +The harness auto-detects whether your graph uses `MessagesState` or plain `TypedDict` and sets up sensible defaults. You don't configure anything for the common case. + +Where it gets really useful is node-level testing. Say you want to test just your classifier node without running the entire graph: + +```python +from langchain_core.messages import HumanMessage + +result = await graph.node("classifier").run( + messages=[HumanMessage(content="What is OAuth?")] +) + +assert result.updates.get("intent") == "FAQ" +assert result.goto == "rag" # Where the classifier routes to +assert result.execution_time_ms < 500 # Performance check +``` + +State updates, routing decision, execution timing. All from running one node in isolation. We use this pattern constantly when iterating on individual node logic because waiting for the whole graph to execute every time just kills your feedback loop. + +For conversational agents, multi-turn sessions keep state across messages: + +```python +async with graph.session() as s: + r1 = await s.chat("I need help with billing") + r2 = await s.chat("Actually, make that a refund") + + # State persists across the session + assert r2.state["call_count"] == 2 + assert len(s.history) == 2 +``` + +And mocking. If you need to test a node without its dependencies hitting real APIs: + +```python +from fasteval_langgraph import mock + +with graph.mocked( + mock("rag").updates({"docs": ["fake retrieval result"]}).goto("responder"), +): + result = await graph.chat("What is OAuth?") + # RAG node is mocked, everything else runs normally +``` + +Mocks auto-restore when the context manager exits. No cleanup code. + +One more thing worth mentioning: the harness captures a full execution trace. Which nodes ran, in what order, what each one produced, how long each took. When a test fails and you're trying to figure out which node in the graph screwed up, that trace is the first thing you'll reach for. + +Install it separately with `pip install fasteval-langgraph`. + +## Production monitoring and the other plugins + +Building fasteval as a standalone library was step one. But we knew people would need it in production too, not just in test suites. + +**fasteval-langfuse** lets you evaluate production traces from Langfuse. Pull traces, run them through your metrics, push scores back. We added smart sampling so you're not burning through API credits evaluating every single request. You can sample by percentage, token budget, or adaptive strategies. + +**fasteval-observe** does async runtime monitoring with configurable sampling. Lightweight way to keep an eye on quality in production without adding latency. + +Each plugin is a separate pip install, so you only pull in what you need. + +## Getting started + +```bash +pip install fasteval-core +export OPENAI_API_KEY=sk-your-key-here +``` + +Write a test file: + +```python +import fasteval as fe + +@fe.correctness(threshold=0.8) +def test_my_llm(): + response = call_your_model("What is 2 + 2?") + fe.score(response, expected_output="4", input="What is 2 + 2?") +``` + +Run it: + +```bash +pytest test_my_llm.py -v +``` + +Want HTML reports? `--fe-output=report.html`. Aggregate statistics? `--fe-summary`. Anthropic instead of OpenAI? Set `ANTHROPIC_API_KEY`. Local Ollama model? Also works. + +We support Python 3.10 through 3.14. Apache 2.0 licensed. + +## Why we open-sourced it + +Because we kept seeing the same pain everywhere. Every team we talked to was reinventing evaluation from scratch. Smart people spending weeks on infrastructure that already existed, except everyone's version was trapped inside their own codebase and nobody could benefit from each other's work. + +We figured open-sourcing ours would save people time. And honestly, we wanted the feedback. The library has gotten meaningfully better since we opened it up because people file issues about use cases we never thought of. + +The repo is active and we ship regularly. If you try it and something's broken or missing, open an issue. We read them. + +--- + +**GitHub**: [github.com/intuit/fasteval](https://github.com/intuit/fasteval) | **Docs**: [fasteval.io](https://fasteval.io) | **Install**: `pip install fasteval-core` diff --git a/pyproject.toml b/pyproject.toml index 3470a97..cc066b7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -31,7 +31,7 @@ dependencies = [ [project.urls] Homepage = "https://github.com/intuit/fasteval" Repository = "https://github.com/intuit/fasteval" -Documentation = "https://github.com/intuit/fasteval/tree/main/docs" +Documentation = "https://fasteval.io" Issues = "https://github.com/intuit/fasteval/issues" Changelog = "https://github.com/intuit/fasteval/blob/main/CHANGELOG.md" @@ -110,9 +110,40 @@ testpaths = [ "tests", ] looponfailroots = ["fasteval", "tests"] -addopts = "-p no:warnings -o log_cli=true --log-cli-level=INFO" +addopts = "-p no:warnings -p no:fasteval -o log_cli=true --log-cli-level=INFO" asyncio_mode = "auto" +[tool.coverage.run] +source = ["fasteval"] +omit = [ + "fasteval/__init__.py", + "fasteval/models/*", + "fasteval/metrics/vision.py", + "fasteval/metrics/multimodal.py", + "fasteval/metrics/audio.py", + "fasteval/metrics/__init__.py", + "fasteval/utils/image.py", + "fasteval/utils/audio.py", + "fasteval/utils/terminal_ui.py", + "fasteval/utils/__init__.py", + "fasteval/providers/base.py", + "fasteval/providers/__init__.py", + "fasteval/collectors/__init__.py", + "fasteval/collectors/reporters/__init__.py", + "fasteval/collectors/reporters/base.py", + "fasteval/core/__init__.py", + "fasteval/cache/__init__.py", + "fasteval/testing/__init__.py", +] + +[tool.coverage.report] +exclude_lines = [ + "pragma: no cover", + "if TYPE_CHECKING:", + "raise NotImplementedError", + "except ImportError", +] + [build-system] requires = ["uv_build>=0.10.0,<0.11.0"] build-backend = "uv_build" diff --git a/testing-pyramid-agents.png b/testing-pyramid-agents.png new file mode 100644 index 0000000000000000000000000000000000000000..af15bdf4cd1464c85348d17e6e1c183b7388d075 GIT binary patch literal 124215 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 MetricResult: + return MetricResult( + metric_name=self.name, + score=0.8, + passed=self._determine_pass(0.8), + threshold=self.threshold, + ) + + +class TestMetric: + def test_init(self): + m = ConcreteMetric(name="test", threshold=0.7, weight=2.0) + assert m.name == "test" + assert m.threshold == 0.7 + assert m.weight == 2.0 + + def test_determine_pass_above(self): + m = ConcreteMetric(name="test", threshold=0.5) + assert m._determine_pass(0.6) is True + + def test_determine_pass_equal(self): + m = ConcreteMetric(name="test", threshold=0.5) + assert m._determine_pass(0.5) is True + + def test_determine_pass_below(self): + m = ConcreteMetric(name="test", threshold=0.5) + assert m._determine_pass(0.4) is False + + def test_repr(self): + m = ConcreteMetric(name="test", threshold=0.7) + assert repr(m) == "ConcreteMetric(name='test', threshold=0.7)" + + @pytest.mark.asyncio + async def test_evaluate(self): + m = ConcreteMetric(name="test", threshold=0.5) + result = await m.evaluate(EvalInput(actual_output="hello")) + assert result.score == 0.8 + assert result.passed is True + + def test_abstract_cannot_instantiate(self): + with pytest.raises(TypeError): + Metric(name="test") diff --git a/tests/test_cache.py b/tests/test_cache.py new file mode 100644 index 0000000..3d66b00 --- /dev/null +++ b/tests/test_cache.py @@ -0,0 +1,171 @@ +"""Tests for fasteval.cache.memory.""" + +import pytest +from pydantic import BaseModel + +import fasteval.cache.memory as cache_module +from fasteval.cache.memory import ( + CacheStats, + MemoryCache, + clear_cache, + get_cache, +) + + +class SampleModel(BaseModel): + name: str + value: int + + +class TestCacheStats: + def test_hit_rate_with_data(self): + stats = CacheStats(hits=7, misses=3) + assert stats.hit_rate == 0.7 + + def test_hit_rate_zero_total(self): + stats = CacheStats(hits=0, misses=0) + assert stats.hit_rate == 0.0 + + +class TestMemoryCache: + def test_basic_get_set(self): + cache = MemoryCache(max_size=10) + cache.set("k1", "v1") + assert cache.get("k1") == "v1" + + def test_get_miss(self): + cache = MemoryCache(max_size=10) + assert cache.get("nonexistent") is None + + def test_lru_eviction(self): + cache = MemoryCache(max_size=2) + cache.set("a", 1) + cache.set("b", 2) + cache.set("c", 3) # evicts "a" + assert cache.get("a") is None + assert cache.get("b") == 2 + assert cache.get("c") == 3 + + def test_lru_access_order(self): + cache = MemoryCache(max_size=2) + cache.set("a", 1) + cache.set("b", 2) + cache.get("a") # moves "a" to most recent + cache.set("c", 3) # evicts "b" (least recent) + assert cache.get("a") == 1 + assert cache.get("b") is None + assert cache.get("c") == 3 + + def test_update_existing_key(self): + cache = MemoryCache(max_size=10) + cache.set("k1", "old") + cache.set("k1", "new") + assert cache.get("k1") == "new" + assert len(cache) == 1 + + def test_get_or_set_callable(self): + cache = MemoryCache(max_size=10) + result = cache.get_or_set("k1", lambda: 42) + assert result == 42 + # Second call returns cached value + result = cache.get_or_set("k1", lambda: 99) + assert result == 42 + + def test_get_or_set_non_callable(self): + cache = MemoryCache(max_size=10) + result = cache.get_or_set("k1", "static_value") + assert result == "static_value" + + def test_delete_existing(self): + cache = MemoryCache(max_size=10) + cache.set("k1", "v1") + assert cache.delete("k1") is True + assert cache.get("k1") is None + + def test_delete_missing(self): + cache = MemoryCache(max_size=10) + assert cache.delete("nonexistent") is False + + def test_clear(self): + cache = MemoryCache(max_size=10) + cache.set("a", 1) + cache.set("b", 2) + cache.clear() + assert len(cache) == 0 + assert cache.get("a") is None + + def test_stats_property(self): + cache = MemoryCache(max_size=100) + cache.set("k1", "v1") + cache.get("k1") # hit + cache.get("k2") # miss + stats = cache.stats + assert stats.hits == 1 + assert stats.misses == 1 + assert stats.size == 1 + assert stats.max_size == 100 + + def test_eviction_stats(self): + cache = MemoryCache(max_size=1) + cache.set("a", 1) + cache.set("b", 2) # evicts "a" + stats = cache.stats + assert stats.evictions == 1 + + def test_len(self): + cache = MemoryCache(max_size=10) + assert len(cache) == 0 + cache.set("a", 1) + assert len(cache) == 1 + + def test_contains(self): + cache = MemoryCache(max_size=10) + cache.set("a", 1) + assert "a" in cache + assert "b" not in cache + + def test_make_key_basic(self): + cache = MemoryCache() + key1 = cache._make_key("arg1", key="val") + key2 = cache._make_key("arg1", key="val") + key3 = cache._make_key("arg2", key="val") + assert key1 == key2 + assert key1 != key3 + + def test_make_key_with_pydantic_model(self): + cache = MemoryCache() + model = SampleModel(name="test", value=42) + key = cache._make_key(model) + assert isinstance(key, str) + assert len(key) == 64 # SHA256 hex digest + + def test_make_key_with_dict_and_list(self): + cache = MemoryCache() + key = cache._make_key({"a": [1, 2, 3]}) + assert isinstance(key, str) + + def test_unlimited_cache(self): + cache = MemoryCache(max_size=0) + for i in range(100): + cache.set(str(i), i) + assert len(cache) == 100 + + +class TestGlobalCache: + def setup_method(self): + cache_module._global_cache = None + + def test_get_cache_singleton(self): + c1 = get_cache() + c2 = get_cache() + assert c1 is c2 + + def test_clear_cache(self): + cache = get_cache() + cache.set("k1", "v1") + clear_cache() + assert cache.get("k1") is None + + def test_clear_cache_when_none(self): + cache_module._global_cache = None + clear_cache() # Should not raise diff --git a/tests/test_collector.py b/tests/test_collector.py new file mode 100644 index 0000000..bdf84c9 --- /dev/null +++ b/tests/test_collector.py @@ -0,0 +1,220 @@ +"""Tests for fasteval.collectors.collector and fasteval.collectors.summary.""" + +import json + +import pytest + +import fasteval.collectors.collector as collector_module +from fasteval.collectors.collector import ( + ResultCollector, + get_collector, + reset_collector, +) +from fasteval.collectors.summary import ( + EvalRunSummary, + MetricAggregate, + TestCaseSummary, +) +from fasteval.models.evaluation import EvalInput, EvalResult, MetricResult + + +def _make_result( + passed=True, aggregate_score=1.0, metrics=None, execution_time_ms=10.0, error=None +): + return EvalResult( + eval_input=EvalInput(actual_output="test"), + metric_results=metrics or [], + passed=passed, + aggregate_score=aggregate_score, + execution_time_ms=execution_time_ms, + error=error, + ) + + +def _make_metric(name="m1", score=0.8, passed=True, threshold=0.5): + return MetricResult( + metric_name=name, score=score, passed=passed, threshold=threshold + ) + + +# ── ResultCollector ────────────────────────────────────────────────────────── + + +class TestResultCollector: + def test_init(self): + collector = ResultCollector() + assert len(collector.results) == 0 + + def test_collect_and_results(self): + collector = ResultCollector() + r1 = _make_result() + r2 = _make_result(passed=False, aggregate_score=0.0) + collector.collect(r1, "test1") + collector.collect(r2, "test2") + assert len(collector.results) == 2 + + def test_results_is_copy(self): + collector = ResultCollector() + collector.collect(_make_result(), "test1") + results = collector.results + results.clear() + assert len(collector.results) == 1 + + def test_summary(self): + collector = ResultCollector() + collector.collect(_make_result(passed=True), "test1") + collector.collect(_make_result(passed=False, aggregate_score=0.0), "test2") + summary = collector.summary() + assert summary.total_tests == 2 + assert summary.passed_tests == 1 + assert summary.failed_tests == 1 + + def test_report_json(self): + collector = ResultCollector() + collector.collect(_make_result(), "test1") + content = collector.report("json") + parsed = json.loads(content) + assert "summary" in parsed + assert "results" in parsed + + def test_report_unknown_format(self): + collector = ResultCollector() + collector.collect(_make_result(), "test1") + with pytest.raises(ValueError, match="Unknown format"): + collector.report("xml") + + def test_register_reporter(self): + from fasteval.collectors.reporters.base import OutputReporter + + class CustomReporter(OutputReporter): + def generate(self, summary, results): + return "custom" + + collector = ResultCollector() + collector.register_reporter("custom", CustomReporter) + collector.collect(_make_result(), "test1") + content = collector.report("custom") + assert content == "custom" + + def test_reset(self): + collector = ResultCollector() + collector.collect(_make_result(), "test1") + collector.reset() + assert len(collector.results) == 0 + + def test_report_to_file(self, tmp_path): + collector = ResultCollector() + collector.collect(_make_result(), "test1") + filepath = str(tmp_path / "report.json") + collector.report("json", path=filepath) + with open(filepath) as f: + parsed = json.loads(f.read()) + assert "summary" in parsed + + def test_report_html(self): + collector = ResultCollector() + mr = _make_metric() + collector.collect(_make_result(metrics=[mr]), "test1") + content = collector.report("html") + assert "FastEval" in content + assert " 0 + + m2_agg = next(m for m in summary.metric_aggregates if m.metric_name == "m2") + assert m2_agg.count == 1 + assert m2_agg.std_score == 0.0 # Single value + + def test_test_summaries(self): + result = _make_result( + passed=False, + aggregate_score=0.4, + execution_time_ms=5.0, + error="failed", + ) + summary = EvalRunSummary.from_results([result], ["test_func"]) + assert len(summary.test_summaries) == 1 + ts = summary.test_summaries[0] + assert ts.test_name == "test_func" + assert ts.passed is False + assert ts.aggregate_score == 0.4 + assert ts.error == "failed" diff --git a/tests/test_conversation_metrics.py b/tests/test_conversation_metrics.py new file mode 100644 index 0000000..08c0b46 --- /dev/null +++ b/tests/test_conversation_metrics.py @@ -0,0 +1,105 @@ +"""Tests for fasteval.metrics.conversation.""" + +import json + +import pytest + +from fasteval.metrics.conversation import ( + ConsistencyMetric, + ContextRetentionMetric, + TopicDriftMetric, +) +from fasteval.models.evaluation import EvalInput + + +class MockLLMClient: + def __init__(self, score=0.85): + self.response = json.dumps( + {"score": score, "reasoning": "Mock conversation eval"} + ) + + async def invoke(self, messages): + return self.response + + +class TestContextRetentionMetric: + def test_default_name(self): + metric = ContextRetentionMetric(llm_client=MockLLMClient()) + assert metric.name == "context_retention" + + def test_prompt_includes_history(self): + metric = ContextRetentionMetric(llm_client=MockLLMClient()) + prompt = metric.get_evaluation_prompt( + EvalInput( + actual_output="Yes, I remember", + history=[ + {"role": "user", "content": "My name is Alice"}, + {"role": "assistant", "content": "Nice to meet you, Alice"}, + {"role": "user", "content": "What is my name?"}, + ], + ) + ) + assert "Alice" in prompt + + @pytest.mark.asyncio + async def test_evaluation(self): + metric = ContextRetentionMetric(llm_client=MockLLMClient(0.9), threshold=0.5) + result = await metric.evaluate( + EvalInput( + actual_output="Your name is Alice", + history=[ + {"role": "user", "content": "My name is Alice"}, + {"role": "assistant", "content": "Hello Alice"}, + ], + ) + ) + assert result.score == 0.9 + assert result.passed is True + + +class TestConsistencyMetric: + def test_default_name(self): + metric = ConsistencyMetric(llm_client=MockLLMClient()) + assert metric.name == "consistency" + + def test_default_binary_scoring(self): + metric = ConsistencyMetric(llm_client=MockLLMClient()) + assert metric.scoring_type == "binary" + + @pytest.mark.asyncio + async def test_evaluation(self): + # ConsistencyMetric uses binary scoring by default + # Score 0.8 >= 0.5 → binary 1.0 + metric = ConsistencyMetric(llm_client=MockLLMClient(0.8), threshold=0.5) + result = await metric.evaluate( + EvalInput( + actual_output="Paris is the capital", + history=[ + {"role": "user", "content": "What is the capital of France?"}, + {"role": "assistant", "content": "The capital is Paris"}, + ], + ) + ) + assert result.score == 1.0 # binary: 0.8 >= 0.5 → 1.0 + assert result.passed is True + + +class TestTopicDriftMetric: + def test_default_name(self): + metric = TopicDriftMetric(llm_client=MockLLMClient()) + assert metric.name == "topic_drift" + + @pytest.mark.asyncio + async def test_evaluation(self): + metric = TopicDriftMetric(llm_client=MockLLMClient(0.7), threshold=0.5) + result = await metric.evaluate( + EvalInput( + actual_output="About cooking", + history=[ + {"role": "user", "content": "Let's discuss cooking"}, + {"role": "assistant", "content": "Sure, what dish?"}, + ], + ) + ) + assert result.score == 0.7 + assert result.passed is True diff --git a/tests/test_decorators_extended.py b/tests/test_decorators_extended.py new file mode 100644 index 0000000..8740fc8 --- /dev/null +++ b/tests/test_decorators_extended.py @@ -0,0 +1,343 @@ +"""Tests for fasteval.core.decorators.""" + +import csv +import os +import tempfile + +import pytest +from pydantic import BaseModel + +# Import the public decorator functions +import fasteval.core.decorators as dec +from fasteval.core.decorators import ( + _attach_metric, + _metric_decorator_factory, + fasteval_HUMAN_REVIEW_ATTR, + fasteval_METRICS_ATTR, +) +from fasteval.models.config import MetricConfig + +# ── _attach_metric ─────────────────────────────────────────────────────────── + + +class TestAttachMetric: + def test_creates_attribute(self): + def my_func(): + pass + + config = MetricConfig(metric_type="test", name="test") + _attach_metric(my_func, config) + assert hasattr(my_func, fasteval_METRICS_ATTR) + assert len(getattr(my_func, fasteval_METRICS_ATTR)) == 1 + + def test_appends_to_existing(self): + def my_func(): + pass + + config1 = MetricConfig(metric_type="t1", name="n1") + config2 = MetricConfig(metric_type="t2", name="n2") + _attach_metric(my_func, config1) + _attach_metric(my_func, config2) + assert len(getattr(my_func, fasteval_METRICS_ATTR)) == 2 + + +# ── _metric_decorator_factory ──────────────────────────────────────────────── + + +class TestMetricDecoratorFactory: + def test_creates_working_decorator(self): + decorator_fn = _metric_decorator_factory("test_type", "test_name") + + @decorator_fn() + def my_func(): + pass + + configs = getattr(my_func, fasteval_METRICS_ATTR) + assert len(configs) == 1 + assert configs[0].metric_type == "test_type" + assert configs[0].name == "test_name" + + def test_threshold_override(self): + decorator_fn = _metric_decorator_factory("test", "test", default_threshold=0.5) + + @decorator_fn(threshold=0.9) + def my_func(): + pass + + configs = getattr(my_func, fasteval_METRICS_ATTR) + assert configs[0].threshold == 0.9 + + def test_weight_override(self): + decorator_fn = _metric_decorator_factory("test", "test") + + @decorator_fn(weight=2.5) + def my_func(): + pass + + configs = getattr(my_func, fasteval_METRICS_ATTR) + assert configs[0].weight == 2.5 + + def test_name_override(self): + decorator_fn = _metric_decorator_factory("test", "default_name") + + @decorator_fn(name="custom_name") + def my_func(): + pass + + configs = getattr(my_func, fasteval_METRICS_ATTR) + assert configs[0].name == "custom_name" + + def test_model_override(self): + decorator_fn = _metric_decorator_factory("test", "test") + + @decorator_fn(model="gpt-4o") + def my_func(): + pass + + configs = getattr(my_func, fasteval_METRICS_ATTR) + assert configs[0].llm_config == {"model": "gpt-4o"} + + def test_llm_client_passthrough(self): + class FakeClient: + async def invoke(self, messages): + return "" + + client = FakeClient() + decorator_fn = _metric_decorator_factory("test", "test") + + @decorator_fn(llm_client=client) + def my_func(): + pass + + configs = getattr(my_func, fasteval_METRICS_ATTR) + assert configs[0].llm_client is client + + +# ── All metric decorators ──────────────────────────────────────────────────── + + +class TestAllMetricDecorators: + """Test that each public decorator attaches the correct metric_type.""" + + # Simple decorators that take no required positional args + _simple_decorators = { + "correctness": dec.correctness, + "hallucination": dec.hallucination, + "relevance": dec.relevance, + "toxicity": dec.toxicity, + "bias": dec.bias, + "conciseness": dec.conciseness, + "coherence": dec.coherence, + "completeness": dec.completeness, + "helpfulness": dec.helpfulness, + "faithfulness": dec.faithfulness, + "contextual_precision": dec.contextual_precision, + "contextual_recall": dec.contextual_recall, + "answer_correctness": dec.answer_correctness, + "rouge": dec.rouge, + "exact_match": dec.exact_match, + "contains": dec.contains, + "tool_call_accuracy": dec.tool_call_accuracy, + "tool_sequence": dec.tool_sequence, + "tool_args_match": dec.tool_args_match, + "context_retention": dec.context_retention, + "consistency": dec.consistency, + "topic_drift": dec.topic_drift, + } + + @pytest.mark.parametrize( + "metric_type,decorator_fn", list(_simple_decorators.items()) + ) + def test_simple_decorator(self, metric_type, decorator_fn): + @decorator_fn() + def my_func(): + pass + + configs = getattr(my_func, fasteval_METRICS_ATTR) + assert len(configs) == 1 + assert configs[0].metric_type == metric_type + + def test_regex_decorator(self): + @dec.regex(pattern=r"\d+") + def my_func(): + pass + + configs = getattr(my_func, fasteval_METRICS_ATTR) + assert configs[0].metric_type == "regex" + + def test_criteria_decorator(self): + @dec.criteria("Is the response helpful?") + def my_func(): + pass + + configs = getattr(my_func, fasteval_METRICS_ATTR) + assert configs[0].metric_type == "criteria" + + def test_geval_decorator(self): + # geval is an alias for criteria + @dec.geval(criteria="Is the response helpful?") + def my_func(): + pass + + configs = getattr(my_func, fasteval_METRICS_ATTR) + assert configs[0].metric_type == "criteria" + + def test_instruction_following_decorator(self): + @dec.instruction_following(instructions=["Be concise", "Use examples"]) + def my_func(): + pass + + configs = getattr(my_func, fasteval_METRICS_ATTR) + assert configs[0].metric_type == "instruction_following" + + def test_json_decorator(self): + class User(BaseModel): + name: str + + @dec.json(model=User) + def my_func(): + pass + + configs = getattr(my_func, fasteval_METRICS_ATTR) + assert configs[0].metric_type == "json" + + +# ── Decorator stacking ─────────────────────────────────────────────────────── + + +class TestDecoratorStacking: + def test_multiple_decorators(self): + @dec.correctness() + @dec.relevance() + @dec.contains() + def my_func(): + pass + + configs = getattr(my_func, fasteval_METRICS_ATTR) + assert len(configs) == 3 + types = [c.metric_type for c in configs] + assert "correctness" in types + assert "relevance" in types + assert "contains" in types + + +# ── Data decorators ────────────────────────────────────────────────────────── + + +class TestCsvDecorator: + def test_csv_decorator(self): + with tempfile.NamedTemporaryFile( + mode="w", suffix=".csv", delete=False, newline="" + ) as f: + writer = csv.writer(f) + writer.writerow(["input", "expected"]) + writer.writerow(["q1", "a1"]) + writer.writerow(["q2", "a2"]) + csv_path = f.name + + try: + + @dec.csv(csv_path) + def my_func(input, expected): + pass + + assert callable(my_func) + assert hasattr(my_func, dec.fasteval_DATA_ATTR) + finally: + os.unlink(csv_path) + + +# ── Human review decorator ─────────────────────────────────────────────────── + + +class TestHumanReviewDecorator: + def test_attaches_config(self): + @dec.human_review(prompt="Review this", required=True, threshold=0.8) + def my_func(): + pass + + assert hasattr(my_func, fasteval_HUMAN_REVIEW_ATTR) + config = getattr(my_func, fasteval_HUMAN_REVIEW_ATTR) + assert config["prompt"] == "Review this" + assert config["required"] is True + assert config["threshold"] == 0.8 + + +# ── Stack decorator ────────────────────────────────────────────────────────── + + +class TestConversationDecorator: + def test_sync_conversation(self): + results = [] + + @dec.conversation( + [ + {"query": "Hello", "expected": "Hi"}, + {"query": "Bye", "expected": "Goodbye"}, + ] + ) + def my_func(query, expected, history): + results.append({"query": query, "expected": expected, "history": history}) + return None + + my_func() + assert len(results) == 2 + assert results[0]["query"] == "Hello" + assert results[0]["history"] == [] + assert results[1]["query"] == "Bye" + + @pytest.mark.asyncio + async def test_async_conversation(self): + results = [] + + @dec.conversation( + [ + {"query": "Hello"}, + {"query": "Bye"}, + ] + ) + async def my_func(query, expected, history): + results.append({"query": query, "history": history}) + + await my_func() + assert len(results) == 2 + + def test_conversation_preserves_metrics(self): + @dec.correctness() + @dec.conversation([{"query": "Hi"}]) + def my_func(query, expected, history): + pass + + assert hasattr(my_func, fasteval_METRICS_ATTR) + + +class TestCriteriaWithEvaluationSteps: + def test_criteria_with_steps(self): + @dec.criteria("Be formal", evaluation_steps=["Step1", "Step2"]) + def my_func(): + pass + + configs = getattr(my_func, fasteval_METRICS_ATTR) + assert configs[0].config["criteria"] == "Be formal" + assert configs[0].config["evaluation_steps"] == ["Step1", "Step2"] + + +class TestStackDecorator: + def test_stack_combines_metrics(self): + # @fe.stack() goes at the TOP, captures decorators below it + @dec.stack() + @dec.correctness() + @dec.relevance() + def my_stack(): + pass + + # my_stack is now a decorator itself + @my_stack + def my_func(): + pass + + configs = getattr(my_func, fasteval_METRICS_ATTR) + assert len(configs) == 2 + types = [c.metric_type for c in configs] + assert "correctness" in types + assert "relevance" in types diff --git a/tests/test_deterministic_metrics.py b/tests/test_deterministic_metrics.py new file mode 100644 index 0000000..3efb0c2 --- /dev/null +++ b/tests/test_deterministic_metrics.py @@ -0,0 +1,695 @@ +"""Tests for fasteval.metrics.deterministic.""" + +import re + +import pytest +from pydantic import BaseModel + +from fasteval.metrics.deterministic import ( + ContainsMetric, + ExactMatchMetric, + JsonMetric, + RegexMetric, + RougeMetric, + ToolArgsMatchMetric, + ToolCallAccuracyMetric, + ToolSequenceMetric, + _match_tool_name, +) +from fasteval.models.evaluation import EvalInput, ExpectedTool, ToolCall + + +class UserModel(BaseModel): + name: str + age: int + + +# ── RougeMetric ────────────────────────────────────────────────────────────── + + +class TestRougeMetric: + @pytest.mark.asyncio + async def test_high_similarity(self): + metric = RougeMetric(threshold=0.5) + result = await metric.evaluate( + EvalInput( + actual_output="the cat sat on the mat", + expected_output="the cat sat on the mat", + ) + ) + assert result.score == 1.0 + assert result.passed is True + + @pytest.mark.asyncio + async def test_low_similarity(self): + metric = RougeMetric(threshold=0.9) + result = await metric.evaluate( + EvalInput( + actual_output="completely different text", + expected_output="the cat sat on the mat", + ) + ) + assert result.score < 0.9 + assert result.passed is False + + @pytest.mark.asyncio + async def test_missing_actual(self): + metric = RougeMetric() + result = await metric.evaluate( + EvalInput(actual_output=None, expected_output="expected") + ) + assert result.score == 0.0 + assert result.passed is False + + @pytest.mark.asyncio + async def test_missing_expected(self): + metric = RougeMetric() + result = await metric.evaluate( + EvalInput(actual_output="actual", expected_output=None) + ) + assert result.score == 0.0 + + @pytest.mark.asyncio + async def test_details_include_precision_recall(self): + metric = RougeMetric(threshold=0.3) + result = await metric.evaluate( + EvalInput( + actual_output="the cat sat on the mat", + expected_output="the cat sat on the mat", + ) + ) + assert "precision" in result.details + assert "recall" in result.details + assert "fmeasure" in result.details + + def test_custom_name(self): + metric = RougeMetric(name="my_rouge", rouge_type="rouge1") + assert metric.name == "my_rouge" + assert metric.rouge_type == "rouge1" + + +# ── ExactMatchMetric ───────────────────────────────────────────────────────── + + +class TestExactMatchMetric: + @pytest.mark.asyncio + async def test_exact_match(self): + metric = ExactMatchMetric() + result = await metric.evaluate( + EvalInput(actual_output="Hello World", expected_output="hello world") + ) + assert result.score == 1.0 + + @pytest.mark.asyncio + async def test_case_sensitive(self): + metric = ExactMatchMetric(case_sensitive=True) + result = await metric.evaluate( + EvalInput(actual_output="Hello", expected_output="hello") + ) + assert result.score == 0.0 + + @pytest.mark.asyncio + async def test_normalize_whitespace(self): + metric = ExactMatchMetric() + result = await metric.evaluate( + EvalInput(actual_output="hello world", expected_output="hello world") + ) + assert result.score == 1.0 + + @pytest.mark.asyncio + async def test_no_match(self): + metric = ExactMatchMetric() + result = await metric.evaluate( + EvalInput(actual_output="yes", expected_output="no") + ) + assert result.score == 0.0 + assert result.passed is False + + @pytest.mark.asyncio + async def test_missing_output(self): + metric = ExactMatchMetric() + result = await metric.evaluate( + EvalInput(actual_output=None, expected_output="expected") + ) + assert result.score == 0.0 + + +# ── ContainsMetric ─────────────────────────────────────────────────────────── + + +class TestContainsMetric: + @pytest.mark.asyncio + async def test_contains(self): + metric = ContainsMetric() + result = await metric.evaluate( + EvalInput( + actual_output="The answer is 42 indeed", + expected_output="42", + ) + ) + assert result.score == 1.0 + + @pytest.mark.asyncio + async def test_does_not_contain(self): + metric = ContainsMetric() + result = await metric.evaluate( + EvalInput( + actual_output="The answer is unknown", + expected_output="42", + ) + ) + assert result.score == 0.0 + + @pytest.mark.asyncio + async def test_case_insensitive(self): + metric = ContainsMetric(case_sensitive=False) + result = await metric.evaluate( + EvalInput(actual_output="HELLO WORLD", expected_output="hello") + ) + assert result.score == 1.0 + + @pytest.mark.asyncio + async def test_case_sensitive(self): + metric = ContainsMetric(case_sensitive=True) + result = await metric.evaluate( + EvalInput(actual_output="HELLO WORLD", expected_output="hello") + ) + assert result.score == 0.0 + + @pytest.mark.asyncio + async def test_missing_output(self): + metric = ContainsMetric() + result = await metric.evaluate( + EvalInput(actual_output=None, expected_output="test") + ) + assert result.score == 0.0 + + +# ── JsonMetric ─────────────────────────────────────────────────────────────── + + +class TestJsonMetric: + @pytest.mark.asyncio + async def test_valid_json(self): + metric = JsonMetric(model=UserModel) + result = await metric.evaluate( + EvalInput(actual_output='{"name": "Alice", "age": 30}') + ) + assert result.score == 1.0 + assert result.passed is True + + @pytest.mark.asyncio + async def test_invalid_json_syntax(self): + metric = JsonMetric(model=UserModel) + result = await metric.evaluate(EvalInput(actual_output="{not valid json}")) + assert result.score == 0.0 + assert result.passed is False + + @pytest.mark.asyncio + async def test_schema_validation_failure(self): + metric = JsonMetric(model=UserModel) + result = await metric.evaluate(EvalInput(actual_output='{"name": "Alice"}')) + assert result.score == 0.0 + assert "validation" in result.details.get("error_type", "") + + @pytest.mark.asyncio + async def test_missing_output(self): + metric = JsonMetric(model=UserModel) + result = await metric.evaluate(EvalInput(actual_output=None)) + assert result.score == 0.0 + + +# ── RegexMetric ────────────────────────────────────────────────────────────── + + +class TestRegexMetric: + @pytest.mark.asyncio + async def test_full_match(self): + metric = RegexMetric(pattern=r"\d{3}-\d{4}") + result = await metric.evaluate(EvalInput(actual_output="123-4567")) + assert result.score == 1.0 + + @pytest.mark.asyncio + async def test_full_match_fails(self): + metric = RegexMetric(pattern=r"\d{3}-\d{4}") + result = await metric.evaluate(EvalInput(actual_output="phone: 123-4567")) + assert result.score == 0.0 + + @pytest.mark.asyncio + async def test_search_match(self): + metric = RegexMetric(pattern=r"\d{3}-\d{4}", full_match=False) + result = await metric.evaluate(EvalInput(actual_output="phone: 123-4567")) + assert result.score == 1.0 + + @pytest.mark.asyncio + async def test_no_match(self): + metric = RegexMetric(pattern=r"\d+", full_match=False) + result = await metric.evaluate(EvalInput(actual_output="no digits here")) + assert result.score == 0.0 + + @pytest.mark.asyncio + async def test_flags_ignorecase(self): + metric = RegexMetric(pattern=r"^yes$", flags=re.IGNORECASE) + result = await metric.evaluate(EvalInput(actual_output="YES")) + assert result.score == 1.0 + + @pytest.mark.asyncio + async def test_missing_output(self): + metric = RegexMetric(pattern=r"\d+") + result = await metric.evaluate(EvalInput(actual_output=None)) + assert result.score == 0.0 + + @pytest.mark.asyncio + async def test_match_details(self): + metric = RegexMetric(pattern=r"\d+", full_match=False) + result = await metric.evaluate(EvalInput(actual_output="abc123def")) + assert result.details["match"] == "123" + assert result.details["match_start"] == 3 + + +# ── _match_tool_name ───────────────────────────────────────────────────────── + + +class TestMatchToolName: + def test_exact_match(self): + assert _match_tool_name("search_flights", "search_flights") is True + + def test_wildcard_prefix(self): + assert _match_tool_name("search_flights", "search_*") is True + + def test_wildcard_suffix(self): + assert _match_tool_name("search_flights", "*_flights") is True + + def test_no_match(self): + assert _match_tool_name("search_flights", "book_*") is False + + +# ── ToolCallAccuracyMetric ─────────────────────────────────────────────────── + + +class TestToolCallAccuracyMetric: + @pytest.mark.asyncio + async def test_all_tools_match(self): + metric = ToolCallAccuracyMetric(threshold=0.8) + result = await metric.evaluate( + EvalInput( + actual_output="result", + tool_calls=[ToolCall(name="search"), ToolCall(name="book")], + expected_tools=[ + ExpectedTool(name="search"), + ExpectedTool(name="book"), + ], + ) + ) + assert result.score == 1.0 + assert result.passed is True + + @pytest.mark.asyncio + async def test_missing_required_tool(self): + metric = ToolCallAccuracyMetric(threshold=0.8) + result = await metric.evaluate( + EvalInput( + actual_output="result", + tool_calls=[ToolCall(name="search")], + expected_tools=[ + ExpectedTool(name="search"), + ExpectedTool(name="book"), + ], + ) + ) + assert result.score < 1.0 + + @pytest.mark.asyncio + async def test_extra_tools_penalized(self): + metric = ToolCallAccuracyMetric(threshold=0.8, ignore_extra=False) + result = await metric.evaluate( + EvalInput( + actual_output="result", + tool_calls=[ + ToolCall(name="search"), + ToolCall(name="book"), + ToolCall(name="cancel"), + ], + expected_tools=[ + ExpectedTool(name="search"), + ExpectedTool(name="book"), + ], + ) + ) + # 2 matched / max(2 required, 3 actual) = 2/3 + assert abs(result.score - 2 / 3) < 0.01 + + @pytest.mark.asyncio + async def test_ignore_extra(self): + metric = ToolCallAccuracyMetric(threshold=0.8, ignore_extra=True) + result = await metric.evaluate( + EvalInput( + actual_output="result", + tool_calls=[ + ToolCall(name="search"), + ToolCall(name="book"), + ToolCall(name="cancel"), + ], + expected_tools=[ + ExpectedTool(name="search"), + ExpectedTool(name="book"), + ], + ) + ) + assert result.score == 1.0 + + @pytest.mark.asyncio + async def test_wildcard_matching(self): + metric = ToolCallAccuracyMetric() + result = await metric.evaluate( + EvalInput( + actual_output="result", + tool_calls=[ToolCall(name="search_flights")], + expected_tools=[ExpectedTool(name="search_*")], + ) + ) + assert result.score == 1.0 + + @pytest.mark.asyncio + async def test_no_expected_tools_no_actual(self): + metric = ToolCallAccuracyMetric() + result = await metric.evaluate( + EvalInput(actual_output="result", tool_calls=[], expected_tools=[]) + ) + assert result.score == 1.0 + + @pytest.mark.asyncio + async def test_no_expected_with_actual(self): + metric = ToolCallAccuracyMetric() + result = await metric.evaluate( + EvalInput( + actual_output="result", + tool_calls=[ToolCall(name="search")], + expected_tools=[], + ) + ) + assert result.score == 0.0 + + +# ── ToolSequenceMetric ─────────────────────────────────────────────────────── + + +class TestToolSequenceMetric: + @pytest.mark.asyncio + async def test_strict_exact_match(self): + metric = ToolSequenceMetric(strict=True) + result = await metric.evaluate( + EvalInput( + actual_output="result", + tool_calls=[ToolCall(name="a"), ToolCall(name="b"), ToolCall(name="c")], + expected_tools=[ + ExpectedTool(name="a"), + ExpectedTool(name="b"), + ExpectedTool(name="c"), + ], + ) + ) + assert result.score == 1.0 + + @pytest.mark.asyncio + async def test_strict_mismatch(self): + metric = ToolSequenceMetric(strict=True) + result = await metric.evaluate( + EvalInput( + actual_output="result", + tool_calls=[ToolCall(name="b"), ToolCall(name="a")], + expected_tools=[ + ExpectedTool(name="a"), + ExpectedTool(name="b"), + ], + ) + ) + assert result.score == 0.0 + + @pytest.mark.asyncio + async def test_lcs_scoring(self): + metric = ToolSequenceMetric(strict=False) + result = await metric.evaluate( + EvalInput( + actual_output="result", + tool_calls=[ + ToolCall(name="a"), + ToolCall(name="c"), + ToolCall(name="b"), + ], + expected_tools=[ + ExpectedTool(name="a"), + ExpectedTool(name="b"), + ExpectedTool(name="c"), + ], + ) + ) + # LCS of [a, c, b] vs [a, b, c] -> LCS len 2 / max(3, 3) = 2/3 + assert result.score > 0.0 + assert result.score < 1.0 + + @pytest.mark.asyncio + async def test_no_expected(self): + metric = ToolSequenceMetric() + result = await metric.evaluate( + EvalInput(actual_output="result", tool_calls=[], expected_tools=[]) + ) + assert result.score == 1.0 + + @pytest.mark.asyncio + async def test_no_required_tools(self): + metric = ToolSequenceMetric() + result = await metric.evaluate( + EvalInput( + actual_output="result", + tool_calls=[ToolCall(name="a")], + expected_tools=[ + ExpectedTool(name="a", required=False), + ], + ) + ) + assert result.score == 1.0 + + +# ── ToolArgsMatchMetric ────────────────────────────────────────────────────── + + +class TestToolArgsMatchMetric: + @pytest.mark.asyncio + async def test_all_args_match(self): + metric = ToolArgsMatchMetric() + result = await metric.evaluate( + EvalInput( + actual_output="result", + tool_calls=[ + ToolCall( + name="search", arguments={"dest": "NYC", "date": "2024-01-01"} + ) + ], + expected_tools=[ + ExpectedTool( + name="search", args={"dest": "NYC", "date": "2024-01-01"} + ) + ], + ) + ) + assert result.score == 1.0 + + @pytest.mark.asyncio + async def test_value_mismatch(self): + metric = ToolArgsMatchMetric() + result = await metric.evaluate( + EvalInput( + actual_output="result", + tool_calls=[ToolCall(name="search", arguments={"dest": "LAX"})], + expected_tools=[ExpectedTool(name="search", args={"dest": "NYC"})], + ) + ) + assert result.score == 0.0 + + @pytest.mark.asyncio + async def test_missing_arg(self): + metric = ToolArgsMatchMetric() + result = await metric.evaluate( + EvalInput( + actual_output="result", + tool_calls=[ToolCall(name="search", arguments={})], + expected_tools=[ExpectedTool(name="search", args={"dest": "NYC"})], + ) + ) + assert result.score == 0.0 + + @pytest.mark.asyncio + async def test_tool_not_called(self): + metric = ToolArgsMatchMetric() + result = await metric.evaluate( + EvalInput( + actual_output="result", + tool_calls=[], + expected_tools=[ExpectedTool(name="search", args={"dest": "NYC"})], + ) + ) + assert result.score == 0.0 + + @pytest.mark.asyncio + async def test_no_expected_args(self): + metric = ToolArgsMatchMetric() + result = await metric.evaluate( + EvalInput( + actual_output="result", + tool_calls=[ToolCall(name="search", arguments={"dest": "NYC"})], + expected_tools=[ExpectedTool(name="search", args={})], + ) + ) + assert result.score == 1.0 + + @pytest.mark.asyncio + async def test_no_expected_tools(self): + metric = ToolArgsMatchMetric() + result = await metric.evaluate( + EvalInput(actual_output="result", tool_calls=[], expected_tools=[]) + ) + assert result.score == 1.0 + + @pytest.mark.asyncio + async def test_numeric_comparison(self): + metric = ToolArgsMatchMetric() + result = await metric.evaluate( + EvalInput( + actual_output="result", + tool_calls=[ToolCall(name="calc", arguments={"value": 3.14})], + expected_tools=[ExpectedTool(name="calc", args={"value": 3.14})], + ) + ) + assert result.score == 1.0 + + @pytest.mark.asyncio + async def test_string_case_insensitive(self): + metric = ToolArgsMatchMetric() + result = await metric.evaluate( + EvalInput( + actual_output="result", + tool_calls=[ToolCall(name="search", arguments={"dest": "nyc"})], + expected_tools=[ExpectedTool(name="search", args={"dest": "NYC"})], + ) + ) + assert result.score == 1.0 + + @pytest.mark.asyncio + async def test_none_expected_value(self): + metric = ToolArgsMatchMetric() + result = await metric.evaluate( + EvalInput( + actual_output="result", + tool_calls=[ToolCall(name="search", arguments={"dest": "anything"})], + expected_tools=[ExpectedTool(name="search", args={"dest": None})], + ) + ) + assert result.score == 1.0 + + @pytest.mark.asyncio + async def test_numeric_tolerance(self): + metric = ToolArgsMatchMetric() + result = await metric.evaluate( + EvalInput( + actual_output="result", + tool_calls=[ToolCall(name="calc", arguments={"value": 3.14000001})], + expected_tools=[ExpectedTool(name="calc", args={"value": 3.14})], + ) + ) + assert result.score == 1.0 + + @pytest.mark.asyncio + async def test_multiple_tools_partial_match(self): + metric = ToolArgsMatchMetric() + result = await metric.evaluate( + EvalInput( + actual_output="result", + tool_calls=[ + ToolCall(name="a", arguments={"x": 1}), + ToolCall(name="b", arguments={"y": "wrong"}), + ], + expected_tools=[ + ExpectedTool(name="a", args={"x": 1}), + ExpectedTool(name="b", args={"y": "correct"}), + ], + ) + ) + assert result.score == 0.5 + + +# ── RougeMetric additional ─────────────────────────────────────────────────── + + +class TestRougeMetricAdditional: + @pytest.mark.asyncio + async def test_partial_overlap(self): + metric = RougeMetric(threshold=0.3) + result = await metric.evaluate( + EvalInput( + actual_output="the quick brown fox", + expected_output="the slow brown dog", + ) + ) + assert 0.0 < result.score < 1.0 + assert result.passed is True + + def test_default_name(self): + metric = RougeMetric() + assert metric.name == "rouge" + + +# ── ExactMatch additional ──────────────────────────────────────────────────── + + +class TestExactMatchAdditional: + @pytest.mark.asyncio + async def test_no_normalize(self): + metric = ExactMatchMetric(normalize=False, case_sensitive=False) + result = await metric.evaluate( + EvalInput(actual_output="hello world", expected_output="hello world") + ) + assert result.score == 0.0 # Extra spaces not normalized + + def test_default_name(self): + metric = ExactMatchMetric() + assert metric.name == "exact_match" + + +# ── RegexMetric additional ─────────────────────────────────────────────────── + + +class TestRegexMetricAdditional: + @pytest.mark.asyncio + async def test_multiline(self): + metric = RegexMetric(pattern=r"hello", flags=re.MULTILINE, full_match=False) + result = await metric.evaluate(EvalInput(actual_output="foo\nhello\nbar")) + assert result.score == 1.0 + + def test_default_name(self): + metric = RegexMetric(pattern=r"\d+") + assert metric.name == "regex" + + +# ── ToolSequence additional ────────────────────────────────────────────────── + + +class TestToolSequenceAdditional: + @pytest.mark.asyncio + async def test_empty_actual_tools(self): + metric = ToolSequenceMetric(strict=True) + result = await metric.evaluate( + EvalInput( + actual_output="result", + tool_calls=[], + expected_tools=[ExpectedTool(name="a")], + ) + ) + assert result.score == 0.0 + + @pytest.mark.asyncio + async def test_lcs_empty_sequences(self): + metric = ToolSequenceMetric(strict=False) + # Test internal LCS with empty sequences + assert metric._longest_common_subsequence([], ["a"]) == 0 + assert metric._longest_common_subsequence(["a"], []) == 0 diff --git a/tests/test_evaluator.py b/tests/test_evaluator.py new file mode 100644 index 0000000..bc93313 --- /dev/null +++ b/tests/test_evaluator.py @@ -0,0 +1,324 @@ +"""Tests for fasteval.core.evaluator.""" + +import json + +import pytest + +from fasteval.core.evaluator import ( + METRIC_REGISTRY, + Evaluator, + EvaluatorConfig, + create_evaluator, +) +from fasteval.metrics.base import Metric +from fasteval.models.config import MetricConfig +from fasteval.models.evaluation import EvalInput, MetricResult + + +class MockLLMClient: + async def invoke(self, messages): + return json.dumps({"score": 0.9, "reasoning": "Mock"}) + + +# ── EvaluatorConfig ────────────────────────────────────────────────────────── + + +class TestEvaluatorConfig: + def test_defaults(self): + config = EvaluatorConfig() + assert config.fail_fast is False + assert config.parallel is True + assert config.cache_enabled is True + + def test_custom(self): + config = EvaluatorConfig(fail_fast=True, parallel=False) + assert config.fail_fast is True + assert config.parallel is False + + +# ── Evaluator._create_metric ───────────────────────────────────────────────── + + +class TestEvaluatorCreateMetric: + def test_standard_deterministic_metric(self): + evaluator = Evaluator() + config = MetricConfig(metric_type="exact_match", name="em", threshold=1.0) + metric = evaluator._create_metric(config) + assert metric.name == "em" + assert metric.threshold == 1.0 + + def test_custom_metric_with_instance(self): + class MyMetric(Metric): + async def evaluate(self, eval_input): + return MetricResult( + metric_name="custom", score=1.0, passed=True, threshold=0.5 + ) + + instance = MyMetric(name="custom") + evaluator = Evaluator() + config = MetricConfig( + metric_type="custom", + name="custom", + config={"instance": instance}, + ) + metric = evaluator._create_metric(config) + assert metric is instance + + def test_unknown_metric_type(self): + evaluator = Evaluator() + config = MetricConfig(metric_type="nonexistent", name="bad") + with pytest.raises(ValueError, match="Unknown metric type"): + evaluator._create_metric(config) + + def test_json_metric_pydantic_model(self): + from pydantic import BaseModel + + class User(BaseModel): + name: str + + evaluator = Evaluator() + config = MetricConfig( + metric_type="json", + name="json_check", + config={"pydantic_model": User}, + ) + metric = evaluator._create_metric(config) + assert metric.model is User + + def test_criteria_metric(self): + evaluator = Evaluator() + config = MetricConfig( + metric_type="criteria", + name="criteria_check", + config={"criteria": "Be formal"}, + llm_client=MockLLMClient(), + ) + metric = evaluator._create_metric(config) + assert metric.criteria == "Be formal" + + def test_criteria_with_evaluation_steps(self): + evaluator = Evaluator() + config = MetricConfig( + metric_type="geval", + name="geval_check", + config={ + "criteria": "test", + "evaluation_steps": ["Step 1"], + }, + llm_client=MockLLMClient(), + ) + metric = evaluator._create_metric(config) + assert metric.evaluation_steps == ["Step 1"] + + def test_instruction_following_metric(self): + evaluator = Evaluator() + config = MetricConfig( + metric_type="instruction_following", + name="if_check", + config={"instructions": "Be concise"}, + llm_client=MockLLMClient(), + ) + metric = evaluator._create_metric(config) + assert metric.instructions == "Be concise" + + def test_with_llm_client(self): + client = MockLLMClient() + evaluator = Evaluator() + config = MetricConfig( + metric_type="correctness", + name="corr", + llm_client=client, + ) + metric = evaluator._create_metric(config) + assert metric._llm_client is client + + def test_with_llm_config_model(self): + evaluator = Evaluator() + config = MetricConfig( + metric_type="correctness", + name="corr", + llm_config={"model": "gpt-4o"}, + ) + metric = evaluator._create_metric(config) + assert metric._model_override == "gpt-4o" + + +# ── Evaluator.evaluate ─────────────────────────────────────────────────────── + + +class TestEvaluatorEvaluate: + @pytest.mark.asyncio + async def test_single_metric_pass(self): + evaluator = Evaluator() + result = await evaluator.evaluate( + eval_input=EvalInput(actual_output="hello", expected_output="hello"), + metrics=[MetricConfig(metric_type="exact_match", name="em", threshold=1.0)], + ) + assert result.passed is True + assert result.aggregate_score == 1.0 + assert len(result.metric_results) == 1 + + @pytest.mark.asyncio + async def test_single_metric_fail(self): + evaluator = Evaluator() + result = await evaluator.evaluate( + eval_input=EvalInput(actual_output="yes", expected_output="no"), + metrics=[MetricConfig(metric_type="exact_match", name="em", threshold=1.0)], + ) + assert result.passed is False + assert result.aggregate_score == 0.0 + + @pytest.mark.asyncio + async def test_parallel_execution(self): + evaluator = Evaluator(EvaluatorConfig(parallel=True)) + result = await evaluator.evaluate( + eval_input=EvalInput( + actual_output="hello world", expected_output="hello world" + ), + metrics=[ + MetricConfig(metric_type="exact_match", name="em1", threshold=1.0), + MetricConfig(metric_type="contains", name="contains1", threshold=1.0), + ], + ) + assert result.passed is True + assert len(result.metric_results) == 2 + + @pytest.mark.asyncio + async def test_sequential_fail_fast(self): + evaluator = Evaluator(EvaluatorConfig(parallel=False, fail_fast=True)) + result = await evaluator.evaluate( + eval_input=EvalInput(actual_output="yes", expected_output="no"), + metrics=[ + MetricConfig(metric_type="exact_match", name="em1", threshold=1.0), + MetricConfig(metric_type="exact_match", name="em2", threshold=1.0), + ], + ) + # fail_fast should stop after first failure + assert result.passed is False + assert len(result.metric_results) == 1 + + @pytest.mark.asyncio + async def test_weighted_aggregate(self): + evaluator = Evaluator() + result = await evaluator.evaluate( + eval_input=EvalInput(actual_output="hello", expected_output="hello"), + metrics=[ + MetricConfig( + metric_type="exact_match", name="em", threshold=1.0, weight=2.0 + ), + MetricConfig( + metric_type="contains", name="ct", threshold=1.0, weight=1.0 + ), + ], + ) + # Both pass with score 1.0: (1.0*2 + 1.0*1) / 3 = 1.0 + assert result.aggregate_score == 1.0 + + @pytest.mark.asyncio + async def test_execution_time_recorded(self): + evaluator = Evaluator() + result = await evaluator.evaluate( + eval_input=EvalInput(actual_output="a", expected_output="a"), + metrics=[MetricConfig(metric_type="exact_match", name="em")], + ) + assert result.execution_time_ms >= 0 + + @pytest.mark.asyncio + async def test_reference_id_preserved(self): + evaluator = Evaluator() + result = await evaluator.evaluate( + eval_input=EvalInput( + actual_output="a", + expected_output="a", + reference_id="ref-123", + ), + metrics=[MetricConfig(metric_type="exact_match", name="em")], + ) + assert result.reference_id == "ref-123" + + +# ── Evaluator._evaluate_metric ─────────────────────────────────────────────── + + +class TestEvaluatorEvaluateMetric: + @pytest.mark.asyncio + async def test_error_handling(self): + class BrokenMetric(Metric): + async def evaluate(self, eval_input): + raise RuntimeError("metric broke") + + evaluator = Evaluator() + metric = BrokenMetric(name="broken", threshold=0.5) + result = await evaluator._evaluate_metric( + metric, EvalInput(actual_output="test") + ) + assert result.score == 0.0 + assert result.passed is False + assert "metric broke" in result.reasoning + + +# ── Evaluator.evaluate_batch ───────────────────────────────────────────────── + + +class TestEvaluatorBatch: + @pytest.mark.asyncio + async def test_batch(self): + evaluator = Evaluator() + inputs = [ + EvalInput(actual_output="a", expected_output="a"), + EvalInput(actual_output="b", expected_output="b"), + ] + results = await evaluator.evaluate_batch( + inputs, + [MetricConfig(metric_type="exact_match", name="em")], + ) + assert len(results) == 2 + assert all(r.passed for r in results) + + +# ── create_evaluator ───────────────────────────────────────────────────────── + + +class TestCreateEvaluator: + def test_factory(self): + evaluator = create_evaluator(fail_fast=True, parallel=False) + assert evaluator.config.fail_fast is True + assert evaluator.config.parallel is False + + +# ── METRIC_REGISTRY ────────────────────────────────────────────────────────── + + +class TestMetricRegistry: + def test_core_metrics_registered(self): + expected = [ + "correctness", + "hallucination", + "relevance", + "criteria", + "geval", + "toxicity", + "bias", + "conciseness", + "coherence", + "completeness", + "helpfulness", + "instruction_following", + "faithfulness", + "contextual_precision", + "contextual_recall", + "answer_correctness", + "rouge", + "exact_match", + "contains", + "json", + "regex", + "tool_call_accuracy", + "tool_sequence", + "tool_args_match", + "context_retention", + "consistency", + "topic_drift", + ] + for name in expected: + assert name in METRIC_REGISTRY, f"{name} not in METRIC_REGISTRY" diff --git a/tests/test_formatting.py b/tests/test_formatting.py new file mode 100644 index 0000000..e17e6e8 --- /dev/null +++ b/tests/test_formatting.py @@ -0,0 +1,88 @@ +"""Tests for fasteval.utils.formatting.""" + +from fasteval.models.evaluation import EvalInput, EvalResult, MetricResult +from fasteval.utils.formatting import format_evaluation_report + + +def _make_metric_result( + name="test_metric", score=0.5, passed=True, threshold=0.5, reasoning="" +): + return MetricResult( + metric_name=name, + score=score, + passed=passed, + threshold=threshold, + reasoning=reasoning, + ) + + +def _make_eval_result(metric_results=None, passed=True, aggregate_score=1.0): + return EvalResult( + eval_input=EvalInput(actual_output="actual", expected_output="expected"), + metric_results=metric_results or [], + passed=passed, + aggregate_score=aggregate_score, + ) + + +class TestFormatEvaluationReport: + def test_basic_report_structure(self): + mr = _make_metric_result(score=0.3, passed=False, reasoning="Bad output") + result = _make_eval_result(metric_results=[mr], passed=False) + report = format_evaluation_report("test_func", [result]) + + assert "FASTEVAL EVALUATION FAILED" in report + assert "test_func" in report + assert "0/1 metrics passed" in report + + def test_failed_metric_shows_reasoning(self): + mr = _make_metric_result( + score=0.1, passed=False, threshold=0.7, reasoning="Not correct" + ) + result = _make_eval_result(metric_results=[mr], passed=False) + report = format_evaluation_report("test_func", [result]) + + assert "Not correct" in report + assert "0.10 / 0.70" in report + + def test_passed_metric_no_reasoning(self): + mr = _make_metric_result(score=0.9, passed=True) + result = _make_eval_result(metric_results=[mr]) + report = format_evaluation_report("test_func", [result]) + + assert "1/1 metrics passed" in report + + def test_with_eval_inputs(self): + result = _make_eval_result() + eval_input = EvalInput( + actual_output="my actual", + expected_output="my expected", + input="my question", + ) + report = format_evaluation_report("test_func", [result], [eval_input]) + + assert "my question" in report + assert "my expected" in report + assert "my actual" in report + + def test_without_eval_inputs(self): + result = _make_eval_result() + report = format_evaluation_report("test_func", [result]) + # Should still generate without errors + assert "FASTEVAL EVALUATION FAILED" in report + + def test_empty_metrics(self): + result = _make_eval_result(metric_results=[]) + report = format_evaluation_report("test_func", [result]) + assert "0/0 metrics passed" in report + + def test_mixed_pass_fail(self): + mr1 = _make_metric_result(name="m1", score=0.9, passed=True) + mr2 = _make_metric_result( + name="m2", score=0.2, passed=False, reasoning="fail reason" + ) + result = _make_eval_result(metric_results=[mr1, mr2], passed=False) + report = format_evaluation_report("test_func", [result]) + + assert "1/2 metrics passed" in report + assert "fail reason" in report diff --git a/tests/test_json_parsing.py b/tests/test_json_parsing.py new file mode 100644 index 0000000..bcc72b1 --- /dev/null +++ b/tests/test_json_parsing.py @@ -0,0 +1,113 @@ +"""Tests for fasteval.utils.json_parsing.""" + +import pytest +from pydantic import BaseModel + +from fasteval.utils.json_parsing import extract_json_from_text, parse_json_response + + +class SampleModel(BaseModel): + score: float + reasoning: str = "" + + +class TestExtractJsonFromText: + def test_direct_json(self): + result = extract_json_from_text('{"score": 0.8, "reasoning": "Good"}') + assert result == {"score": 0.8, "reasoning": "Good"} + + def test_markdown_code_block(self): + text = 'Here is the result:\n```json\n{"score": 0.5, "reasoning": "OK"}\n```' + result = extract_json_from_text(text) + assert result == {"score": 0.5, "reasoning": "OK"} + + def test_markdown_code_block_no_json_tag(self): + text = '```\n{"score": 0.9}\n```' + result = extract_json_from_text(text) + assert result == {"score": 0.9} + + def test_embedded_json_with_score(self): + text = 'The evaluation shows {"score": 0.7, "reasoning": "decent"} overall.' + result = extract_json_from_text(text) + assert result == {"score": 0.7, "reasoning": "decent"} + + def test_score_only_fallback(self): + text = "The score is score: 0.85 based on analysis" + result = extract_json_from_text(text) + assert result is not None + assert result["score"] == 0.85 + + def test_score_clamping_above_one(self): + text = "score: 1.5" + result = extract_json_from_text(text) + assert result is not None + assert result["score"] == 1.0 + + def test_no_match_for_negative_score(self): + # Regex only matches positive numbers, so negative scores don't match + text = "score: -0.5" + result = extract_json_from_text(text) + # Falls through to "score" fallback but regex captures "0.5" from "-0.5" + if result is not None: + assert 0.0 <= result["score"] <= 1.0 + + def test_empty_string(self): + assert extract_json_from_text("") is None + + def test_no_json_found(self): + assert extract_json_from_text("no json here at all") is None + + def test_invalid_json_in_code_block(self): + text = "```json\n{invalid json}\n```" + # Should fall through to other strategies + result = extract_json_from_text(text) + assert result is None + + def test_score_with_equals(self): + text = "score=0.6" + result = extract_json_from_text(text) + assert result is not None + assert result["score"] == 0.6 + + +class TestParseJsonResponse: + def test_valid_model(self): + result = parse_json_response('{"score": 0.8, "reasoning": "Good"}', SampleModel) + assert isinstance(result, SampleModel) + assert result.score == 0.8 + assert result.reasoning == "Good" + + def test_extraction_failure(self): + with pytest.raises(ValueError, match="Could not extract JSON"): + parse_json_response("no json here", SampleModel) + + def test_validation_failure(self): + with pytest.raises(ValueError, match="JSON validation failed"): + parse_json_response('{"score": "not_a_number"}', SampleModel) + + def test_from_markdown_code_block(self): + text = '```json\n{"score": 0.9, "reasoning": "Excellent"}\n```' + result = parse_json_response(text, SampleModel) + assert result.score == 0.9 + + +class TestExtractJsonEdgeCases: + def test_embedded_json_with_invalid_inner(self): + # JSON object found but has invalid content when parsed + text = 'Result: {"score": "bad"} end' + result = extract_json_from_text(text) + # It should still extract the JSON dict + assert result is not None + assert result["score"] == "bad" + + def test_score_value_extraction_with_float(self): + text = "Based on analysis, score: 0.75 out of 1.0" + result = extract_json_from_text(text) + assert result is not None + assert result["score"] == 0.75 + + def test_score_extraction_with_single_quotes(self): + text = "score': 0.6" + result = extract_json_from_text(text) + assert result is not None + assert result["score"] == 0.6 diff --git a/tests/test_llm_metrics.py b/tests/test_llm_metrics.py new file mode 100644 index 0000000..1bd4dfa --- /dev/null +++ b/tests/test_llm_metrics.py @@ -0,0 +1,412 @@ +"""Tests for fasteval.metrics.llm (with mocked LLM client).""" + +import json +from unittest.mock import AsyncMock, patch + +import pytest + +from fasteval.metrics.llm import ( + AnswerCorrectnessMetric, + BaseLLMMetric, + BiasMetric, + CoherenceMetric, + CompletenessMetric, + ConcisenessMetric, + ContextualPrecisionMetric, + ContextualRecallMetric, + CorrectnessMetric, + CriteriaMetric, + FaithfulnessMetric, + HallucinationMetric, + HelpfulnessMetric, + InstructionFollowingMetric, + LLMEvalResponse, + RelevanceMetric, + ToxicityMetric, +) +from fasteval.models.evaluation import EvalInput + + +class MockLLMClient: + """Mock LLM client that returns configurable responses.""" + + def __init__(self, response_text=None): + self.response_text = response_text or json.dumps( + {"score": 0.85, "reasoning": "Mock evaluation"} + ) + self.call_count = 0 + + async def invoke(self, messages): + self.call_count += 1 + return self.response_text + + +class FailingLLMClient: + """Mock client that always raises.""" + + async def invoke(self, messages): + raise RuntimeError("LLM error") + + +# ── LLMEvalResponse ───────────────────────────────────────────────────────── + + +class TestLLMEvalResponse: + def test_valid(self): + resp = LLMEvalResponse(score=0.8, reasoning="Good") + assert resp.score == 0.8 + assert resp.reasoning == "Good" + + def test_score_bounds(self): + with pytest.raises(Exception): + LLMEvalResponse(score=1.5, reasoning="Out of range") + + def test_default_reasoning(self): + resp = LLMEvalResponse(score=0.5) + assert resp.reasoning == "" + + +# ── BaseLLMMetric ──────────────────────────────────────────────────────────── + + +class TestBaseLLMMetric: + def test_get_client_explicit(self): + client = MockLLMClient() + metric = CorrectnessMetric(llm_client=client) + assert metric._get_client() is client + + def test_get_client_model_override(self): + metric = CorrectnessMetric(model="gpt-4o") + client = metric._get_client() + # Should create an OpenAI client + from fasteval.providers.openai import OpenAIClient + + assert isinstance(client, OpenAIClient) + + @pytest.mark.asyncio + async def test_evaluate_success(self): + client = MockLLMClient() + metric = CorrectnessMetric(llm_client=client, threshold=0.5) + result = await metric.evaluate( + EvalInput( + actual_output="4", + expected_output="4", + input="What is 2+2?", + ) + ) + assert result.score == 0.85 + assert result.passed is True + assert result.reasoning == "Mock evaluation" + + @pytest.mark.asyncio + async def test_evaluate_retry_then_success(self): + call_count = 0 + + class RetryClient: + async def invoke(self, messages): + nonlocal call_count + call_count += 1 + if call_count == 1: + return "not json" + return json.dumps({"score": 0.9, "reasoning": "OK"}) + + metric = CorrectnessMetric(llm_client=RetryClient(), max_retries=3) + result = await metric.evaluate( + EvalInput(actual_output="answer", expected_output="answer") + ) + assert result.score == 0.9 + assert call_count == 2 + + @pytest.mark.asyncio + async def test_evaluate_all_retries_fail(self): + metric = CorrectnessMetric(llm_client=FailingLLMClient(), max_retries=2) + result = await metric.evaluate( + EvalInput(actual_output="answer", expected_output="answer") + ) + assert result.score == 0.0 + assert result.passed is False + assert "LLM error" in result.reasoning + + @pytest.mark.asyncio + async def test_binary_scoring(self): + client = MockLLMClient(json.dumps({"score": 0.7, "reasoning": "Partial"})) + metric = CorrectnessMetric( + llm_client=client, scoring_type="binary", threshold=0.5 + ) + result = await metric.evaluate( + EvalInput(actual_output="answer", expected_output="answer") + ) + assert result.score == 1.0 # 0.7 >= 0.5 → 1.0 + + @pytest.mark.asyncio + async def test_binary_scoring_below(self): + client = MockLLMClient(json.dumps({"score": 0.3, "reasoning": "Low"})) + metric = CorrectnessMetric( + llm_client=client, scoring_type="binary", threshold=0.5 + ) + result = await metric.evaluate( + EvalInput(actual_output="answer", expected_output="answer") + ) + assert result.score == 0.0 # 0.3 < 0.5 → 0.0 + + +# ── Specific Metric Prompt Tests ───────────────────────────────────────────── + + +class TestCorrectnessMetric: + def test_default_name(self): + metric = CorrectnessMetric(llm_client=MockLLMClient()) + assert metric.name == "correctness" + + def test_prompt_contains_inputs(self): + metric = CorrectnessMetric(llm_client=MockLLMClient()) + prompt = metric.get_evaluation_prompt( + EvalInput( + actual_output="4", + expected_output="4", + input="What is 2+2?", + ) + ) + assert "What is 2+2?" in prompt + assert "Semantic Equivalence" in prompt + + +class TestHallucinationMetric: + def test_default_threshold(self): + metric = HallucinationMetric(llm_client=MockLLMClient()) + assert metric.threshold == 0.9 + + def test_prompt_includes_context(self): + metric = HallucinationMetric(llm_client=MockLLMClient()) + prompt = metric.get_evaluation_prompt( + EvalInput( + actual_output="The earth is flat", + context=["The earth is round"], + ) + ) + assert "The earth is round" in prompt + + +class TestRelevanceMetric: + def test_default_name(self): + metric = RelevanceMetric(llm_client=MockLLMClient()) + assert metric.name == "relevance" + + @pytest.mark.asyncio + async def test_evaluation(self): + client = MockLLMClient() + metric = RelevanceMetric(llm_client=client, threshold=0.5) + result = await metric.evaluate( + EvalInput(actual_output="answer", input="question") + ) + assert result.score == 0.85 + + +class TestCriteriaMetric: + def test_default_name(self): + metric = CriteriaMetric(llm_client=MockLLMClient(), criteria="Be concise") + assert metric.name == "criteria" + + def test_prompt_includes_criteria(self): + metric = CriteriaMetric( + llm_client=MockLLMClient(), criteria="Answer must be formal" + ) + prompt = metric.get_evaluation_prompt(EvalInput(actual_output="yo what up")) + assert "Answer must be formal" in prompt + + def test_with_evaluation_steps(self): + metric = CriteriaMetric( + llm_client=MockLLMClient(), + criteria="test", + evaluation_steps=["Step 1", "Step 2"], + ) + prompt = metric.get_evaluation_prompt(EvalInput(actual_output="test")) + assert "Step 1" in prompt + + +class TestToxicityMetric: + def test_default_name(self): + metric = ToxicityMetric(llm_client=MockLLMClient()) + assert metric.name == "toxicity" + + @pytest.mark.asyncio + async def test_evaluation(self): + client = MockLLMClient() + metric = ToxicityMetric(llm_client=client, threshold=0.5) + result = await metric.evaluate( + EvalInput(actual_output="Hello, how can I help?") + ) + assert result.passed is True + + +class TestBiasMetric: + def test_default_name(self): + metric = BiasMetric(llm_client=MockLLMClient()) + assert metric.name == "bias" + + +class TestQualityMetrics: + def test_conciseness_name(self): + metric = ConcisenessMetric(llm_client=MockLLMClient()) + assert metric.name == "conciseness" + + def test_coherence_name(self): + metric = CoherenceMetric(llm_client=MockLLMClient()) + assert metric.name == "coherence" + + def test_completeness_name(self): + metric = CompletenessMetric(llm_client=MockLLMClient()) + assert metric.name == "completeness" + + def test_helpfulness_name(self): + metric = HelpfulnessMetric(llm_client=MockLLMClient()) + assert metric.name == "helpfulness" + + def test_instruction_following_name(self): + metric = InstructionFollowingMetric(llm_client=MockLLMClient()) + assert metric.name == "instruction_following" + + def test_instruction_following_prompt(self): + metric = InstructionFollowingMetric( + llm_client=MockLLMClient(), + instructions=["Always respond in French"], + ) + prompt = metric.get_evaluation_prompt(EvalInput(actual_output="Bonjour")) + assert "Always respond in French" in prompt + + +class TestRAGMetrics: + def test_faithfulness_name(self): + metric = FaithfulnessMetric(llm_client=MockLLMClient()) + assert metric.name == "faithfulness" + + def test_faithfulness_prompt_includes_context(self): + metric = FaithfulnessMetric(llm_client=MockLLMClient()) + prompt = metric.get_evaluation_prompt( + EvalInput( + actual_output="answer", + context=["doc1", "doc2"], + ) + ) + assert "doc1" in prompt + assert "doc2" in prompt + + def test_contextual_precision_name(self): + metric = ContextualPrecisionMetric(llm_client=MockLLMClient()) + assert metric.name == "contextual_precision" + + def test_contextual_recall_name(self): + metric = ContextualRecallMetric(llm_client=MockLLMClient()) + assert metric.name == "contextual_recall" + + def test_answer_correctness_name(self): + metric = AnswerCorrectnessMetric(llm_client=MockLLMClient()) + assert metric.name == "answer_correctness" + + def test_contextual_precision_prompt(self): + metric = ContextualPrecisionMetric(llm_client=MockLLMClient()) + prompt = metric.get_evaluation_prompt( + EvalInput( + actual_output="answer", + input="question", + retrieval_context=["doc1", "doc2"], + ) + ) + assert "doc1" in prompt + + def test_contextual_recall_prompt(self): + metric = ContextualRecallMetric(llm_client=MockLLMClient()) + prompt = metric.get_evaluation_prompt( + EvalInput( + actual_output="answer", + expected_output="expected", + context=["doc1"], + ) + ) + assert "doc1" in prompt + + def test_answer_correctness_prompt(self): + metric = AnswerCorrectnessMetric(llm_client=MockLLMClient()) + prompt = metric.get_evaluation_prompt( + EvalInput( + actual_output="answer", + expected_output="expected", + input="question", + ) + ) + assert "question" in prompt + + +class TestLLMMetricEdgeCases: + def test_get_client_default_provider(self): + """Test _get_client falls back to default provider.""" + mock_client = MockLLMClient() + from fasteval.providers.registry import ( + clear_default_provider, + set_default_provider, + ) + + set_default_provider(mock_client) + try: + metric = CorrectnessMetric() + client = metric._get_client() + assert client is mock_client + finally: + clear_default_provider() + + def test_parse_response(self): + metric = CorrectnessMetric(llm_client=MockLLMClient()) + result = metric._parse_response('{"score": 0.7, "reasoning": "OK"}') + assert result.score == 0.7 + + @pytest.mark.asyncio + async def test_conciseness_evaluation(self): + client = MockLLMClient() + metric = ConcisenessMetric(llm_client=client, threshold=0.5) + result = await metric.evaluate( + EvalInput(actual_output="Short answer", input="question") + ) + assert result.passed is True + + @pytest.mark.asyncio + async def test_coherence_evaluation(self): + client = MockLLMClient() + metric = CoherenceMetric(llm_client=client, threshold=0.5) + result = await metric.evaluate(EvalInput(actual_output="Coherent text")) + assert result.passed is True + + @pytest.mark.asyncio + async def test_completeness_evaluation(self): + client = MockLLMClient() + metric = CompletenessMetric(llm_client=client, threshold=0.5) + result = await metric.evaluate( + EvalInput(actual_output="Complete answer", input="q") + ) + assert result.passed is True + + @pytest.mark.asyncio + async def test_helpfulness_evaluation(self): + client = MockLLMClient() + metric = HelpfulnessMetric(llm_client=client, threshold=0.5) + result = await metric.evaluate( + EvalInput(actual_output="Helpful response", input="q") + ) + assert result.passed is True + + @pytest.mark.asyncio + async def test_instruction_following_evaluation(self): + client = MockLLMClient() + metric = InstructionFollowingMetric( + llm_client=client, + instructions=["Be formal"], + threshold=0.5, + ) + result = await metric.evaluate(EvalInput(actual_output="Formal response")) + assert result.passed is True + + @pytest.mark.asyncio + async def test_instruction_following_no_instructions(self): + client = MockLLMClient() + metric = InstructionFollowingMetric(llm_client=client, threshold=0.5) + prompt = metric.get_evaluation_prompt(EvalInput(actual_output="test")) + assert "No instructions" in prompt diff --git a/tests/test_plugin.py b/tests/test_plugin.py new file mode 100644 index 0000000..aa52ec3 --- /dev/null +++ b/tests/test_plugin.py @@ -0,0 +1,217 @@ +"""Tests for fasteval.testing.plugin.""" + +import os +from io import StringIO +from unittest.mock import MagicMock, patch + +import pytest + +from fasteval.collectors.summary import EvalRunSummary, MetricAggregate, TestCaseSummary +from fasteval.testing.plugin import ( + _print_console_summary, + pytest_addoption, + pytest_configure, + pytest_sessionfinish, + pytest_sessionstart, + pytest_unconfigure, +) + +# ── pytest_addoption ───────────────────────────────────────────────────────── + + +class TestPytestAddoption: + def test_adds_options(self): + mock_parser = MagicMock() + pytest_addoption(mock_parser) + assert mock_parser.addoption.call_count == 3 + option_names = [call[0][0] for call in mock_parser.addoption.call_args_list] + assert "--no-interactive" in option_names + assert "--fe-output" in option_names + assert "--fe-summary" in option_names + + +# ── pytest_configure ───────────────────────────────────────────────────────── + + +class TestPytestConfigure: + def test_sets_env_var(self): + mock_config = MagicMock() + mock_config.getoption.return_value = True + with patch.dict(os.environ, {}, clear=False): + pytest_configure(mock_config) + assert os.environ.get("FASTEVAL_NO_INTERACTIVE") == "1" + # Cleanup + os.environ.pop("FASTEVAL_NO_INTERACTIVE", None) + + def test_no_env_var_when_false(self): + mock_config = MagicMock() + mock_config.getoption.return_value = False + initial = os.environ.get("FASTEVAL_NO_INTERACTIVE") + pytest_configure(mock_config) + assert os.environ.get("FASTEVAL_NO_INTERACTIVE") == initial + + +# ── pytest_sessionstart ────────────────────────────────────────────────────── + + +class TestPytestSessionStart: + def test_resets_collector(self): + with patch("fasteval.collectors.collector.reset_collector") as mock_reset: + pytest_sessionstart(MagicMock()) + + +# ── pytest_sessionfinish ───────────────────────────────────────────────────── + + +class TestPytestSessionFinish: + def test_no_results_noop(self): + mock_session = MagicMock() + mock_collector = MagicMock() + mock_collector.results = [] + + with patch( + "fasteval.collectors.collector.get_collector", + return_value=mock_collector, + ): + pytest_sessionfinish(mock_session, 0) + mock_collector.report.assert_not_called() + + def test_fe_output_with_path(self): + mock_session = MagicMock() + mock_session.config.getoption.side_effect = lambda opt, **kwargs: { + "--fe-summary": False, + "--fe-output": ["json:output.json"], + }.get(opt, kwargs.get("default")) + + mock_collector = MagicMock() + mock_collector.results = [MagicMock()] + + with patch( + "fasteval.collectors.collector.get_collector", + return_value=mock_collector, + ): + pytest_sessionfinish(mock_session, 0) + mock_collector.report.assert_called_once_with("json", path="output.json") + + def test_fe_output_without_path(self): + mock_session = MagicMock() + mock_session.config.getoption.side_effect = lambda opt, **kwargs: { + "--fe-summary": False, + "--fe-output": ["json"], + }.get(opt, kwargs.get("default")) + + mock_collector = MagicMock() + mock_collector.results = [MagicMock()] + mock_collector.report.return_value = '{"test": true}' + + with patch( + "fasteval.collectors.collector.get_collector", + return_value=mock_collector, + ): + pytest_sessionfinish(mock_session, 0) + mock_collector.report.assert_called_once_with("json") + + def test_fe_summary(self): + mock_session = MagicMock() + mock_session.config.getoption.side_effect = lambda opt, **kwargs: { + "--fe-summary": True, + "--fe-output": [], + }.get(opt, kwargs.get("default")) + + mock_collector = MagicMock() + mock_collector.results = [MagicMock()] + + with ( + patch( + "fasteval.collectors.collector.get_collector", + return_value=mock_collector, + ), + patch("fasteval.testing.plugin._print_console_summary") as mock_print, + ): + pytest_sessionfinish(mock_session, 0) + mock_print.assert_called_once() + + +# ── pytest_unconfigure ─────────────────────────────────────────────────────── + + +class TestPytestUnconfigure: + def test_cleans_up_env_var(self): + mock_config = MagicMock() + mock_config.getoption.return_value = True + with patch.dict(os.environ, {"FASTEVAL_NO_INTERACTIVE": "1"}): + pytest_unconfigure(mock_config) + assert "FASTEVAL_NO_INTERACTIVE" not in os.environ + + def test_no_cleanup_when_not_set(self): + mock_config = MagicMock() + mock_config.getoption.return_value = False + env_copy = os.environ.copy() + env_copy.pop("FASTEVAL_NO_INTERACTIVE", None) + with patch.dict(os.environ, env_copy, clear=True): + pytest_unconfigure(mock_config) + + +# ── _print_console_summary ─────────────────────────────────────────────────── + + +class TestPrintConsoleSummary: + def test_output_format(self, capsys): + summary = EvalRunSummary( + total_tests=3, + passed_tests=2, + failed_tests=1, + pass_rate=2 / 3, + avg_aggregate_score=0.75, + total_execution_time_ms=100.0, + metric_aggregates=[ + MetricAggregate( + metric_name="correctness", + count=3, + pass_count=2, + fail_count=1, + pass_rate=2 / 3, + avg_score=0.75, + min_score=0.3, + max_score=1.0, + ) + ], + test_summaries=[ + TestCaseSummary( + test_name="test_pass", + passed=True, + aggregate_score=1.0, + metric_count=1, + execution_time_ms=10.0, + ), + TestCaseSummary( + test_name="test_fail", + passed=False, + aggregate_score=0.3, + metric_count=1, + execution_time_ms=20.0, + error="low score", + ), + ], + ) + _print_console_summary(summary) + captured = capsys.readouterr() + assert "FastEval Summary" in captured.out + assert "3 total" in captured.out + assert "2 passed" in captured.out + assert "1 failed" in captured.out + assert "correctness" in captured.out + assert "test_fail" in captured.out + + def test_no_metrics(self, capsys): + summary = EvalRunSummary( + total_tests=1, + passed_tests=1, + failed_tests=0, + pass_rate=1.0, + avg_aggregate_score=1.0, + total_execution_time_ms=5.0, + ) + _print_console_summary(summary) + captured = capsys.readouterr() + assert "FastEval Summary" in captured.out diff --git a/tests/test_providers.py b/tests/test_providers.py new file mode 100644 index 0000000..8577f0e --- /dev/null +++ b/tests/test_providers.py @@ -0,0 +1,192 @@ +"""Tests for fasteval.providers (registry, openai, anthropic).""" + +import os +from unittest.mock import AsyncMock, MagicMock, patch + +import pytest + +import fasteval.providers.registry as registry_module +from fasteval.providers.anthropic import AnthropicClient +from fasteval.providers.openai import OpenAIClient +from fasteval.providers.registry import ( + clear_default_provider, + create_provider_for_model, + get_default_provider, + set_default_provider, +) + + +class MockLLMClient: + async def invoke(self, messages): + return "mock response" + + +class TestProviderRegistry: + def setup_method(self): + clear_default_provider() + + def test_set_and_get_default_provider(self): + client = MockLLMClient() + set_default_provider(client) + assert get_default_provider() is client + + def test_clear_default_provider(self): + set_default_provider(MockLLMClient()) + clear_default_provider() + # Should now try env vars or raise + with patch.dict(os.environ, {}, clear=True): + env = os.environ.copy() + env.pop("OPENAI_API_KEY", None) + env.pop("ANTHROPIC_API_KEY", None) + with patch.dict(os.environ, env, clear=True): + with pytest.raises(ValueError, match="No LLM provider configured"): + get_default_provider() + + def test_create_from_env_openai(self): + clear_default_provider() + with patch.dict(os.environ, {"OPENAI_API_KEY": "test-key"}): + provider = get_default_provider() + assert isinstance(provider, OpenAIClient) + + def test_create_from_env_anthropic(self): + clear_default_provider() + with patch.dict( + os.environ, + {"ANTHROPIC_API_KEY": "test-key"}, + clear=False, + ): + # Remove OpenAI key if present + env = os.environ.copy() + env.pop("OPENAI_API_KEY", None) + env["ANTHROPIC_API_KEY"] = "test-key" + with patch.dict(os.environ, env, clear=True): + provider = get_default_provider() + assert isinstance(provider, AnthropicClient) + + def test_create_from_env_no_keys(self): + clear_default_provider() + with patch.dict(os.environ, {}, clear=True): + with pytest.raises(ValueError, match="No LLM provider configured"): + get_default_provider() + + def test_create_provider_for_model_gpt(self): + provider = create_provider_for_model("gpt-4o") + assert isinstance(provider, OpenAIClient) + assert provider.model == "gpt-4o" + + def test_create_provider_for_model_o1(self): + provider = create_provider_for_model("o1-preview") + assert isinstance(provider, OpenAIClient) + + def test_create_provider_for_model_o3(self): + provider = create_provider_for_model("o3-mini") + assert isinstance(provider, OpenAIClient) + + def test_create_provider_for_model_claude(self): + provider = create_provider_for_model("claude-sonnet-4-6") + assert isinstance(provider, AnthropicClient) + assert provider.model == "claude-sonnet-4-6" + + def test_create_provider_for_model_unknown(self): + with pytest.raises(ValueError, match="Unknown model"): + create_provider_for_model("llama-70b") + + +class TestOpenAIClient: + def test_init_defaults(self): + client = OpenAIClient() + assert client.model == "gpt-4o-mini" + assert client.temperature == 0.0 + assert client._client is None + + def test_init_custom(self): + client = OpenAIClient(model="gpt-4o", api_key="key", temperature=0.5) + assert client.model == "gpt-4o" + assert client.api_key == "key" + assert client.temperature == 0.5 + + def test_repr(self): + client = OpenAIClient(model="gpt-4o") + assert repr(client) == "OpenAIClient(model='gpt-4o')" + + @pytest.mark.asyncio + async def test_invoke_mocked(self): + client = OpenAIClient(model="gpt-4o", api_key="test") + + mock_response = MagicMock() + mock_response.choices = [MagicMock()] + mock_response.choices[0].message.content = "Hello!" + + mock_async_client = AsyncMock() + mock_async_client.chat.completions.create = AsyncMock( + return_value=mock_response + ) + client._client = mock_async_client + + result = await client.invoke([{"role": "user", "content": "Hi"}]) + assert result == "Hello!" + + +class TestProviderRegistryEdgeCases: + def setup_method(self): + clear_default_provider() + + def test_create_provider_for_model_claude_import_error(self): + with patch.dict("sys.modules", {"anthropic": None}): + # When anthropic is not importable + try: + provider = create_provider_for_model("claude-3-5-sonnet") + # If it succeeds, that's fine (anthropic might already be imported) + assert isinstance(provider, AnthropicClient) + except ImportError: + pass # Expected when anthropic can't be imported + + +class TestAnthropicClient: + def test_init_defaults(self): + client = AnthropicClient() + assert client.model == "claude-sonnet-4-6" + assert client.temperature == 0.0 + assert client.max_tokens == 4096 + + def test_repr(self): + client = AnthropicClient(model="claude-3-5-sonnet") + assert repr(client) == "AnthropicClient(model='claude-3-5-sonnet')" + + @pytest.mark.asyncio + async def test_invoke_mocked(self): + client = AnthropicClient(model="claude-sonnet-4-6", api_key="test") + + mock_response = MagicMock() + mock_response.content = [MagicMock()] + mock_response.content[0].text = "Hi from Claude!" + + mock_async_client = AsyncMock() + mock_async_client.messages.create = AsyncMock(return_value=mock_response) + client._client = mock_async_client + + result = await client.invoke([{"role": "user", "content": "Hello"}]) + assert result == "Hi from Claude!" + + @pytest.mark.asyncio + async def test_invoke_with_system_message(self): + client = AnthropicClient(api_key="test") + + mock_response = MagicMock() + mock_response.content = [MagicMock()] + mock_response.content[0].text = "Response" + + mock_async_client = AsyncMock() + mock_async_client.messages.create = AsyncMock(return_value=mock_response) + client._client = mock_async_client + + messages = [ + {"role": "system", "content": "You are helpful"}, + {"role": "user", "content": "Hi"}, + ] + await client.invoke(messages) + + call_kwargs = mock_async_client.messages.create.call_args[1] + assert call_kwargs["system"] == "You are helpful" + assert len(call_kwargs["messages"]) == 1 + assert call_kwargs["messages"][0]["role"] == "user" diff --git a/tests/test_reporters.py b/tests/test_reporters.py new file mode 100644 index 0000000..145aff0 --- /dev/null +++ b/tests/test_reporters.py @@ -0,0 +1,155 @@ +"""Tests for fasteval.collectors.reporters (json + html).""" + +import json + +import pytest + +from fasteval.collectors.reporters.html_reporter import HtmlReporter +from fasteval.collectors.reporters.json_reporter import JsonReporter +from fasteval.collectors.summary import EvalRunSummary +from fasteval.models.evaluation import EvalInput, EvalResult, MetricResult + + +def _make_metric(name="m1", score=0.8, passed=True, threshold=0.5, reasoning="OK"): + return MetricResult( + metric_name=name, + score=score, + passed=passed, + threshold=threshold, + reasoning=reasoning, + ) + + +def _make_result( + passed=True, aggregate_score=0.8, metrics=None, execution_time_ms=10.0 +): + return EvalResult( + eval_input=EvalInput(actual_output="test output", expected_output="expected"), + metric_results=metrics or [], + passed=passed, + aggregate_score=aggregate_score, + execution_time_ms=execution_time_ms, + ) + + +def _make_summary_and_results(): + mr1 = _make_metric(name="correctness", score=0.9, passed=True) + mr2 = _make_metric( + name="relevance", score=0.3, passed=False, reasoning="Not relevant" + ) + r1 = _make_result(passed=True, metrics=[mr1]) + r2 = _make_result(passed=False, aggregate_score=0.3, metrics=[mr2]) + summary = EvalRunSummary.from_results([r1, r2], ["test_pass", "test_fail"]) + return summary, [r1, r2] + + +# ── JsonReporter ───────────────────────────────────────────────────────────── + + +class TestJsonReporter: + def test_generates_valid_json(self): + summary, results = _make_summary_and_results() + reporter = JsonReporter() + output = reporter.generate(summary, results) + parsed = json.loads(output) + assert isinstance(parsed, dict) + + def test_includes_summary_and_results(self): + summary, results = _make_summary_and_results() + reporter = JsonReporter() + parsed = json.loads(reporter.generate(summary, results)) + assert "summary" in parsed + assert "results" in parsed + assert len(parsed["results"]) == 2 + + def test_test_name_assigned(self): + summary, results = _make_summary_and_results() + reporter = JsonReporter() + parsed = json.loads(reporter.generate(summary, results)) + assert parsed["results"][0]["test_name"] == "test_pass" + assert parsed["results"][1]["test_name"] == "test_fail" + + def test_include_inputs_false(self): + summary, results = _make_summary_and_results() + reporter = JsonReporter(include_inputs=False) + parsed = json.loads(reporter.generate(summary, results)) + for r in parsed["results"]: + assert "eval_input" not in r + + def test_custom_indent(self): + summary, results = _make_summary_and_results() + reporter = JsonReporter(indent=4) + output = reporter.generate(summary, results) + # 4-space indent should produce more whitespace than 2-space + assert " " in output + + def test_empty_results(self): + summary = EvalRunSummary.from_results([], []) + reporter = JsonReporter() + output = reporter.generate(summary, []) + parsed = json.loads(output) + assert parsed["results"] == [] + + +# ── HtmlReporter ───────────────────────────────────────────────────────────── + + +class TestHtmlReporter: + def test_generates_html(self): + summary, results = _make_summary_and_results() + reporter = HtmlReporter() + output = reporter.generate(summary, results) + assert "" in output + assert "" in output + + def test_contains_key_sections(self): + summary, results = _make_summary_and_results() + reporter = HtmlReporter() + output = reporter.generate(summary, results) + assert "FastEval Evaluation Report" in output + assert "Metric Breakdown" in output + assert "Test Results" in output + + def test_cards_section(self): + summary, results = _make_summary_and_results() + reporter = HtmlReporter() + output = reporter.generate(summary, results) + assert "Total Tests" in output + assert "Passed" in output + assert "Failed" in output + + def test_metric_table(self): + summary, results = _make_summary_and_results() + reporter = HtmlReporter() + output = reporter.generate(summary, results) + assert "correctness" in output + assert "relevance" in output + + def test_pass_fail_badges(self): + summary, results = _make_summary_and_results() + reporter = HtmlReporter() + output = reporter.generate(summary, results) + assert "PASS" in output + assert "FAIL" in output + + def test_empty_results(self): + summary = EvalRunSummary.from_results([], []) + reporter = HtmlReporter() + output = reporter.generate(summary, []) + assert "No test results" in output + + def test_empty_metrics(self): + r = _make_result(metrics=[]) + summary = EvalRunSummary.from_results([r], ["test1"]) + reporter = HtmlReporter() + output = reporter.generate(summary, [r]) + assert "No metrics recorded" in output + + def test_reasoning_displayed(self): + mr = _make_metric(reasoning="Detailed reason here", passed=False) + r = _make_result(metrics=[mr], passed=False) + summary = EvalRunSummary.from_results([r], ["test1"]) + reporter = HtmlReporter() + output = reporter.generate(summary, [r]) + assert "Detailed reason here" in output diff --git a/tests/test_scoring.py b/tests/test_scoring.py new file mode 100644 index 0000000..59069b6 --- /dev/null +++ b/tests/test_scoring.py @@ -0,0 +1,191 @@ +"""Tests for fasteval.core.scoring.""" + +from pathlib import Path +from unittest.mock import MagicMock, patch + +import pytest + +from fasteval.core.scoring import ( + _get_test_name_from_caller, + _last_score_result, + _normalize_audio, + _normalize_generated_image, + _normalize_image, + clear_last_score_result, + get_last_score_result, + score, +) +from fasteval.models.evaluation import ( + EvalInput, + EvalResult, + EvaluationFailedError, + ExpectedTool, + MetricResult, + ToolCall, +) +from fasteval.models.multimodal import AudioInput, GeneratedImage, ImageInput + +# ── Normalization helpers ──────────────────────────────────────────────────── + + +class TestNormalizeImage: + def test_image_input_passthrough(self): + img = ImageInput(source="test.png") + assert _normalize_image(img) is img + + def test_path_to_str(self): + result = _normalize_image(Path("/tmp/test.png")) + assert result == "/tmp/test.png" + assert isinstance(result, str) + + def test_string_passthrough(self): + assert _normalize_image("http://img.png") == "http://img.png" + + +class TestNormalizeAudio: + def test_audio_input_passthrough(self): + aud = AudioInput(source="test.wav") + assert _normalize_audio(aud) is aud + + def test_path_to_str(self): + result = _normalize_audio(Path("/tmp/test.wav")) + assert result == "/tmp/test.wav" + + def test_string_passthrough(self): + assert _normalize_audio("http://audio.wav") == "http://audio.wav" + + +class TestNormalizeGeneratedImage: + def test_generated_image_passthrough(self): + img = GeneratedImage(image=ImageInput(source="test.png"), prompt="A test image") + assert _normalize_generated_image(img) is img + + def test_image_input_passthrough(self): + img = ImageInput(source="test.png") + assert _normalize_generated_image(img) is img + + def test_path_to_str(self): + result = _normalize_generated_image(Path("/tmp/gen.png")) + assert result == "/tmp/gen.png" + + def test_string_passthrough(self): + assert _normalize_generated_image("gen.png") == "gen.png" + + +# ── Context variable storage ───────────────────────────────────────────────── + + +class TestLastScoreResult: + def test_default_is_none(self): + clear_last_score_result() + assert get_last_score_result() is None + + def test_set_and_get(self): + result = EvalResult( + eval_input=EvalInput(actual_output="test"), + metric_results=[], + passed=True, + aggregate_score=1.0, + ) + _last_score_result.set(result) + assert get_last_score_result() is result + clear_last_score_result() + + def test_clear(self): + _last_score_result.set( + EvalResult( + eval_input=EvalInput(actual_output="test"), + metric_results=[], + passed=True, + aggregate_score=1.0, + ) + ) + clear_last_score_result() + assert get_last_score_result() is None + + +# ── _get_test_name_from_caller ─────────────────────────────────────────────── + + +class TestGetTestName: + def test_from_test_function(self): + # This is called from a function starting with "test_" + name = _get_test_name_from_caller() + assert name.startswith("test_") + + def _helper_non_test(self): + return _get_test_name_from_caller() + + def test_from_non_test_via_helper(self): + # The helper doesn't start with test_, but the caller does + name = self._helper_non_test() + assert name.startswith("test_") + + +# ── score() function ───────────────────────────────────────────────────────── + + +class TestScoreFunction: + def test_score_no_decorators(self): + """score() without decorators returns a base result.""" + result = score("actual output", "expected output", input="question") + assert result.passed is True + assert result.aggregate_score == 1.0 + assert len(result.metric_results) == 0 + + def test_score_stores_last_result(self): + clear_last_score_result() + result = score("output") + assert get_last_score_result() is result + + def test_score_normalizes_tool_calls_dict(self): + result = score( + "output", + tool_calls=[ + {"name": "search", "args": {"q": "test"}, "result": "found"}, + ], + ) + assert result.eval_input.tool_calls[0].name == "search" + assert result.eval_input.tool_calls[0].arguments == {"q": "test"} + + def test_score_normalizes_tool_calls_with_arguments_key(self): + result = score( + "output", + tool_calls=[ + {"name": "search", "arguments": {"q": "test"}}, + ], + ) + assert result.eval_input.tool_calls[0].arguments == {"q": "test"} + + def test_score_normalizes_tool_call_model(self): + tc = ToolCall(name="search", arguments={"q": "test"}) + result = score("output", tool_calls=[tc]) + assert result.eval_input.tool_calls[0] is tc + + def test_score_normalizes_expected_tools_dict(self): + result = score( + "output", + expected_tools=[ + {"name": "search", "args": {"q": "test"}, "required": False}, + ], + ) + assert result.eval_input.expected_tools[0].name == "search" + assert result.eval_input.expected_tools[0].required is False + + def test_score_normalizes_expected_tool_model(self): + et = ExpectedTool(name="search") + result = score("output", expected_tools=[et]) + assert result.eval_input.expected_tools[0] is et + + def test_score_with_context(self): + result = score( + "output", + context=["doc1", "doc2"], + retrieval_context=["ret1"], + ) + assert result.eval_input.context == ["doc1", "doc2"] + assert result.eval_input.retrieval_context == ["ret1"] + + def test_score_with_metadata(self): + result = score("output", metadata={"key": "value"}) + assert result.eval_input.metadata == {"key": "value"} diff --git a/tests/test_text_utils.py b/tests/test_text_utils.py new file mode 100644 index 0000000..47e56eb --- /dev/null +++ b/tests/test_text_utils.py @@ -0,0 +1,39 @@ +"""Tests for fasteval.utils.text.""" + +from fasteval.utils.text import truncate + + +class TestTruncate: + def test_empty_string(self): + assert truncate("") == "" + + def test_short_text_unchanged(self): + assert truncate("Hello", max_length=80) == "Hello" + + def test_long_text_truncated(self): + result = truncate("a" * 100, max_length=10) + assert len(result) == 10 + assert result.endswith("...") + + def test_newlines_replaced(self): + result = truncate("line1\nline2\nline3", max_length=80) + assert "\n" not in result + assert result == "line1 line2 line3" + + def test_custom_ellipsis(self): + result = truncate("a" * 100, max_length=10, ellipsis="~~") + assert result.endswith("~~") + assert len(result) == 10 + + def test_max_length_less_than_ellipsis(self): + result = truncate("a" * 100, max_length=2, ellipsis="...") + assert result == ".." + assert len(result) == 2 + + def test_exact_max_length_no_truncation(self): + text = "a" * 80 + assert truncate(text, max_length=80) == text + + def test_whitespace_stripped(self): + result = truncate(" hello ", max_length=80) + assert result == "hello" diff --git a/uv.lock b/uv.lock index adcc268..790b580 100644 --- a/uv.lock +++ b/uv.lock @@ -541,7 +541,7 @@ wheels = [ [[package]] name = "fasteval-core" -version = "1.0.0a1" +version = "1.2.0" source = { editable = "." } dependencies = [ { name = "openai" }, @@ -2571,6 +2571,13 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/0f/8b/4b61d6e13f7108f36910df9ab4b58fd389cc2520d54d81b88660804aad99/torch-2.10.0-2-cp311-none-macosx_11_0_arm64.whl", hash = "sha256:418997cb02d0a0f1497cf6a09f63166f9f5df9f3e16c8a716ab76a72127c714f", size = 79423467, upload-time = "2026-02-10T21:44:48.711Z" }, { url = "https://files.pythonhosted.org/packages/d3/54/a2ba279afcca44bbd320d4e73675b282fcee3d81400ea1b53934efca6462/torch-2.10.0-2-cp312-none-macosx_11_0_arm64.whl", hash = "sha256:13ec4add8c3faaed8d13e0574f5cd4a323c11655546f91fbe6afa77b57423574", size = 79498202, upload-time = "2026-02-10T21:44:52.603Z" }, { url = "https://files.pythonhosted.org/packages/ec/23/2c9fe0c9c27f7f6cb865abcea8a4568f29f00acaeadfc6a37f6801f84cb4/torch-2.10.0-2-cp313-none-macosx_11_0_arm64.whl", hash = "sha256:e521c9f030a3774ed770a9c011751fb47c4d12029a3d6522116e48431f2ff89e", size = 79498254, upload-time = "2026-02-10T21:44:44.095Z" }, + { url = "https://files.pythonhosted.org/packages/16/ee/efbd56687be60ef9af0c9c0ebe106964c07400eade5b0af8902a1d8cd58c/torch-2.10.0-3-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:a1ff626b884f8c4e897c4c33782bdacdff842a165fee79817b1dd549fdda1321", size = 915510070, upload-time = "2026-03-11T14:16:39.386Z" }, + { url = "https://files.pythonhosted.org/packages/36/ab/7b562f1808d3f65414cd80a4f7d4bb00979d9355616c034c171249e1a303/torch-2.10.0-3-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:ac5bdcbb074384c66fa160c15b1ead77839e3fe7ed117d667249afce0acabfac", size = 915518691, upload-time = "2026-03-11T14:15:43.147Z" }, + { url = "https://files.pythonhosted.org/packages/b3/7a/abada41517ce0011775f0f4eacc79659bc9bc6c361e6bfe6f7052a6b9363/torch-2.10.0-3-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:98c01b8bb5e3240426dcde1446eed6f40c778091c8544767ef1168fc663a05a6", size = 915622781, upload-time = "2026-03-11T14:17:11.354Z" }, + { url = "https://files.pythonhosted.org/packages/ab/c6/4dfe238342ffdcec5aef1c96c457548762d33c40b45a1ab7033bb26d2ff2/torch-2.10.0-3-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:80b1b5bfe38eb0e9f5ff09f206dcac0a87aadd084230d4a36eea5ec5232c115b", size = 915627275, upload-time = "2026-03-11T14:16:11.325Z" }, + { url = "https://files.pythonhosted.org/packages/d8/f0/72bf18847f58f877a6a8acf60614b14935e2f156d942483af1ffc081aea0/torch-2.10.0-3-cp313-cp313t-manylinux_2_28_x86_64.whl", hash = "sha256:46b3574d93a2a8134b3f5475cfb98e2eb46771794c57015f6ad1fb795ec25e49", size = 915523474, upload-time = "2026-03-11T14:17:44.422Z" }, + { url = "https://files.pythonhosted.org/packages/f4/39/590742415c3030551944edc2ddc273ea1fdfe8ffb2780992e824f1ebee98/torch-2.10.0-3-cp314-cp314-manylinux_2_28_x86_64.whl", hash = "sha256:b1d5e2aba4eb7f8e87fbe04f86442887f9167a35f092afe4c237dfcaaef6e328", size = 915632474, upload-time = "2026-03-11T14:15:13.666Z" }, + { url = "https://files.pythonhosted.org/packages/b6/8e/34949484f764dde5b222b7fe3fede43e4a6f0da9d7f8c370bb617d629ee2/torch-2.10.0-3-cp314-cp314t-manylinux_2_28_x86_64.whl", hash = "sha256:0228d20b06701c05a8f978357f657817a4a63984b0c90745def81c18aedfa591", size = 915523882, upload-time = "2026-03-11T14:14:46.311Z" }, { url = "https://files.pythonhosted.org/packages/0c/1a/c61f36cfd446170ec27b3a4984f072fd06dab6b5d7ce27e11adb35d6c838/torch-2.10.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:5276fa790a666ee8becaffff8acb711922252521b28fbce5db7db5cf9cb2026d", size = 145992962, upload-time = "2026-01-21T16:24:14.04Z" }, { url = "https://files.pythonhosted.org/packages/b5/60/6662535354191e2d1555296045b63e4279e5a9dbad49acf55a5d38655a39/torch-2.10.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:aaf663927bcd490ae971469a624c322202a2a1e68936eb952535ca4cd3b90444", size = 915599237, upload-time = "2026-01-21T16:23:25.497Z" }, { url = "https://files.pythonhosted.org/packages/40/b8/66bbe96f0d79be2b5c697b2e0b187ed792a15c6c4b8904613454651db848/torch-2.10.0-cp310-cp310-win_amd64.whl", hash = "sha256:a4be6a2a190b32ff5c8002a0977a25ea60e64f7ba46b1be37093c141d9c49aeb", size = 113720931, upload-time = "2026-01-21T16:24:23.743Z" }, From 3b6810510500b9bd23c6ac79a0f95aa86eb3d51a Mon Sep 17 00:00:00 2001 From: sridharswain Date: Wed, 18 Mar 2026 13:28:31 +0530 Subject: [PATCH 2/5] Coverage check added --- .github/workflows/ci.yml | 25 +++++++++++++++++++++---- tests/test_base_metric.py | 2 +- tests/test_decorators_extended.py | 4 ++-- tests/test_evaluator.py | 16 +++++++++------- tests/test_llm_metrics.py | 2 +- 5 files changed, 34 insertions(+), 15 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e7373c2..2c9d39f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -54,13 +54,14 @@ jobs: - name: Install dependencies run: uv sync --all-extras --group test - - name: Run tests + - name: Run tests with coverage run: | uv run pytest tests/ \ --color=yes \ --cov=fasteval \ --cov-report=term \ --cov-report=xml:coverage.xml \ + --cov-fail-under=85 \ -v - name: Upload coverage @@ -76,7 +77,13 @@ jobs: strategy: fail-fast: false matrix: - plugin: [fasteval-langfuse, fasteval-langgraph, fasteval-observe] + include: + - plugin: fasteval-langfuse + module: fasteval_langfuse + - plugin: fasteval-langgraph + module: fasteval_langgraph + - plugin: fasteval-observe + module: fasteval_observe steps: - uses: actions/checkout@v4 @@ -93,6 +100,16 @@ jobs: working-directory: plugins/${{ matrix.plugin }} run: uv sync --all-extras --group dev - - name: Run plugin tests + - name: Install coverage tools working-directory: plugins/${{ matrix.plugin }} - run: uv run pytest tests/ -v --color=yes + run: uv pip install pytest-cov + + - name: Run plugin tests with coverage + working-directory: plugins/${{ matrix.plugin }} + run: | + uv run pytest tests/ \ + --color=yes \ + --cov=${{ matrix.module }} \ + --cov-report=term \ + --cov-fail-under=85 \ + -v diff --git a/tests/test_base_metric.py b/tests/test_base_metric.py index c401305..f945e7e 100644 --- a/tests/test_base_metric.py +++ b/tests/test_base_metric.py @@ -50,4 +50,4 @@ async def test_evaluate(self): def test_abstract_cannot_instantiate(self): with pytest.raises(TypeError): - Metric(name="test") + Metric(name="test") # type: ignore[abstract] diff --git a/tests/test_decorators_extended.py b/tests/test_decorators_extended.py index 8740fc8..0d95008 100644 --- a/tests/test_decorators_extended.py +++ b/tests/test_decorators_extended.py @@ -280,7 +280,7 @@ def my_func(query, expected, history): results.append({"query": query, "expected": expected, "history": history}) return None - my_func() + my_func() # type: ignore[call-arg] assert len(results) == 2 assert results[0]["query"] == "Hello" assert results[0]["history"] == [] @@ -299,7 +299,7 @@ async def test_async_conversation(self): async def my_func(query, expected, history): results.append({"query": query, "history": history}) - await my_func() + await my_func() # type: ignore[call-arg] assert len(results) == 2 def test_conversation_preserves_metrics(self): diff --git a/tests/test_evaluator.py b/tests/test_evaluator.py index bc93313..05a899d 100644 --- a/tests/test_evaluator.py +++ b/tests/test_evaluator.py @@ -4,6 +4,8 @@ import pytest +from typing import Any + from fasteval.core.evaluator import ( METRIC_REGISTRY, Evaluator, @@ -82,7 +84,7 @@ class User(BaseModel): name="json_check", config={"pydantic_model": User}, ) - metric = evaluator._create_metric(config) + metric: Any = evaluator._create_metric(config) assert metric.model is User def test_criteria_metric(self): @@ -93,7 +95,7 @@ def test_criteria_metric(self): config={"criteria": "Be formal"}, llm_client=MockLLMClient(), ) - metric = evaluator._create_metric(config) + metric: Any = evaluator._create_metric(config) assert metric.criteria == "Be formal" def test_criteria_with_evaluation_steps(self): @@ -107,7 +109,7 @@ def test_criteria_with_evaluation_steps(self): }, llm_client=MockLLMClient(), ) - metric = evaluator._create_metric(config) + metric: Any = evaluator._create_metric(config) assert metric.evaluation_steps == ["Step 1"] def test_instruction_following_metric(self): @@ -118,7 +120,7 @@ def test_instruction_following_metric(self): config={"instructions": "Be concise"}, llm_client=MockLLMClient(), ) - metric = evaluator._create_metric(config) + metric: Any = evaluator._create_metric(config) assert metric.instructions == "Be concise" def test_with_llm_client(self): @@ -129,7 +131,7 @@ def test_with_llm_client(self): name="corr", llm_client=client, ) - metric = evaluator._create_metric(config) + metric: Any = evaluator._create_metric(config) assert metric._llm_client is client def test_with_llm_config_model(self): @@ -139,7 +141,7 @@ def test_with_llm_config_model(self): name="corr", llm_config={"model": "gpt-4o"}, ) - metric = evaluator._create_metric(config) + metric: Any = evaluator._create_metric(config) assert metric._model_override == "gpt-4o" @@ -254,7 +256,7 @@ async def evaluate(self, eval_input): ) assert result.score == 0.0 assert result.passed is False - assert "metric broke" in result.reasoning + assert result.reasoning is not None and "metric broke" in result.reasoning # ── Evaluator.evaluate_batch ───────────────────────────────────────────────── diff --git a/tests/test_llm_metrics.py b/tests/test_llm_metrics.py index 1bd4dfa..8244ddd 100644 --- a/tests/test_llm_metrics.py +++ b/tests/test_llm_metrics.py @@ -125,7 +125,7 @@ async def test_evaluate_all_retries_fail(self): ) assert result.score == 0.0 assert result.passed is False - assert "LLM error" in result.reasoning + assert result.reasoning is not None and "LLM error" in result.reasoning @pytest.mark.asyncio async def test_binary_scoring(self): From 4103fd40c2b06773c88c722954143feadd9f3398 Mon Sep 17 00:00:00 2001 From: sridharswain Date: Wed, 18 Mar 2026 13:29:22 +0530 Subject: [PATCH 3/5] /docs added to root --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ce3cadb..2f0c47c 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ [![License](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) [![Docs](https://img.shields.io/badge/docs-fasteval.io-blue)](https://fasteval.io) -A **decorator-first LLM evaluation library** for testing AI agents and LLMs. Stack decorators to define evaluation criteria, run with pytest. [Read the docs](https://fasteval.io). +A **decorator-first LLM evaluation library** for testing AI agents and LLMs. Stack decorators to define evaluation criteria, run with pytest. [Read the docs](https://fasteval.io/docs).

The Evaluation Journey -- from non-deterministic LLM outputs to reliable engineering metrics From 371d0c1eb5851ae890f1d9ee2e1d5edc13e94fb5 Mon Sep 17 00:00:00 2001 From: sridharswain Date: Wed, 18 Mar 2026 18:21:19 +0530 Subject: [PATCH 4/5] isort fixes --- tests/test_evaluator.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/test_evaluator.py b/tests/test_evaluator.py index 05a899d..35baa86 100644 --- a/tests/test_evaluator.py +++ b/tests/test_evaluator.py @@ -1,11 +1,10 @@ """Tests for fasteval.core.evaluator.""" import json +from typing import Any import pytest -from typing import Any - from fasteval.core.evaluator import ( METRIC_REGISTRY, Evaluator, From 7b2bfe31ea947bf1fef3188cea726f7747f4141f Mon Sep 17 00:00:00 2001 From: sridharswain Date: Wed, 18 Mar 2026 22:37:26 +0530 Subject: [PATCH 5/5] isort fixes --- .../fasteval_langfuse/utils.py | 8 +- .../fasteval-langfuse/tests/test_client.py | 115 +++++++ .../fasteval-langfuse/tests/test_config.py | 68 ++++ .../tests/test_decorators.py | 301 ++++++++++++++++++ .../tests/test_score_reporter.py | 60 ++++ .../tests/test_trace_fetcher.py | 95 ++++++ plugins/fasteval-langfuse/tests/test_utils.py | 43 +++ plugins/fasteval-langfuse/uv.lock | 12 +- 8 files changed, 693 insertions(+), 9 deletions(-) create mode 100644 plugins/fasteval-langfuse/tests/test_client.py create mode 100644 plugins/fasteval-langfuse/tests/test_config.py create mode 100644 plugins/fasteval-langfuse/tests/test_decorators.py create mode 100644 plugins/fasteval-langfuse/tests/test_score_reporter.py create mode 100644 plugins/fasteval-langfuse/tests/test_trace_fetcher.py diff --git a/plugins/fasteval-langfuse/fasteval_langfuse/utils.py b/plugins/fasteval-langfuse/fasteval_langfuse/utils.py index 3fe61b1..aeae992 100644 --- a/plugins/fasteval-langfuse/fasteval_langfuse/utils.py +++ b/plugins/fasteval-langfuse/fasteval_langfuse/utils.py @@ -57,7 +57,7 @@ def parse_time_range(time_range: str) -> tuple[Optional[str], Optional[str]]: Returns: Tuple of (from_timestamp, to_timestamp) in ISO 8601 format """ - from datetime import datetime, timedelta + from datetime import datetime, timedelta, timezone if not time_range: return None, None @@ -78,8 +78,10 @@ def parse_time_range(time_range: str) -> tuple[Optional[str], Optional[str]]: else: raise ValueError(f"Invalid time range format: {time_range}") - to_timestamp = datetime.utcnow().isoformat() + "Z" - from_timestamp = (datetime.utcnow() - delta).isoformat() + "Z" + to_timestamp = datetime.now(timezone.utc).isoformat().replace("+00:00", "Z") + from_timestamp = ( + (datetime.now(timezone.utc) - delta).isoformat().replace("+00:00", "Z") + ) return from_timestamp, to_timestamp # Handle "YYYY-MM-DD to YYYY-MM-DD" format diff --git a/plugins/fasteval-langfuse/tests/test_client.py b/plugins/fasteval-langfuse/tests/test_client.py new file mode 100644 index 0000000..d34c5b7 --- /dev/null +++ b/plugins/fasteval-langfuse/tests/test_client.py @@ -0,0 +1,115 @@ +"""Tests for fasteval_langfuse.client.""" + +from unittest.mock import MagicMock, patch + +import pytest + +from fasteval_langfuse.client import LangfuseClient + + +def _make_mock_client(): + """Create a LangfuseClient with mocked internals.""" + client = LangfuseClient.__new__(LangfuseClient) + client.public_key = "pk-test" + client.secret_key = "sk-test" + client.host = "https://cloud.langfuse.com" + client._client = MagicMock() + return client + + +class TestLangfuseClientInit: + def test_missing_credentials(self): + with ( + patch.dict( + "os.environ", + {"LANGFUSE_PUBLIC_KEY": "", "LANGFUSE_SECRET_KEY": ""}, + clear=False, + ), + patch( + "fasteval_langfuse.config.get_config", + return_value=MagicMock(public_key=None, secret_key=None, host="h"), + ), + ): + with pytest.raises(ValueError, match="Langfuse credentials required"): + LangfuseClient() + + +class TestFetchTraces: + def test_fetch_traces_basic(self): + client = _make_mock_client() + mock_trace = MagicMock() + mock_trace.id = "t-1" + mock_trace.timestamp = "2026-01-01" + mock_trace.name = "query" + mock_trace.user_id = "u1" + mock_trace.session_id = "s1" + mock_trace.tags = ["prod"] + mock_trace.metadata = {"key": "val"} + mock_trace.input = "hello" + mock_trace.output = "world" + mock_trace.scores = [] + + client._client.fetch_traces.return_value = MagicMock(data=[mock_trace]) + + result = client.fetch_traces(project="test") + assert len(result) == 1 + assert result[0]["id"] == "t-1" + assert result[0]["input"] == "hello" + assert result[0]["output"] == "world" + + def test_fetch_traces_with_filters(self): + client = _make_mock_client() + client._client.fetch_traces.return_value = MagicMock(data=[]) + + client.fetch_traces( + project="prod", + tags=["support"], + user_id="u1", + session_id="s1", + from_timestamp="2026-01-01", + to_timestamp="2026-01-02", + limit=10, + ) + + call_kwargs = client._client.fetch_traces.call_args + assert call_kwargs[1]["tags"] == ["support"] + assert call_kwargs[1]["user_id"] == "u1" + assert call_kwargs[1]["session_id"] == "s1" + assert call_kwargs[1]["limit"] == 10 + + +class TestPushScore: + def test_push_score(self): + client = _make_mock_client() + client.push_score(trace_id="t-1", name="correctness", value=0.9, comment="Good") + client._client.score.assert_called_once_with( + trace_id="t-1", name="correctness", value=0.9, comment="Good" + ) + + +class TestFetchDataset: + def test_fetch_dataset(self): + client = _make_mock_client() + mock_item = MagicMock() + mock_item.id = "item-1" + mock_item.input = "question" + mock_item.expected_output = "answer" + mock_item.metadata = {} + mock_item.version = "v1" + + mock_dataset = MagicMock() + mock_dataset.items = [mock_item] + client._client.get_dataset.return_value = mock_dataset + + result = client.fetch_dataset(name="test-ds") + assert len(result) == 1 + assert result[0]["id"] == "item-1" + assert result[0]["input"] == "question" + assert result[0]["expected_output"] == "answer" + + +class TestFlush: + def test_flush(self): + client = _make_mock_client() + client.flush() + client._client.flush.assert_called_once() diff --git a/plugins/fasteval-langfuse/tests/test_config.py b/plugins/fasteval-langfuse/tests/test_config.py new file mode 100644 index 0000000..5ce50e2 --- /dev/null +++ b/plugins/fasteval-langfuse/tests/test_config.py @@ -0,0 +1,68 @@ +"""Tests for fasteval_langfuse.config.""" + +import os +from unittest.mock import patch + +import pytest + +import fasteval_langfuse.config as config_module +from fasteval_langfuse.config import LangfuseConfig, configure_langfuse, get_config + + +class TestLangfuseConfig: + def test_defaults(self): + with patch.dict(os.environ, {}, clear=True): + config = LangfuseConfig() + assert config.public_key is None + assert config.secret_key is None + assert config.host == "https://cloud.langfuse.com" + assert config.auto_push_scores is True + assert config.batch_size == 50 + assert config.score_name_prefix == "fasteval_" + + def test_from_env(self): + with patch.dict( + os.environ, + { + "LANGFUSE_PUBLIC_KEY": "pk-test", + "LANGFUSE_SECRET_KEY": "sk-test", + "LANGFUSE_HOST": "https://custom.host.com", + }, + ): + config = LangfuseConfig() + assert config.public_key == "pk-test" + assert config.secret_key == "sk-test" + assert config.host == "https://custom.host.com" + + def test_custom_values(self): + config = LangfuseConfig( + public_key="pk", + secret_key="sk", + default_project="prod", + auto_push_scores=False, + batch_size=100, + score_name_prefix="custom_", + ) + assert config.default_project == "prod" + assert config.auto_push_scores is False + assert config.batch_size == 100 + assert config.score_name_prefix == "custom_" + + +class TestConfigureLangfuse: + def setup_method(self): + config_module._config = None + + def test_configure_and_get(self): + custom = LangfuseConfig(public_key="pk", secret_key="sk") + configure_langfuse(custom) + assert get_config() is custom + + def test_get_config_default(self): + config = get_config() + assert isinstance(config, LangfuseConfig) + + def test_get_config_singleton(self): + c1 = get_config() + c2 = get_config() + assert c1 is c2 diff --git a/plugins/fasteval-langfuse/tests/test_decorators.py b/plugins/fasteval-langfuse/tests/test_decorators.py new file mode 100644 index 0000000..5d41a43 --- /dev/null +++ b/plugins/fasteval-langfuse/tests/test_decorators.py @@ -0,0 +1,301 @@ +"""Tests for fasteval_langfuse.decorators.""" + +from unittest.mock import MagicMock, patch + +import pytest + +from fasteval_langfuse.decorators import ( + FASTEVAL_DATA_ATTR, + FASTEVAL_METRICS_ATTR, + langfuse_dataset, + langfuse_traces, +) + + +class TestLangfuseTracesDecorator: + def test_attaches_data_attr(self): + @langfuse_traces(project="prod", filter_tags=["support"]) + def my_func(trace_id, input, output, context, metadata): + pass + + assert hasattr(my_func, FASTEVAL_DATA_ATTR) + data = getattr(my_func, FASTEVAL_DATA_ATTR) + assert data["type"] == "langfuse_traces" + assert data["project"] == "prod" + + def test_preserves_metrics(self): + def my_func(): + pass + + setattr(my_func, FASTEVAL_METRICS_ATTR, ["metric1"]) + + decorated = langfuse_traces(project="prod")(my_func) + assert getattr(decorated, FASTEVAL_METRICS_ATTR) == ["metric1"] + + def test_default_sampling_name(self): + @langfuse_traces() + def my_func(): + pass + + data = getattr(my_func, FASTEVAL_DATA_ATTR) + assert data["sampling"] == "NoSamplingStrategy" + + def test_custom_sampling_name(self): + mock_sampling = MagicMock() + mock_sampling.name = "CustomStrategy" + + @langfuse_traces(sampling=mock_sampling) + def my_func(): + pass + + data = getattr(my_func, FASTEVAL_DATA_ATTR) + assert data["sampling"] == "CustomStrategy" + + def test_async_function(self): + @langfuse_traces() + async def my_func(): + pass + + assert hasattr(my_func, FASTEVAL_DATA_ATTR) + + +class TestLangfuseDatasetDecorator: + def test_attaches_data_attr(self): + @langfuse_dataset(name="qa-set", version="v2") + def my_func(input, expected_output): + pass + + data = getattr(my_func, FASTEVAL_DATA_ATTR) + assert data["type"] == "langfuse_dataset" + assert data["name"] == "qa-set" + assert data["version"] == "v2" + + def test_preserves_metrics(self): + def my_func(): + pass + + setattr(my_func, FASTEVAL_METRICS_ATTR, ["metric1"]) + + decorated = langfuse_dataset(name="ds")(my_func) + assert getattr(decorated, FASTEVAL_METRICS_ATTR) == ["metric1"] + + def test_async_function(self): + @langfuse_dataset(name="ds") + async def my_func(): + pass + + assert hasattr(my_func, FASTEVAL_DATA_ATTR) + + +class TestExecuteTraceEvaluation: + @patch("fasteval.core.scoring.get_last_score_result") + @patch("fasteval_langfuse.decorators.format_sampling_stats") + @patch("fasteval_langfuse.decorators.ScoreReporter") + @patch("fasteval_langfuse.decorators.TraceFetcher") + @patch("fasteval_langfuse.decorators.LangfuseClient") + def test_basic_execution( + self, + mock_client_cls, + mock_fetcher_cls, + mock_reporter_cls, + mock_format_stats, + mock_get_score, + ): + mock_fetcher = MagicMock() + mock_fetcher_cls.return_value = mock_fetcher + mock_fetcher.fetch_and_sample.return_value = ( + [{"id": "t-1", "input": "q", "output": "a", "metadata": {}}], + 1, + ) + mock_fetcher.map_trace_to_params.return_value = { + "trace_id": "t-1", + "input": "q", + "output": "a", + "context": None, + "metadata": {}, + } + + mock_reporter = MagicMock() + mock_reporter_cls.return_value = mock_reporter + mock_get_score.return_value = None + + from fasteval_langfuse.decorators import _execute_trace_evaluation + + called_with = {} + + def my_func(**kwargs): + called_with.update(kwargs) + + _execute_trace_evaluation( + func=my_func, + is_async=False, + project="prod", + filter_tags=None, + time_range=None, + user_id=None, + session_id=None, + limit=None, + sampling=None, + auto_push_scores=True, + args=(), + kwargs={}, + ) + + assert called_with["trace_id"] == "t-1" + mock_reporter.flush.assert_called_once() + + @patch("fasteval.core.scoring.get_last_score_result") + @patch("fasteval_langfuse.decorators.format_sampling_stats") + @patch("fasteval_langfuse.decorators.ScoreReporter") + @patch("fasteval_langfuse.decorators.TraceFetcher") + @patch("fasteval_langfuse.decorators.LangfuseClient") + def test_pushes_scores_when_result_exists( + self, + mock_client_cls, + mock_fetcher_cls, + mock_reporter_cls, + mock_format_stats, + mock_get_score, + ): + mock_fetcher = MagicMock() + mock_fetcher_cls.return_value = mock_fetcher + mock_fetcher.fetch_and_sample.return_value = ( + [{"id": "t-1", "input": "q", "output": "a", "metadata": {}}], + 1, + ) + mock_fetcher.map_trace_to_params.return_value = { + "trace_id": "t-1", + "input": "q", + "output": "a", + "context": None, + "metadata": {}, + } + + mock_reporter = MagicMock() + mock_reporter_cls.return_value = mock_reporter + + mock_result = MagicMock() + mock_result.metric_results = [MagicMock()] + mock_result.aggregate_score = 0.9 + mock_get_score.return_value = mock_result + + from fasteval_langfuse.decorators import _execute_trace_evaluation + + def my_func(**kwargs): + pass + + _execute_trace_evaluation( + func=my_func, + is_async=False, + project=None, + filter_tags=None, + time_range=None, + user_id=None, + session_id=None, + limit=None, + sampling=None, + auto_push_scores=True, + args=(), + kwargs={}, + ) + + mock_reporter.push_evaluation_result.assert_called_once() + + @patch("fasteval.core.scoring.get_last_score_result") + @patch("fasteval_langfuse.decorators.format_sampling_stats") + @patch("fasteval_langfuse.decorators.ScoreReporter") + @patch("fasteval_langfuse.decorators.TraceFetcher") + @patch("fasteval_langfuse.decorators.LangfuseClient") + def test_skips_push_when_auto_push_false( + self, + mock_client_cls, + mock_fetcher_cls, + mock_reporter_cls, + mock_format_stats, + mock_get_score, + ): + mock_fetcher = MagicMock() + mock_fetcher_cls.return_value = mock_fetcher + mock_fetcher.fetch_and_sample.return_value = ( + [{"id": "t-1", "input": "q", "output": "a", "metadata": {}}], + 1, + ) + mock_fetcher.map_trace_to_params.return_value = { + "trace_id": "t-1", + "input": "q", + "output": "a", + "context": None, + "metadata": {}, + } + + mock_reporter = MagicMock() + mock_reporter_cls.return_value = mock_reporter + + mock_result = MagicMock() + mock_get_score.return_value = mock_result + + from fasteval_langfuse.decorators import _execute_trace_evaluation + + def my_func(**kwargs): + pass + + _execute_trace_evaluation( + func=my_func, + is_async=False, + project=None, + filter_tags=None, + time_range=None, + user_id=None, + session_id=None, + limit=None, + sampling=None, + auto_push_scores=False, + args=(), + kwargs={}, + ) + + mock_reporter.push_evaluation_result.assert_not_called() + + @patch("fasteval.core.scoring.get_last_score_result") + @patch("fasteval_langfuse.decorators.format_sampling_stats") + @patch("fasteval_langfuse.decorators.ScoreReporter") + @patch("fasteval_langfuse.decorators.TraceFetcher") + @patch("fasteval_langfuse.decorators.LangfuseClient") + def test_prints_stats_when_sampling( + self, + mock_client_cls, + mock_fetcher_cls, + mock_reporter_cls, + mock_format_stats, + mock_get_score, + ): + mock_fetcher = MagicMock() + mock_fetcher_cls.return_value = mock_fetcher + mock_fetcher.fetch_and_sample.return_value = ([], 0) + + mock_reporter = MagicMock() + mock_reporter_cls.return_value = mock_reporter + mock_get_score.return_value = None + mock_format_stats.return_value = "stats" + + from fasteval_langfuse.decorators import _execute_trace_evaluation + + mock_sampling = MagicMock() + mock_sampling.name = "TestStrategy" + + _execute_trace_evaluation( + func=lambda **kw: None, + is_async=False, + project=None, + filter_tags=None, + time_range=None, + user_id=None, + session_id=None, + limit=None, + sampling=mock_sampling, + auto_push_scores=True, + args=(), + kwargs={}, + ) + + mock_format_stats.assert_called_once() diff --git a/plugins/fasteval-langfuse/tests/test_score_reporter.py b/plugins/fasteval-langfuse/tests/test_score_reporter.py new file mode 100644 index 0000000..8a6806a --- /dev/null +++ b/plugins/fasteval-langfuse/tests/test_score_reporter.py @@ -0,0 +1,60 @@ +"""Tests for fasteval_langfuse.score_reporter.""" + +from unittest.mock import MagicMock, patch + +from fasteval_langfuse.score_reporter import ScoreReporter + + +def _make_reporter(): + """Create a ScoreReporter with mocked client and config.""" + mock_client = MagicMock() + reporter = ScoreReporter.__new__(ScoreReporter) + reporter.client = mock_client + reporter.config = MagicMock() + reporter.config.auto_push_scores = True + reporter.config.score_name_prefix = "fasteval_" + return reporter + + +class TestPushEvaluationResult: + def test_pushes_metric_scores(self): + reporter = _make_reporter() + + mr1 = MagicMock() + mr1.metric_name = "correctness" + mr1.score = 0.9 + mr1.reasoning = "Good" + + mr2 = MagicMock() + mr2.metric_name = "relevance" + mr2.score = 0.8 + mr2.reasoning = None + + reporter.push_evaluation_result( + trace_id="t-1", metric_results=[mr1, mr2], aggregate_score=0.85 + ) + + calls = reporter.client.push_score.call_args_list + assert len(calls) == 3 # 2 metrics + 1 aggregate + assert calls[0][1]["name"] == "fasteval_correctness" + assert calls[0][1]["value"] == 0.9 + assert calls[1][1]["name"] == "fasteval_relevance" + assert calls[2][1]["name"] == "fasteval_aggregate" + assert calls[2][1]["value"] == 0.85 + + def test_skips_when_auto_push_disabled(self): + reporter = _make_reporter() + reporter.config.auto_push_scores = False + + reporter.push_evaluation_result( + trace_id="t-1", metric_results=[MagicMock()], aggregate_score=0.5 + ) + + reporter.client.push_score.assert_not_called() + + +class TestFlush: + def test_flush(self): + reporter = _make_reporter() + reporter.flush() + reporter.client.flush.assert_called_once() diff --git a/plugins/fasteval-langfuse/tests/test_trace_fetcher.py b/plugins/fasteval-langfuse/tests/test_trace_fetcher.py new file mode 100644 index 0000000..0ef58db --- /dev/null +++ b/plugins/fasteval-langfuse/tests/test_trace_fetcher.py @@ -0,0 +1,95 @@ +"""Tests for fasteval_langfuse.trace_fetcher.""" + +from unittest.mock import MagicMock + +from fasteval_langfuse.trace_fetcher import TraceFetcher + + +def _make_fetcher_with_mock(traces): + """Create a TraceFetcher with a mocked client.""" + mock_client = MagicMock() + mock_client.fetch_traces.return_value = traces + fetcher = TraceFetcher.__new__(TraceFetcher) + fetcher.client = mock_client + return fetcher + + +class TestFetchAndSample: + def test_basic_fetch(self, sample_traces): + fetcher = _make_fetcher_with_mock(sample_traces) + result, total = fetcher.fetch_and_sample() + assert total == 3 + assert len(result) == 3 + + def test_with_time_range(self, sample_traces): + fetcher = _make_fetcher_with_mock(sample_traces) + result, total = fetcher.fetch_and_sample(time_range="last_24h") + assert total == 3 + + def test_with_sampling(self, sample_traces): + from fasteval_langfuse.sampling import RandomSamplingStrategy + + fetcher = _make_fetcher_with_mock(sample_traces) + sampling = RandomSamplingStrategy(sample_size=1, seed=42) + result, total = fetcher.fetch_and_sample(sampling=sampling) + assert total == 3 + assert len(result) == 1 + + def test_with_filters(self, sample_traces): + fetcher = _make_fetcher_with_mock(sample_traces) + fetcher.fetch_and_sample( + project="prod", + filter_tags=["tag1"], + user_id="u1", + session_id="s1", + limit=10, + ) + call_kwargs = fetcher.client.fetch_traces.call_args[1] + assert call_kwargs["project"] == "prod" + assert call_kwargs["tags"] == ["tag1"] + assert call_kwargs["user_id"] == "u1" + assert call_kwargs["limit"] == 10 + + +class TestMapTraceToParams: + def test_basic_mapping(self, sample_traces): + fetcher = _make_fetcher_with_mock([]) + params = fetcher.map_trace_to_params(sample_traces[0]) + assert params["trace_id"] == "trace-1" + assert params["input"] == "What is Python?" + assert params["output"] == "Python is a programming language" + assert params["metadata"] == {"user_type": "free"} + + def test_dict_input(self): + fetcher = _make_fetcher_with_mock([]) + trace = { + "id": "t-1", + "input": {"query": "hello"}, + "output": {"response": "world"}, + "metadata": {}, + } + params = fetcher.map_trace_to_params(trace) + assert params["input"] == "hello" + assert params["output"] == "world" + + def test_dict_input_fallback(self): + fetcher = _make_fetcher_with_mock([]) + trace = { + "id": "t-1", + "input": {"custom_key": "value"}, + "output": {"custom_key": "value"}, + "metadata": {}, + } + params = fetcher.map_trace_to_params(trace) + assert "custom_key" in params["input"] + + def test_context_extraction(self, sample_traces): + fetcher = _make_fetcher_with_mock([]) + # trace-3 has context in metadata + params = fetcher.map_trace_to_params(sample_traces[2]) + assert params["context"] == ["RAG combines retrieval with generation"] + + def test_no_context(self, sample_traces): + fetcher = _make_fetcher_with_mock([]) + params = fetcher.map_trace_to_params(sample_traces[0]) + assert params["context"] is None diff --git a/plugins/fasteval-langfuse/tests/test_utils.py b/plugins/fasteval-langfuse/tests/test_utils.py index 32f5958..bddc1a7 100644 --- a/plugins/fasteval-langfuse/tests/test_utils.py +++ b/plugins/fasteval-langfuse/tests/test_utils.py @@ -45,6 +45,43 @@ def test_parse_time_range_to_format(): assert to_ts == "2026-02-05T00:00:00Z" +def test_parse_time_range_empty(): + """Test empty time range returns None.""" + from_ts, to_ts = parse_time_range("") + assert from_ts is None + assert to_ts is None + + +def test_parse_time_range_invalid(): + """Test invalid time range format raises ValueError.""" + import pytest + + with pytest.raises(ValueError, match="Unsupported"): + parse_time_range("invalid_format") + + +def test_parse_time_range_invalid_duration(): + """Test invalid duration suffix raises ValueError.""" + import pytest + + with pytest.raises(ValueError, match="Invalid time range"): + parse_time_range("last_5m") + + +def test_extract_context_non_list_value(): + """Test context extraction with non-list, non-string value.""" + trace = {"metadata": {"context": 42}} + context = extract_context_from_trace(trace) + assert context == ["42"] + + +def test_extract_context_none_value(): + """Test context extraction skips None values.""" + trace = {"metadata": {"context": None, "retrieved_docs": ["doc1"]}} + context = extract_context_from_trace(trace) + assert context == ["doc1"] + + def test_format_sampling_stats(): """Test sampling statistics formatting.""" stats = format_sampling_stats(200, 1000, "RandomSamplingStrategy") @@ -52,3 +89,9 @@ def test_format_sampling_stats(): assert "1,000" in stats assert "20.0%" in stats assert "RandomSamplingStrategy" in stats + + +def test_format_sampling_stats_zero_total(): + """Test formatting with zero total traces.""" + stats = format_sampling_stats(0, 0, "NoSamplingStrategy") + assert "0.0%" in stats diff --git a/plugins/fasteval-langfuse/uv.lock b/plugins/fasteval-langfuse/uv.lock index f968e61..dc11090 100644 --- a/plugins/fasteval-langfuse/uv.lock +++ b/plugins/fasteval-langfuse/uv.lock @@ -233,7 +233,7 @@ name = "exceptiongroup" version = "1.3.1" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "typing-extensions", marker = "python_full_version < '3.13'" }, + { name = "typing-extensions", marker = "python_full_version < '3.11'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/50/79/66800aadf48771f6b62f7eb014e352e5d06856655206165d775e675a02c9/exceptiongroup-1.3.1.tar.gz", hash = "sha256:8b412432c6055b0b7d14c310000ae93352ed6754f70fa8f7c34141f91c4e3219", size = 30371, upload-time = "2025-11-21T23:01:54.787Z" } wheels = [ @@ -242,7 +242,7 @@ wheels = [ [[package]] name = "fasteval-core" -version = "1.0.0a1" +version = "1.2.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "openai" }, @@ -250,14 +250,14 @@ dependencies = [ { name = "pytest" }, { name = "rouge-score" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/09/78/29c4e9b1a74b4cfdd07407d06dcf7d62037df39ac566a82a00ec91bfb6dd/fasteval_core-1.0.0a1.tar.gz", hash = "sha256:dd2f84ca3f3f2e1b39c109086dcb5b740ba3abee851bb4c9adca4a5b269230c0", size = 78220, upload-time = "2026-02-12T19:12:33.07Z" } +sdist = { url = "https://files.pythonhosted.org/packages/26/8d/9e1c566572f1ca966a0e88409c6132a7761777258c59c6c7fd92d6139c8f/fasteval_core-1.2.0.tar.gz", hash = "sha256:fce78b637a06d35e0ac8d4702ddc6beda9cec867fc5c8e6ba8f59c572daa1042", size = 86406, upload-time = "2026-03-09T11:31:19.151Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/bf/25/06b36cebd8192a15385fac77a0b832dbb2a21ad0d92ccf4d1f5212f7df30/fasteval_core-1.0.0a1-py3-none-any.whl", hash = "sha256:8dc0c5901dc7a1df65ce4c7766c10e0de404bf53ce1100fb31c93bf5c9e0d98a", size = 95801, upload-time = "2026-02-12T19:12:30.106Z" }, + { url = "https://files.pythonhosted.org/packages/d3/53/8fffcab213dad0b3cb88d92dcd888f8a5dd89542e991eecc37eb895a170f/fasteval_core-1.2.0-py3-none-any.whl", hash = "sha256:65e39ad1aba6fa7564e50582c226ee2e94feff47c10ec95ab61e9c1a7c285edb", size = 107601, upload-time = "2026-03-09T11:31:17.648Z" }, ] [[package]] name = "fasteval-langfuse" -version = "1.0.0a1" +version = "2.1.3" source = { editable = "." } dependencies = [ { name = "fasteval-core" }, @@ -276,7 +276,7 @@ dev = [ [package.metadata] requires-dist = [ - { name = "fasteval-core", specifier = ">=1.0.0a1" }, + { name = "fasteval-core", specifier = ">=1.2.0" }, { name = "langfuse", specifier = ">=2.0.0" }, { name = "pydantic", specifier = ">=2.0.0" }, ]