pytest-llm-assert 0.1.0__py3-none-any.whl → 0.2.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  """pytest-llm-assert: Simple LLM-powered assertions for any pytest test."""
2
2
 
3
- from pytest_llm_assert.core import LLMAssert
3
+ from pytest_llm_assert.core import AssertionResult, LLMAssert, LLMResponse
4
4
 
5
- __all__ = ["LLMAssert"]
5
+ __all__ = ["LLMAssert", "AssertionResult", "LLMResponse"]
6
6
  __version__ = "0.1.0"
pytest_llm_assert/core.py CHANGED
@@ -6,14 +6,35 @@ import json
6
6
  import os
7
7
  import re
8
8
  from dataclasses import dataclass
9
+ from pathlib import Path
9
10
  from typing import TYPE_CHECKING, Callable
10
11
 
11
12
  import litellm
12
13
 
14
+ # Load default system prompt from file
15
+ _PROMPTS_DIR = Path(__file__).parent / "prompts"
16
+ _DEFAULT_SYSTEM_PROMPT = (_PROMPTS_DIR / "system_prompt.md").read_text().strip()
17
+
13
18
  if TYPE_CHECKING:
14
19
  from typing import Any
15
20
 
16
21
 
22
+ @dataclass(slots=True)
23
+ class LLMResponse:
24
+ """Response details from the last LLM call.
25
+
26
+ Access via `llm.response` after making an assertion call.
27
+ """
28
+
29
+ model: str | None = None
30
+ prompt_tokens: int | None = None
31
+ completion_tokens: int | None = None
32
+ total_tokens: int | None = None
33
+ cost: float | None = None
34
+ response_id: str | None = None
35
+ created: int | None = None
36
+
37
+
17
38
  @dataclass(slots=True)
18
39
  class AssertionResult:
19
40
  """Result of an LLM assertion with rich repr for pytest."""
@@ -57,7 +78,8 @@ class LLMAssert:
57
78
 
58
79
  Args:
59
80
  model: LiteLLM model string (e.g., "openai/gpt-5-mini", "azure/gpt-4o")
60
- api_key: API key (supports ${ENV_VAR} expansion). For Azure, leave empty to use Entra ID.
81
+ api_key: API key (supports ${ENV_VAR} expansion).
82
+ For Azure, leave empty to use Entra ID.
61
83
  api_base: Custom API base URL (required for Azure)
62
84
  **kwargs: Additional parameters passed to LiteLLM
63
85
  """
@@ -66,6 +88,8 @@ class LLMAssert:
66
88
  self.api_base = api_base
67
89
  self.kwargs = kwargs
68
90
  self._azure_ad_token_provider: Callable[[], str] | None = None
91
+ self._system_prompt: str = _DEFAULT_SYSTEM_PROMPT
92
+ self.response: LLMResponse | None = None
69
93
 
70
94
  # Auto-configure Azure Entra ID when no API key is provided
71
95
  if self._is_azure_model() and not self._has_azure_api_key():
@@ -86,7 +110,7 @@ class LLMAssert:
86
110
  Uses LiteLLM's built-in helper which leverages DefaultAzureCredential:
87
111
  - Azure CLI credentials (az login)
88
112
  - Managed Identity
89
- - Environment variables (AZURE_CLIENT_ID, AZURE_CLIENT_SECRET, AZURE_TENANT_ID)
113
+ - Environment variables (AZURE_CLIENT_ID, AZURE_CLIENT_SECRET, ...)
90
114
  - Visual Studio Code credentials
91
115
  """
92
116
  try:
@@ -102,6 +126,20 @@ class LLMAssert:
102
126
  # Credential not available
103
127
  return None
104
128
 
