Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Ability to Specify Gemini Safety Settings #790

Draft
wants to merge 9 commits into
base: main
Choose a base branch
from

Conversation

dAIsySHEng1
Copy link
Contributor

@dAIsySHEng1 dAIsySHEng1 commented Jan 28, 2025

fix #373

Add ability to specify Gemini safety settings when doing an agent run. This addition allows you to specify safety categories and thresholds via the model_settings field. Valid settings are based on the Gemini API docs. This should hopefully add flexibility to deal with Gemini's safety guardrails as needed, aligning with what one is able to currently do in the vertexai package.

Example Code:

from pydantic_ai import Agent
from pydantic_ai.models.gemini import GeminiModel, GeminiModelSettings

GEMINI_API_KEY = '<api key here>'

model = GeminiModel('gemini-1.5-flash', api_key=GEMINI_API_KEY)
agent = Agent(model, system_prompt='Be concise, reply with one sentence.')

result = agent.run_sync(
    'Write a list of 3 mean things that I might say to Paddington after he steals my marmalade:',
    model_settings=GeminiModelSettings(
        gemini_safety_settings=[
            {'category': 'HARM_CATEGORY_HARASSMENT', 'threshold': 'BLOCK_LOW_AND_ABOVE'},
            {'category': 'HARM_CATEGORY_HATE_SPEECH', 'threshold': 'BLOCK_LOW_AND_ABOVE'},
            {'category': 'HARM_CATEGORY_DANGEROUS_CONTENT', 'threshold': 'BLOCK_LOW_AND_ABOVE'},
        ],
    ),
)

To Do:

  • Fix validation errors when running live test
    • Add blocked field to _GeminiSafetyRating
    • Revise code to raise an UnexpectedModelBehavior error when finish_reason is 'SAFETY'
  • Figure out way to deal with potential duplicates (deferred)
  • Do more testing and add tests
  • Update docs (Gemini, VertexAI?)
  • Add more detail to PR description

@sydney-runkle sydney-runkle self-assigned this Jan 28, 2025
Copy link
Member

@sydney-runkle sydney-runkle left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks fantastic, @dAIsySHEng1! Great work.

In your PR description, you can add "fix #373", and when this PR is merged, it'll automatically close that issue. If you could add a bit more of a detailed description (just a few sentences), that would be great as well.

The test looks great. Given that we'll probably want to test this sort of pattern often, we should generalize this further (given the similar pattern in the above test). That lies outside of the scope of this PR, though.

pydantic_ai_slim/pydantic_ai/models/gemini.py Outdated Show resolved Hide resolved
pydantic_ai_slim/pydantic_ai/models/gemini.py Outdated Show resolved Hide resolved
@sydney-runkle
Copy link
Member

Ah one other thing - the example you sent me on slack is hilarious, let's add this to the gemini model docs :)

@zaidalyafeai
Copy link

Will this also work for VertexAIModel?

See <https://ai.google.dev/gemini-api/docs/safety-settings> for API docs.
"""

category: Literal[
Copy link

@Finndersen Finndersen Jan 30, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it perhaps be better to make these StrEnum? e.g.

class HarmCategory(StrEnum):
    UNSPECIFIED = auto()
    DEROGATORY = auto()
    ....

This actually already exists in the SDK

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And perhaps even make GeminiSafetySettings a dataclass instead?

Copy link
Member

@sydney-runkle sydney-runkle Feb 4, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think Literal is fine here - it's consistent with other patterns we're using in this file. If we were using the sdk, I definitely think we should pull from there.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why make GeminiSafetySettings a dataclass? Does it need any methods?

Copy link

@Finndersen Finndersen Feb 4, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Enums provide better developer experience with stronger type safety, IDE autocomplete, enumeration, avoiding typos etc

Copy link

@Finndersen Finndersen Feb 4, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And dataclasses often don't have any methods, that's not their purpose. It's for having a date structure similar to Pydantic models but without overhead of validation. Again provides better developer experience of attribute instead of key access, with IDE autocomplete, stronger type safety, defaults, etc

Copy link

@Finndersen Finndersen Feb 4, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I prefer using enums & dataclasses over str literals and typeddicts for more explicit typing, But I realise that opinion is somewhat subjective

Copy link
Contributor

@hyperlint-ai hyperlint-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The style guide flagged several spelling errors that seemed like false positives. We skipped posting inline suggestions for the following words:

  • Chinoy
  • Hussain

@github-actions github-actions bot temporarily deployed to deploy-preview January 31, 2025 05:08 Inactive
docs/agents.md Outdated
@@ -226,6 +226,29 @@ print(result_sync.data)
#> Rome
```

For Gemini models, safety settings for requests can be specified via [`GeminiModelSettings`][pydantic_ai.models.gemini.GeminiModelSettings]. For example:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can remove my previous example, this one is better.

Just preface with:

If you wish to further customize model behavior, you can use a subclass of [`ModelSettings`][pydantic_ai.settings.ModelSettings], like [`GeminiModelSettings`][pydantic_ai.models.gemini.GeminiModelSettings], associated with your model of choice.
For example:

docs/agents.md Outdated
],
),
)
print(result.data)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe wrap this in a try/except block and print the error response?

Comment on lines +249 to +253
if 'content' not in response['candidates'][0]:
if response['candidates'][0].get('finish_reason') == 'SAFETY':
raise UnexpectedModelBehavior('Safety settings triggered', str(response))
else:
raise UnexpectedModelBehavior('Content field missing from Gemini response', str(response))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm going to chat with the team tomorrow morning to see if this is the right way to go about this. I think we might just want to catch the validation issue earlier.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok confirmed, we can move forward with this approach for now 👍

@github-actions github-actions bot temporarily deployed to deploy-preview February 5, 2025 19:13 Inactive
@github-actions github-actions bot temporarily deployed to deploy-preview February 6, 2025 01:57 Inactive
@github-actions github-actions bot temporarily deployed to deploy-preview February 6, 2025 02:34 Inactive
@github-actions github-actions bot temporarily deployed to deploy-preview February 6, 2025 02:59 Inactive
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Failing due to SAFETY errors using Gemini-1.5
4 participants