Skip to content

Commit

Permalink
uprev uv and distribute examples (#27)
Browse files Browse the repository at this point in the history
  • Loading branch information
samuelcolvin authored Nov 3, 2024
1 parent 4254e7e commit cf92860
Show file tree
Hide file tree
Showing 9 changed files with 239 additions and 156 deletions.
5 changes: 4 additions & 1 deletion pydantic_ai/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
from importlib.metadata import version

from .agent import Agent
from .shared import AgentError, CallContext, ModelRetry, UnexpectedModelBehaviour, UserError

__all__ = 'Agent', 'AgentError', 'CallContext', 'ModelRetry', 'UnexpectedModelBehaviour', 'UserError'
__all__ = 'Agent', 'AgentError', 'CallContext', 'ModelRetry', 'UnexpectedModelBehaviour', 'UserError', '__version__'
__version__ = version('pydantic_ai')
45 changes: 35 additions & 10 deletions examples/README.md → pydantic_ai_examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,35 @@ Examples of how to use Pydantic AI and what it can do.

## Usage

These examples are distributed with `pydantic-ai` so you can run them either by cloning the [pydantic-ai repo](https://github.com/pydantic/pydantic-ai) or by simply installing `pydantic-ai` from PyPI with `pip` or `uv`.

Either way you'll need to install extra dependencies to run some examples, you just need to install the `examples` optional dependency group.

If you've cloned the repo, add the extra dependencies with:

```bash
uv sync --extra examples
```

If you've installed `pydantic-ai` via pip/uv, you can install the extra dependencies with:

```bash
pip install 'pydantic-ai[examples]'
# of if you're using uv
uv add 'pydantic-ai[examples]'
```

To run the examples, run:

```bash
uv run -m examples.<example_module_name>
python -m pydantic_ai_examples.<example_module_name>
```
(replace `python` with just `uv run` if you're using `uv`)

But you'll probably want to edit examples as well as just running them, so you can copy the examples to a new directory with:

```bash
python -m pydantic_ai_examples --copy-to examples/
```

## Examples
Expand All @@ -19,17 +44,17 @@ uv run -m examples.<example_module_name>
Simple example of using Pydantic AI to construct a Pydantic model from a text input.

```bash
uv run --extra examples -m examples.pydantic_model
(uv run/python) -m pydantic_ai_examples.pydantic_model
```

This examples uses `openai:gpt-4o` by default but it works well with other models, e.g. you can run it
This examples uses `openai:gpt-4o` by default, but it works well with other models, e.g. you can run it
with Gemini using:

```bash
PYDANTIC_AI_MODEL=gemini-1.5-pro uv run --extra examples -m examples.pydantic_model
PYDANTIC_AI_MODEL=gemini-1.5-pro (uv run/python) -m pydantic_ai_examples.pydantic_model
```

(or `PYDANTIC_AI_MODEL=gemini-1.5-flash...`)
(or `PYDANTIC_AI_MODEL=gemini-1.5-flash ...`)

### `sql_gen.py`

Expand All @@ -38,13 +63,13 @@ PYDANTIC_AI_MODEL=gemini-1.5-pro uv run --extra examples -m examples.pydantic_mo
Example demonstrating how to use Pydantic AI to generate SQL queries based on user input.

```bash
uv run --extra examples -m examples.sql_gen
(uv run/python) -m pydantic_ai_examples.sql_gen
```

or to use a custom prompt:

```bash
uv run --extra examples -m examples.sql_gen "find me whatever"
(uv run/python) -m pydantic_ai_examples.sql_gen "find me whatever"
```

This model uses `gemini-1.5-flash` by default since Gemini is good at single shot queries.
Expand All @@ -66,7 +91,7 @@ To run this example properly, you'll need two extra API keys:
**(Note if either key is missing, the code will fall back to dummy data.)**

```bash
uv run --extra examples -m examples.weather
(uv run/python) -m pydantic_ai_examples.weather
```

This example uses `openai:gpt-4o` by default. Gemini seems to be unable to handle the multiple tool
Expand Down Expand Up @@ -97,13 +122,13 @@ We also mount the postgresql `data` directory locally to persist the data if you
With that running, we can build the search database with (**WARNING**: this requires the `OPENAI_API_KEY` env variable and will calling the OpenAI embedding API around 300 times to generate embeddings for each section of the documentation):

```bash
uv run --extra examples -m examples.rag build
(uv run/python) -m pydantic_ai_examples.rag build
```

(Note building the database doesn't use Pydantic AI right now, instead it uses the OpenAI SDK directly.)

You can then ask the agent a question with:

```bash
uv run --extra examples -m examples.rag search "How do I configure logfire to work with FastAPI?"
(uv run/python) -m pydantic_ai_examples.rag search "How do I configure logfire to work with FastAPI?"
```
46 changes: 46 additions & 0 deletions pydantic_ai_examples/__main__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
"""Very simply CLI to aid in running the examples, and for copying examples code to a new directory.
See README.md for more information.
"""
import argparse
import sys
from pathlib import Path


def cli():
this_dir = Path(__file__).parent

parser = argparse.ArgumentParser(prog='pydantic_ai_examples', description=__doc__, formatter_class=argparse.RawTextHelpFormatter)
parser.add_argument('-v', '--version', action='store_true', help='show the version and exit')
parser.add_argument('--copy-to', dest='DEST', help='Copy all examples to a new directory')

args = parser.parse_args()
if args.version:
from pydantic_ai import __version__

print(f'pydantic_ai v{__version__}')
elif args.DEST:
copy_to(this_dir, Path(args.DEST))
else:
parser.print_help()


def copy_to(this_dir: Path, dst: Path):
if dst.exists():
print(f'Error: destination path "{dst}" already exists', file=sys.stderr)
sys.exit(1)

dst.mkdir(parents=True)

count = 0
for file in this_dir.glob('*.*'):
with open(file, 'rb') as src_file:
with open(dst / file.name, 'wb') as dst_file:
dst_file.write(src_file.read())
count += 1

print(f'Copied {count} example files to "{dst}"')


if __name__ == '__main__':
cli()
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
Run with:
uv run --extra examples -m examples.pydantic_model
uv run -m pydantic_ai_examples.pydantic_model
"""

import os
Expand Down
8 changes: 4 additions & 4 deletions examples/rag.py → pydantic_ai_examples/rag.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
"""RAG example with pydantic-ai.
"""RAG example with pydantic-ai — using vector search to augment a chat agent.
Run pgvector with:
Expand All @@ -10,11 +10,11 @@
Build the search DB with:
uv run --extra examples -m examples.rag build
uv run -m pydantic_ai_examples.rag build
Ask the agent a question with:
uv run --extra examples -m examples.rag search "How do I configure logfire to work with FastAPI?"
uv run -m pydantic_ai_examples.rag search "How do I configure logfire to work with FastAPI?"
"""

from __future__ import annotations as _annotations
Expand Down Expand Up @@ -226,5 +226,5 @@ def slugify(value: str, separator: str, unicode: bool = False) -> str:
q = 'How do I configure logfire to work with FastAPI?'
asyncio.run(run_agent(q))
else:
print('uv run --extra examples -m examples.rag build|search', file=sys.stderr)
print('uv run --extra examples -m pydantic_ai_examples.rag build|search', file=sys.stderr)
sys.exit(1)
2 changes: 1 addition & 1 deletion examples/sql_gen.py → pydantic_ai_examples/sql_gen.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
Run with:
uv run --extra examples -m examples.sql_gen "show me logs from yesterday, with level 'error'"
uv run -m pydantic_ai_examples.sql_gen "show me logs from yesterday, with level 'error'"
"""

import asyncio
Expand Down
2 changes: 1 addition & 1 deletion examples/weather.py → pydantic_ai_examples/weather.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
Run with:
uv run --extra examples -m examples.weather
uv run -m pydantic_ai_examples.weather
"""

from __future__ import annotations as _annotations
Expand Down
10 changes: 5 additions & 5 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,8 @@ examples = [
"logfire[asyncpg]>=1.2.0",
]

[tool.uv]
dev-dependencies = [
[dependency-groups]
dev = [
"dirty-equals>=0.8.0",
"mypy>=1.11.2",
"pyright>=1.1.384",
Expand All @@ -66,10 +66,10 @@ dev-dependencies = [
]

[tool.hatch.build.targets.wheel]
packages = ["pydantic_ai"]
packages = ["pydantic_ai", "pydantic_ai_examples"]

[tool.hatch.build.targets.sdist]
include = ["/README.md", "/Makefile", "/pydantic_ai", "/tests"]
include = ["/README.md", "/Makefile", "/pydantic_ai", "/pydantic_ai_examples", "/tests"]

[tool.ruff]
line-length = 120
Expand Down Expand Up @@ -116,7 +116,7 @@ quote-style = "single"
typeCheckingMode = "strict"
reportUnnecessaryTypeIgnoreComment = true
reportMissingTypeStubs = false
include = ["pydantic_ai", "tests", "examples"]
include = ["pydantic_ai", "tests", "pydantic_ai_examples"]
venvPath = ".venv"
# see https://github.com/microsoft/pyright/issues/7771 - we don't want to error on decorated functions in tests
# which are not otherwise used
Expand Down
Loading

0 comments on commit cf92860

Please sign in to comment.