129
+ @property
130
+ def system_prompt(self) -> str:
131
+ """Get the system prompt used for LLM assertions."""
132
+ return self._system_prompt
133
+
134
+ @system_prompt.setter
135
+ def system_prompt(self, value: str) -> None:
136
+ """Set a custom system prompt for LLM assertions.
137
+
138
+ The prompt should instruct the LLM to evaluate content against a criterion
139
+ and respond in JSON format with 'result' (PASS/FAIL) and 'reasoning' keys.
140
+ """
141
+ self._system_prompt = value
142
+
105
143
  @staticmethod
106
144
  def _expand_env(value: str) -> str:
107
145
  """Expand ${VAR} patterns in string."""
@@ -116,7 +154,7 @@ class LLMAssert:
116
154
  return text[: max_len - 3] + "..."
117
155
 
118
156
  def _call_llm(self, messages: list[dict[str, str]]) -> str:
119
- """Call the LLM and return response content."""
157
+ """Call the LLM and return response content. Updates self.response."""
120
158
  kwargs = {**self.kwargs}
121
159
 
122
160
  # Use Azure AD token provider if configured (Entra ID auth)
@@ -130,7 +168,27 @@ class LLMAssert:
130
168
  api_base=self.api_base,
131
169
  **kwargs,
132
170
  )
133
- return response.choices[0].message.content or "" # type: ignore[union-attr]
171
+ content = response.choices[0].message.content or "" # type: ignore[union-attr]
172
+
173
+ # Store response details on instance
174
+ self.response = LLMResponse(
175
+ model=getattr(response, "model", None),
176
+ response_id=getattr(response, "id", None),
177
+ created=getattr(response, "created", None),
178
+ )
179
+
180
+ # Extract usage info
181
+ usage = getattr(response, "usage", None)
182
+ if usage:
183
+ self.response.prompt_tokens = getattr(usage, "prompt_tokens", None)
184
+ self.response.completion_tokens = getattr(usage, "completion_tokens", None)
185
+ self.response.total_tokens = getattr(usage, "total_tokens", None)
186
+
187
+ # Extract cost from hidden params (litellm calculates this)
188
+ if hasattr(response, "_hidden_params"):
189
+ self.response.cost = response._hidden_params.get("response_cost")
190
+
191
+ return content
134
192
 
135
193
  def __call__(self, content: str, criterion: str) -> AssertionResult:
