97e91a83f3
Ruff / Ruff (push) Has been cancelled
Test / Core Tests (push) Has been cancelled
Test / Offline Coverage Tests (Python 3.10) (push) Has been cancelled
Test / Offline Coverage Tests (Python 3.11) (push) Has been cancelled
Test / Offline Coverage Tests (Python 3.12) (push) Has been cancelled
Test / Offline Coverage Tests (Python 3.13) (push) Has been cancelled
Test / Offline Coverage Tests (Python 3.9) (push) Has been cancelled
Test / Full Coverage (Python 3.11) (push) Has been cancelled
Test / Core Provider Tests (OpenAI) (push) Has been cancelled
Test / Core Provider Tests (Anthropic) (push) Has been cancelled
Test / Core Provider Tests (Google) (push) Has been cancelled
Test / Core Provider Tests (Other) (push) Has been cancelled
Test / Anthropic Tests (push) Has been cancelled
Test / Gemini Tests (push) Has been cancelled
Test / Google GenAI Tests (push) Has been cancelled
Test / Vertex AI Tests (push) Has been cancelled
Test / OpenAI Tests (push) Has been cancelled
Test / Writer Tests (push) Has been cancelled
Test / Auto Client Tests (push) Has been cancelled
ty / type-check (push) Has been cancelled
129 lines
4.3 KiB
Python
129 lines
4.3 KiB
Python
from typing import Annotated
|
|
from pydantic import BaseModel, Field, ValidationInfo, field_validator
|
|
import pytest
|
|
import instructor
|
|
from .util import models, modes
|
|
from itertools import product
|
|
|
|
|
|
class Message(BaseModel):
|
|
content: Annotated[str, Field(..., description="The content to be checked")]
|
|
|
|
@field_validator("content")
|
|
@classmethod
|
|
def no_banned_words(cls, v: str, info: ValidationInfo):
|
|
context = info.context
|
|
if context:
|
|
banned_words = context.get("banned_words", [])
|
|
banned_words_found = [
|
|
word for word in banned_words if word.lower() in v.lower()
|
|
]
|
|
if banned_words_found:
|
|
raise ValueError(
|
|
f"Banned words found in content: {', '.join(banned_words_found)}. Please rewrite without using these words."
|
|
)
|
|
return v
|
|
|
|
|
|
@pytest.mark.parametrize("model, mode", product(models, modes))
|
|
def test_banned_words_validation(model: str, mode: instructor.Mode, client):
|
|
client = instructor.from_openai(client, mode=mode)
|
|
|
|
# Test with content containing a banned word
|
|
with pytest.raises(Exception): # noqa: B017
|
|
response = client.chat.completions.create(
|
|
model=model,
|
|
response_model=Message,
|
|
max_retries=0,
|
|
messages=[
|
|
{
|
|
"role": "user",
|
|
"content": "Say the word `hate`.",
|
|
},
|
|
],
|
|
context={"banned_words": ["hate", "violence", "discrimination"]},
|
|
)
|
|
|
|
|
|
@pytest.mark.parametrize("model, mode", product(models, modes))
|
|
def test_banned_words_validation_old(model: str, mode: instructor.Mode, client):
|
|
client = instructor.from_openai(client, mode=mode)
|
|
|
|
# Test with content containing a banned word
|
|
with pytest.raises(Exception): # noqa: B017
|
|
response = client.chat.completions.create(
|
|
model=model,
|
|
response_model=Message,
|
|
max_retries=0,
|
|
messages=[
|
|
{
|
|
"role": "user",
|
|
"content": "Say the word `hate`.",
|
|
},
|
|
],
|
|
validation_context={"banned_words": ["hate", "violence", "discrimination"]},
|
|
)
|
|
|
|
|
|
@pytest.mark.parametrize("model, mode", product(models, modes))
|
|
def test_no_banned_words_validation(model: str, mode: instructor.Mode, client):
|
|
client = instructor.from_openai(client, mode=mode)
|
|
|
|
# Test with content containing a banned word
|
|
response = client.chat.completions.create(
|
|
model=model,
|
|
response_model=Message,
|
|
max_retries=0,
|
|
messages=[
|
|
{
|
|
"role": "user",
|
|
"content": "Say the word `love`.",
|
|
},
|
|
],
|
|
context={"banned_words": ["hate", "violence", "discrimination"]},
|
|
)
|
|
|
|
assert response.content == "love", f"Expected 'love', got {response.content}"
|
|
|
|
|
|
@pytest.mark.parametrize("model, mode", product(models, modes))
|
|
def test_forced_words_validation(model: str, mode: instructor.Mode, client):
|
|
class Response(BaseModel):
|
|
content: str
|
|
|
|
@field_validator("content")
|
|
@classmethod
|
|
def must_contain_words(cls, v: str, info: ValidationInfo):
|
|
context = info.context
|
|
if context:
|
|
must_contain_words = context.get("must_contain_words", [])
|
|
missing_words = [
|
|
word for word in must_contain_words if word.lower() not in v.lower()
|
|
]
|
|
if missing_words:
|
|
error_message = f"Content must contain the following words: {', '.join(missing_words)}"
|
|
raise ValueError(error_message)
|
|
return v
|
|
|
|
client = instructor.from_openai(client, mode=mode)
|
|
|
|
response = client.chat.completions.create(
|
|
model=model,
|
|
response_model=Response,
|
|
messages=[
|
|
{
|
|
"role": "user",
|
|
"content": """
|
|
Make a sentence that contains the words
|
|
{% for word in must_contain_words %}
|
|
`{{ word }}`
|
|
{% endfor %}
|
|
""",
|
|
},
|
|
],
|
|
context={"must_contain_words": ["love", "peace", "joy"]},
|
|
)
|
|
assert "love" in response.content.lower()
|
|
assert "peace" in response.content.lower()
|
|
assert "joy" in response.content.lower()
|