Skip to content

Commit f5ec3b5

Browse files
committed
Ensure the baseline example app works
1 parent d1ad307 commit f5ec3b5

7 files changed

Lines changed: 121 additions & 81 deletions

File tree

examples/fastapi-vite/backend/__init__.py

Lines changed: 0 additions & 1 deletion
This file was deleted.
Lines changed: 58 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,80 @@
11
"""FastAPI application entry point."""
22

3+
from __future__ import annotations
4+
5+
from collections.abc import AsyncGenerator
6+
7+
import agent
38
import fastapi
49
import fastapi.middleware.cors
5-
from routes import chat
10+
import fastapi.responses
11+
import pydantic
12+
import storage
613

7-
api = fastapi.FastAPI(
14+
import vercel_ai_sdk as ai
15+
import vercel_ai_sdk.ai_sdk_ui
16+
17+
app = fastapi.FastAPI(
818
title="py-ai-fastapi-chat",
919
description="Chat demo using Python Vercel AI SDK",
1020
)
1121

12-
api.add_middleware(
22+
app.add_middleware(
1323
fastapi.middleware.cors.CORSMiddleware,
1424
allow_origins=["*"],
1525
allow_credentials=True,
1626
allow_methods=["*"],
1727
allow_headers=["*"],
1828
)
1929

20-
api.include_router(chat.router)
21-
2230

23-
@api.get("/health")
31+
@app.get("/health")
2432
async def health() -> dict[str, str]:
2533
"""Health check endpoint."""
2634
return {"status": "ok"}
2735

2836

29-
app = fastapi.FastAPI()
30-
app.mount("/api", api)
37+
file_storage = storage.FileStorage()
38+
39+
40+
class ChatRequest(pydantic.BaseModel):
41+
"""Request body for the chat endpoint."""
42+
43+
messages: list[ai.ai_sdk_ui.UIMessage]
44+
session_id: str | None = None
45+
46+
47+
@app.post("/chat")
48+
async def chat(request: ChatRequest) -> fastapi.responses.StreamingResponse:
49+
"""Handle chat requests and stream responses."""
50+
messages = ai.ai_sdk_ui.to_messages(request.messages)
51+
session_id = request.session_id or "default"
52+
checkpoint_key = f"checkpoint:{session_id}"
53+
54+
llm = agent.get_llm()
55+
56+
# Checkpoints resume an *interrupted* run (e.g. a hook that needed
57+
# user input in serverless mode). Each normal chat turn is a fresh
58+
# run — the frontend carries the full message history — so we only
59+
# load a checkpoint when one was saved from a previous incomplete run.
60+
saved = await file_storage.get(checkpoint_key)
61+
checkpoint = ai.Checkpoint.model_validate(saved) if saved else None
62+
63+
result = ai.run(agent.graph, llm, messages, agent.TOOLS, checkpoint=checkpoint)
64+
65+
async def stream_response() -> AsyncGenerator[str]:
66+
async for chunk in ai.ai_sdk_ui.to_sse_stream(result):
67+
yield chunk
68+
69+
# If the run completed (no pending hooks), clear the checkpoint
70+
# so the next request starts fresh. If hooks are pending, save
71+
# the checkpoint so the next request can resume from here.
72+
if result.pending_hooks:
73+
await file_storage.put(checkpoint_key, result.checkpoint.model_dump())
74+
else:
75+
await file_storage.delete(checkpoint_key)
76+
77+
return fastapi.responses.StreamingResponse(
78+
stream_response(),
79+
headers=ai.ai_sdk_ui.UI_MESSAGE_STREAM_HEADERS,
80+
)

examples/fastapi-vite/backend/pyproject.toml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,9 @@ description = "Chat demo using Python Vercel AI SDK with FastAPI"
55
requires-python = ">=3.12"
66
dependencies = [
77
"fastapi[standard]>=0.128.1",
8-
"vercel-ai-sdk>=0.0.1.dev5",
8+
"vercel-ai-sdk",
9+
# "vercel-ai-sdk>=0.0.1.dev5",
910
]
11+
12+
[tool.uv.sources]
13+
vercel-ai-sdk = { path = "../../.." }

examples/fastapi-vite/backend/routes/__init__.py

Lines changed: 0 additions & 1 deletion
This file was deleted.

examples/fastapi-vite/backend/routes/chat.py

Lines changed: 0 additions & 60 deletions
This file was deleted.

examples/fastapi-vite/backend/uv.lock

Lines changed: 58 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

examples/fastapi-vite/frontend/vite.config.ts

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,4 @@ export default defineConfig({
1111
'@': path.resolve(__dirname, './src'),
1212
},
1313
},
14-
server: {
15-
proxy: {
16-
'/api': 'http://localhost:8000',
17-
},
18-
},
1914
})

0 commit comments

Comments
 (0)