136
194
  """Evaluate if content meets the given criterion.
@@ -145,12 +203,7 @@ class LLMAssert:
145
203
  messages = [
146
204
  {
147
205
  "role": "system",
148
- "content": (
149
- "You are an assertion evaluator. "
150
- "Evaluate if the given content meets the specified criterion.\n\n"
151
- "Respond in JSON format:\n"
152
- '{"result": "PASS" or "FAIL", "reasoning": "brief explanation"}'
153
- ),
206
+ "content": self._system_prompt,
154
207
  },
155
208
  {
156
209
  "role": "user",
@@ -158,12 +211,12 @@ class LLMAssert:
158
211
  },
159
212
  ]
160
213
 
161
- response = self._call_llm(messages)
214
+ response_text = self._call_llm(messages)
162
215
 
163
216
  # Parse JSON response
164
217
  try:
165
218
  # Handle potential markdown code blocks
166
- text = response.strip()
219
+ text = response_text.strip()
167
220
  if text.startswith("```"):
168
221
  text = text.split("```")[1]
169
222
  if text.startswith("json"):
@@ -173,10 +226,10 @@ class LLMAssert:
173
226
  reasoning = data.get("reasoning", "")
174
227
  except (json.JSONDecodeError, AttributeError):
175
228
  # Fallback to line-based parsing
176
- lines = response.strip().split("\n", 1)
229
+ lines = response_text.strip().split("\n", 1)
177
230
  first_line = lines[0].strip().upper()
178
231
  passed = first_line in ("PASS", "YES", "TRUE", "PASSED")
179
- reasoning = lines[1].strip() if len(lines) > 1 else response
232
+ reasoning = lines[1].strip() if len(lines) > 1 else response_text
180
233
 
181
234
  return AssertionResult(
182
235
  passed=passed,
@@ -0,0 +1,4 @@
1
+ You are an assertion evaluator. Evaluate if the given content meets the specified criterion.
2
+
3
+ Respond in JSON format:
4
+ {"result": "PASS" or "FAIL", "reasoning": "brief explanation"}
@@ -0,0 +1,135 @@
1
+ Metadata-Version: 2.4
2
+ Name: pytest-llm-assert
3
+ Version: 0.2.0
4
+ Summary: Simple LLM-powered assertions for any pytest test
5
+ Project-URL: Homepage, https://github.com/sbroenne/pytest-llm-assert
6
+ Project-URL: Documentation, https://github.com/sbroenne/pytest-llm-assert#readme
7
+ Project-URL: Repository, https://github.com/sbroenne/pytest-llm-assert
8
+ Author: Stefan Broenner
9
+ License-Expression: MIT
10
+ License-File: LICENSE
11
+ Keywords: ai,assertions,llm,pytest,testing
12
+ Classifier: Development Status :: 3 - Alpha
13
+ Classifier: Framework :: Pytest
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: License :: OSI Approved :: MIT License
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Programming Language :: Python :: 3.13
20
+ Requires-Python: >=3.11
21
+ Requires-Dist: azure-identity>=1.25
22
+ Requires-Dist: litellm>=1.81
23
+ Requires-Dist: pytest>=9.0
24
+ Provides-Extra: dev
25
+ Requires-Dist: pre-commit>=4.5; extra == 'dev'
26
+ Requires-Dist: pyright>=1.1.408; extra == 'dev'
27
+ Requires-Dist: pytest-cov>=6.0; extra == 'dev'
28
+ Requires-Dist: pytest>=9.0; extra == 'dev'
29
+ Requires-Dist: python-dotenv>=1.2; extra == 'dev'
30
+ Requires-Dist: ruff>=0.14; extra == 'dev'
31
+ Description-Content-Type: text/markdown
32
+
33
+ # pytest-llm-assert
34
+
35
+ [![PyPI version](https://img.shields.io/pypi/v/pytest-llm-assert)](https://pypi.org/project/pytest-llm-assert/)
36
+ [![Python versions](https://img.shields.io/pypi/pyversions/pytest-llm-assert)](https://pypi.org/project/pytest-llm-assert/)
37
+ [![CI](https://github.com/sbroenne/pytest-llm-assert/actions/workflows/ci.yml/badge.svg)](https://github.com/sbroenne/pytest-llm-assert/actions/workflows/ci.yml)
38
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
39
+
40
+ **Natural language assertions for pytest.**
41
+
42
+ Testing a text-to-SQL agent? Validating LLM-generated code? Checking if error messages are helpful? Now you can:
43
+
44
+ ```python
45
+ def test_sql_agent_output(llm):
46
+ sql = my_agent.generate("Get names of users over 21")
47
+
48
+ assert llm(sql, "Is this a valid SQL query that selects user names filtered by age > 21?")
49
+ ```
50
+
51
+ The LLM evaluates your criterion and returns pass/fail — no regex, no parsing, no exact string matching.
52
+
53
+ ## Features
54
+
55
+ - **Semantic assertions** — Assert meaning, not exact strings
56
+ - **100+ LLM providers** — OpenAI, Azure, Anthropic, Ollama, Vertex AI, Bedrock via [LiteLLM](https://docs.litellm.ai/)
57
+ - **pytest native** — Works as a standard pytest plugin/fixture
58
+ - **Response introspection** — Access tokens, cost, and reasoning via `llm.response`
59
+
60
+ ## Installation
61
+
62
+ ```bash
63
+ pip install pytest-llm-assert
64
+ ```
65
+
66
+ ## Quick Start
67
+
68
+ ```python
69
+ # conftest.py
70
+ import pytest
71
+ from pytest_llm_assert import LLMAssert
72
+
73
+ @pytest.fixture
74
+ def llm():
75
+ return LLMAssert(model="openai/gpt-5-mini")
76
+ ```
77
+
78
+ ```python
79
+ # test_my_agent.py
80
+ def test_generated_sql_is_correct(llm):
81
+ sql = "SELECT name FROM users WHERE age > 21 ORDER BY name"
82
+ assert llm(sql, "Is this a valid SELECT query that returns names of users over 21?")
83
+
84
+ def test_error_message_is_helpful(llm):
85
+ error = "ValidationError: 'port' must be an integer, got 'abc'"
86
+ assert llm(error, "Does this explain what went wrong and how to fix it?")
87
+
88
+ def test_summary_captures_key_points(llm):
89
+ summary = generate_summary(document)
90
+ assert llm(summary, "Does this mention the contract duration and parties involved?")
91
+ ```
92
+
93
+ ## Setup
94
+
95
+ Works out of the box with cloud identity — no API keys to manage:
96
+
97
+ ```bash
98
+ # Azure (Entra ID)
99
+ export AZURE_API_BASE=https://your-resource.openai.azure.com
100
+ az login
101
+
102
+ # Google Cloud (Vertex AI)
103
+ gcloud auth application-default login
104
+
105
+ # AWS (Bedrock)
106
+ aws configure # Uses IAM credentials
107
+ ```
108
+
109
+ Supports 100+ providers via [LiteLLM](https://docs.litellm.ai/docs/providers) — including API key auth for OpenAI, Anthropic, Ollama, and more.
110
+
111
+ ## Documentation
112
+
113
+ - **[Configuration](docs/configuration.md)** — All providers, CLI options, environment variables
114
+ - **[API Reference](docs/api-reference.md)** — Full API documentation
115
+ - **[Comparing Judge Models](docs/comparing-models.md)** — Evaluate which LLM works best for your assertions
116
+ - **[Examples](examples/)** — Working pytest examples
117
+
118
+ ## Related
119
+
120
+ - **[pytest-aitest](https://github.com/sbroenne/pytest-aitest)** — Full framework for testing MCP servers, CLIs, and AI agents
121
+ - **[Contributing](CONTRIBUTING.md)** — Development setup and guidelines
122
+
123
+ ## Requirements
124
+
125
+ - Python 3.11+
126
+ - pytest 8.0+
127
+ - An LLM (OpenAI, Azure, Anthropic, etc.) or local [Ollama](https://ollama.ai/)
128
+
129
+ ## Security
130
+
131
+ - **Sensitive data**: Test content is sent to LLM providers — consider data policies
132
+
133
+ ## License
134
+
135
+ MIT
@@ -0,0 +1,9 @@
1
+ pytest_llm_assert/__init__.py,sha256=OcOVlsvqZBBxMzrQssLbaWVkc4qKSvdOMtLVibzDfFQ,233
2
+ pytest_llm_assert/core.py,sha256=B3lah5pPZ3VMbtzZ3bBtdJ2o8r_mZb7_aw375_hBC2Q,8145
3
+ pytest_llm_assert/plugin.py,sha256=g3sotHAeUXMuOsFQdaoIbn0CY24i-1CPv0EglrC5qtE,1327
4
+ pytest_llm_assert/prompts/system_prompt.md,sha256=RhSaYrpOjVcVwuG_af_Q50kHFhqXGOCKzubSYBXFzTA,181
5
+ pytest_llm_assert-0.2.0.dist-info/METADATA,sha256=SdFu02CtgVAK14bwjP10clZgxFLQF8yEtiIm5Ct6BJE,4723
6
+ pytest_llm_assert-0.2.0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
7
+ pytest_llm_assert-0.2.0.dist-info/entry_points.txt,sha256=YEYg83TT6znVYdvFvZHJEOJ8XsZbcrqV9pY8uM-ThQE,49
8
+ pytest_llm_assert-0.2.0.dist-info/licenses/LICENSE,sha256=wHrdHpzRm4rdlyMdj-sQw7aou6kHPujW0VmRBEhInJ8,1072
9
+ pytest_llm_assert-0.2.0.dist-info/RECORD,,
@@ -1,246 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: pytest-llm-assert
3
- Version: 0.1.0
4
- Summary: Simple LLM-powered assertions for any pytest test
5
- Project-URL: Homepage, https://github.com/sbroenne/pytest-llm-assert
6
- Project-URL: Documentation, https://github.com/sbroenne/pytest-llm-assert#readme
7
- Project-URL: Repository, https://github.com/sbroenne/pytest-llm-assert
8
- Author: Stefan Broenner
9
- License-Expression: MIT
10
- License-File: LICENSE
11
- Keywords: ai,assertions,llm,pytest,testing
12
- Classifier: Development Status :: 3 - Alpha
13
- Classifier: Framework :: Pytest
14
- Classifier: Intended Audience :: Developers
15
- Classifier: License :: OSI Approved :: MIT License
16
- Classifier: Programming Language :: Python :: 3
17
- Classifier: Programming Language :: Python :: 3.11
18
- Classifier: Programming Language :: Python :: 3.12
19
- Classifier: Programming Language :: Python :: 3.13
20
- Requires-Python: >=3.11
21
- Requires-Dist: azure-identity>=1.15
22
- Requires-Dist: litellm>=1.55
23
- Requires-Dist: pytest>=8.0
24
- Provides-Extra: dev
25
- Requires-Dist: pyright>=1.1; extra == 'dev'
26
- Requires-Dist: pytest>=8.0; extra == 'dev'
27
- Requires-Dist: python-dotenv>=1.0; extra == 'dev'
28
- Requires-Dist: ruff>=0.8; extra == 'dev'
29
- Description-Content-Type: text/markdown
30
-
31
- # pytest-llm-assert
32
-
33
- **Natural language assertions for pytest.**
34
-
35
- A pytest plugin that lets you write semantic assertions using LLMs. Stop writing brittle string checks — let an LLM understand what you actually mean.
36
-
37
- ## The Problem
38
-
39
- ```python
40
- # ❌ These all fail even though they mean "success":
41
- assert "success" in response # Fails on "Succeeded", "successful", "It worked!"
42
- assert response == "Operation completed successfully" # Exact match? Really?
43
- assert re.match(r"success|succeeded|worked", response, re.I) # Regex hell
44
- ```
45
-
46
- ```python
47
- # You're testing a text-to-SQL agent. How do you validate the output?
48
-
49
- # ❌ Exact match? There are many valid ways to write the same query:
50
- assert sql == "SELECT name FROM users WHERE age > 21"
51
-
52
- # ❌ Regex? Good luck covering all valid SQL syntax:
53
- assert re.match(r"SELECT\s+name\s+FROM\s+users", sql, re.I)
54
-
55
- # ❌ Parse it? Now you need a SQL parser as a test dependency:
56
- assert sqlparse.parse(sql)[0].get_type() == "SELECT"
57
- ```
58
-
59
- ## The Solution
60
-
61
- ```python
62
- # ✅ Just say what you mean:
63
- assert llm(response, "Does this indicate the operation succeeded?")
64
- assert llm(sql, "Is this a valid SELECT query that returns user names for users over 21?")
65
- ```
66
-
67
- ## Why This Works
68
-
69
- The LLM evaluates your criterion against the content and returns a judgment. It understands:
70
-
71
- - **Synonyms**: "success", "succeeded", "worked", "completed" all mean the same thing
72
- - **Semantics**: Two SQL queries can be equivalent even with different syntax
73
- - **Context**: "The operation failed successfully" is actually a failure
74
- - **Intent**: Generated code can be correct even if it's not identical to a reference
75
-
76
-
77
- ## Installation
78
-
79
- ```bash
80
- pip install pytest-llm-assert
81
- ```
82
-
83
- ## Setup
84
-
85
- This library uses [LiteLLM](https://docs.litellm.ai/) under the hood, giving you access to **100+ LLM providers** with a unified API.
86
-
87
- ```bash
88
- # OpenAI
89
- export OPENAI_API_KEY=sk-...
90
-
91
- # Azure OpenAI with Entra ID (no API keys)
92
- export AZURE_API_BASE=https://your-resource.openai.azure.com
93
- export AZURE_API_VERSION=2024-02-15-preview
94
- # Uses DefaultAzureCredential: az login, managed identity, etc.
95
-
96
- # Ollama (local)
97
- # Just run: ollama serve
98
- ```
99
-
100
- See [LiteLLM docs](https://docs.litellm.ai/docs/providers) for all providers including Vertex AI, Bedrock, Anthropic, and more.
101
-
102
- ## Quick Start
103
-
104
- ```python
105
- from pytest_llm_assert import LLMAssert
106
-
107
- llm = LLMAssert(model="openai/gpt-5-mini") # Uses OPENAI_API_KEY from env
108
-
109
- # Semantic assertions - returns True/False
110
- assert llm("Operation completed successfully", "Does this indicate success?")
111
- assert llm("Error: connection refused", "Does this indicate a failure?")
112
- assert not llm("All tests passed", "Does this indicate a failure?")
113
- ```
114
-
115
- ## Real Examples
116
-
117
- First, create a fixture in `conftest.py`:
118
-
119
- ```python
120
- # conftest.py
121
- import pytest
122
- from pytest_llm_assert import LLMAssert
123
-
124
- @pytest.fixture
125
- def llm():
126
- return LLMAssert(model="openai/gpt-5-mini")
127
- ```
128
-
129
- Then use it in your tests:
130
-
131
- ### Testing Error Messages
132
-
133
- ```python
134
- def test_validation_error_is_helpful(llm):
135
- """Error messages should explain the problem clearly."""
136
- error_msg = "ValidationError: 'port' must be an integer, got 'not-a-number'"
137
-
138
- assert llm(error_msg, "Does this explain that port must be a number?")
139
- assert llm(error_msg, "Does this indicate which field failed validation?")
140
- ```
141
-
142
- ### Testing Generated SQL
143
-
144
- ```python
145
- def test_query_builder_generates_valid_sql(llm):
146
- """Query builder should produce semantically correct SQL."""
147
- query = "SELECT name FROM users WHERE age > 21 ORDER BY name"
148
-
149
- assert llm(query, "Is this a valid SELECT query that returns names of users over 21?")
150
- ```
151
-
152
- ### Testing LLM Output
153
-
154
- ```python
155
- def test_summary_is_comprehensive(llm):
156
- """Generated summaries should capture key points."""
157
- summary = "The contract establishes a 2-year service agreement between..."
158
-
159
- assert llm(summary, "Does this summarize a legal contract?")
160
- assert llm(summary, "Does this mention the contract duration?")
161
- ```
162
-
163
- ## Comparing Judge Models
164
-
165
- Not sure which LLM to use as your assertion judge? Run the same tests against multiple models to find the best one for your use case:
166
-
167
- ```python
168
- import pytest
169
- from pytest_llm_assert import LLMAssert
170
-
171
- MODELS = ["openai/gpt-5-mini", "anthropic/claude-sonnet-4-20250514", "ollama/llama3.1:8b"]
172
-
173
- @pytest.fixture(params=MODELS)
174
- def llm(request):
175
- return LLMAssert(model=request.param)
176
-
177
- def test_validates_sql_equivalence(llm):
178
- """Test which models can judge SQL semantic equivalence."""
179
- sql = "SELECT u.name FROM users AS u WHERE u.age >= 22"
180
- assert llm(sql, "Is this equivalent to selecting names of users over 21?")
181
- ```
182
-
183
- Output shows which judge models correctly evaluate your criterion:
184
- ```
185
- test_validates_sql_equivalence[openai/gpt-5-mini] PASSED
186
- test_validates_sql_equivalence[anthropic/claude-sonnet-4-20250514] PASSED
187
- test_validates_sql_equivalence[ollama/llama3.1:8b] FAILED
188
- ```
189
-
190
- > **Note:** This tests which LLM makes a good *judge* for your assertions. To test AI agents themselves (e.g., "does my coding agent produce working code?"), see [pytest-aitest](https://github.com/sbroenne/pytest-aitest).
191
-
192
- ## Configuration
193
-
194
- ### Programmatic
195
-
196
- ```python
197
- from pytest_llm_assert import LLMAssert
198
-
199
- llm = LLMAssert(
200
- model="openai/gpt-5-mini",
201
- api_key="sk-...", # Or use env var
202
- api_base="https://...", # Custom endpoint
203
- )
204
- ```
205
-
206
- ### CLI Options
207
-
208
- ```bash
209
- pytest --llm-model=openai/gpt-5-mini
210
- pytest --llm-api-key='${OPENAI_API_KEY}' # Env var expansion
211
- pytest --llm-api-base=http://localhost:8080
212
- ```
213
-
214
- ### Environment Variables
215
-
216
- ```bash
217
- export OPENAI_API_KEY=sk-...
218
- export LLM_MODEL=openai/gpt-5-mini
219
- ```
220
-
221
- ## API Reference
222
-
223
- ### `LLMAssert(model, api_key=None, api_base=None, **kwargs)`
224
-
225
- Create an LLM assertion helper.
226
-
227
- - `model`: LiteLLM model string (e.g., `"openai/gpt-5-mini"`, `"azure/gpt-4o"`)
228
- - `api_key`: Optional API key (or use environment variables)
229
- - `api_base`: Optional custom endpoint
230
- - `**kwargs`: Additional parameters passed to LiteLLM
231
-
232
- ### `llm(content, criterion) -> AssertionResult`
233
-
234
- Evaluate if content meets the criterion.
235
-
236
- - Returns `AssertionResult` which is truthy if criterion is met
237
- - Access `.reasoning` for the LLM's explanation
238
-
239
- ## See Also
240
-
241
- - **[Examples](examples/)** — Example pytest tests showing basic usage, model comparison, and fixture patterns
242
- - **[pytest-aitest](https://github.com/sbroenne/pytest-aitest)** — Full framework for testing MCP servers, CLIs, and AI agents. Uses pytest-llm-assert for the judge.
243
-
244
- ## License
245
-
246
- MIT
@@ -1,8 +0,0 @@
1
- pytest_llm_assert/__init__.py,sha256=gp_z4g6Yf9SnjwEyZc6kPSqEWw2Nyb5er84HRuUaXCA,169
2
- pytest_llm_assert/core.py,sha256=sDQvcus5EqHQ-_iQyLH2XB9nL4UhLpiWGTXnGhO7YyE,6351
3
- pytest_llm_assert/plugin.py,sha256=g3sotHAeUXMuOsFQdaoIbn0CY24i-1CPv0EglrC5qtE,1327
4
- pytest_llm_assert-0.1.0.dist-info/METADATA,sha256=cGK3fmb5T0ZKOBtM0PkmnRkAaGnLZ1aEDhBD5U8-1UQ,7713
5
- pytest_llm_assert-0.1.0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
6
- pytest_llm_assert-0.1.0.dist-info/entry_points.txt,sha256=YEYg83TT6znVYdvFvZHJEOJ8XsZbcrqV9pY8uM-ThQE,49
7
- pytest_llm_assert-0.1.0.dist-info/licenses/LICENSE,sha256=wHrdHpzRm4rdlyMdj-sQw7aou6kHPujW0VmRBEhInJ8,1072
8
- pytest_llm_assert-0.1.0.dist-info/RECORD,,