Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ Jinja2 conditionals: `{%- if cookiecutter.enable_rag %}...{%- endif %}`
## Key Features

- **5 AI Frameworks**: PydanticAI, PydanticDeep, LangChain, LangGraph, DeepAgents
- **4 LLM Providers**: OpenAI, Anthropic, Google Gemini, OpenRouter
- **5 LLM Providers**: OpenAI, Anthropic, Google Gemini, OpenRouter, OrcaRouter
- **RAG**: 4 vector stores (Milvus, Qdrant, ChromaDB, pgvector), 4 embedding providers, reranking, image description
- **Document Sources**: Local files (CLI), API upload, Google Drive (service account), S3/MinIO
- **Sync Sources**: Configurable connectors (Google Drive, S3) with scheduled sync
Expand Down
2 changes: 1 addition & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ template/
## Key Design Decisions

- 5 AI frameworks: PydanticAI, PydanticDeep, LangChain, LangGraph, DeepAgents
- 4 LLM providers: OpenAI, Anthropic, Google Gemini, OpenRouter
- 5 LLM providers: OpenAI, Anthropic, Google Gemini, OpenRouter, OrcaRouter
- 4 vector store backends: Milvus, Qdrant, ChromaDB, pgvector
- 4 embedding providers: OpenAI, Voyage, Gemini (multimodal), SentenceTransformers
- RAG document sources: local files (CLI), Google Drive, S3/MinIO
Expand Down
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -714,7 +714,7 @@ They also ship a ready-to-use **`.claude/` toolkit** that adapts to the options
### 🤖 AI/LLM First

- **5 AI Frameworks** - [PydanticAI](https://ai.pydantic.dev), [PydanticDeep](https://github.com/vstorm-co/pydantic-deep), [LangChain](https://python.langchain.com), [LangGraph](https://langchain-ai.github.io/langgraph/), [DeepAgents](https://github.com/vstorm-co/pydantic-deepagents)
- **4 LLM Providers** - OpenAI, Anthropic, Google Gemini, OpenRouter
- **5 LLM Providers** - OpenAI, Anthropic, Google Gemini, OpenRouter, OrcaRouter
- **RAG** - Document ingestion, vector search, reranking (Milvus, Qdrant, ChromaDB, pgvector)
- **WebSocket Streaming** - Real-time responses with full event access
- **Rich Chat UI** - Specialized tool-call cards (web search, knowledge base, Python, charts, skills), live subagent feed, citation sources panel, plan/task checklist, reasoning view, and in-chat file previews
Expand Down Expand Up @@ -754,7 +754,7 @@ They also ship a ready-to-use **`.claude/` toolkit** that adapts to the options
| Category | Integrations |
|----------|-------------|
| **AI Frameworks** | PydanticAI, PydanticDeep, LangChain, LangGraph, DeepAgents |
| **LLM Providers** | OpenAI, Anthropic, Google Gemini, OpenRouter |
| **LLM Providers** | OpenAI, Anthropic, Google Gemini, OpenRouter, OrcaRouter |
| **RAG / Vector Stores** | Milvus, Qdrant, ChromaDB, pgvector |
| **RAG Sources** | Local files, API upload, Google Drive, S3/MinIO, Sync Sources (per-org UI, scheduled) |
| **Embeddings** | OpenAI, Voyage, Gemini (multimodal), SentenceTransformers |
Expand Down Expand Up @@ -786,7 +786,7 @@ They also ship a ready-to-use **`.claude/` toolkit** that adapts to the options
│ │ PydanticAI · LangChain · LangGraph · DeepAgents │ │
│ │ ──────────────────────────────────────────────────────────── │ │
│ │ Tools: datetime · web_search (Tavily) · search_knowledge_base │ │
│ │ Providers: OpenAI · Anthropic · Gemini · OpenRouter │ │
│ │ Providers: OpenAI · Anthropic · Gemini · OpenRouter · OrcaRouter │ │
│ └─────────────────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────────────────┐ │
Expand Down Expand Up @@ -890,7 +890,7 @@ See [Architecture Documentation](https://github.com/vstorm-co/full-stack-ai-agen

## 🤖 AI Agent

Choose from **5 AI frameworks** and **4 LLM providers** when generating your project:
Choose from **5 AI frameworks** and **5 LLM providers** when generating your project:

```bash
# PydanticAI with OpenAI (default)
Expand Down
6 changes: 3 additions & 3 deletions docs/guides/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ All available options when generating a project.
| `--orm` | `sqlalchemy`, `sqlmodel` | ORM choice (SQLModel for simplified syntax) |
| `--oauth-google` | flag | Enable Google OAuth2 login |
| `--ai-framework` | `pydantic_ai`, `pydantic_deep`, `langchain`, `langgraph`, `deepagents` | AI agent framework |
| `--llm-provider` | `openai`, `anthropic`, `google`, `openrouter` | LLM provider |
| `--llm-provider` | `openai`, `anthropic`, `google`, `openrouter`, `orcarouter` | LLM provider |
| `--task-queue` | `none`, `celery`, `taskiq`, `arq` | Background task queue (Redis-backed). **Prefect** is available via the interactive wizard. |
| `--frontend` | `none`, `nextjs` | Frontend framework |

Expand All @@ -31,8 +31,8 @@ fastapi-fullstack create my_app --minimal

| Framework | Providers | Description |
|-----------|-----------|-------------|
| `pydantic_ai` | OpenAI, Anthropic, Google, OpenRouter | Type-safe agents with WebSearch/WebFetch built-in |
| `pydantic_deep` | OpenAI, Anthropic, Google | Deep coding assistant (filesystem tools, Docker/Daytona sandbox) |
| `pydantic_ai` | OpenAI, Anthropic, Google, OpenRouter, OrcaRouter | Type-safe agents with WebSearch/WebFetch built-in |
| `pydantic_deep` | OpenAI, Anthropic, Google, OpenRouter, OrcaRouter | Deep coding assistant (filesystem tools, Docker/Daytona sandbox) |
| `langchain` | OpenAI, Anthropic, Google | Comprehensive chain-based agents |
| `langgraph` | OpenAI, Anthropic, Google | Graph-based ReAct agents |
| `deepagents` | OpenAI, Anthropic, Google | Agentic framework with subagent delegation |
Expand Down
2 changes: 1 addition & 1 deletion docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ See the [Quick Start guide](guides/quick-start.md) for details and the [Installa

| Framework | Streaming | Observability | Providers |
|-----------|:---------:|:-------------:|:---------:|
| **PydanticAI** | WebSocket | Logfire | OpenAI, Anthropic, OpenRouter |
| **PydanticAI** | WebSocket | Logfire | OpenAI, Anthropic, OpenRouter, OrcaRouter |
| **LangChain** | WebSocket | LangSmith | OpenAI, Anthropic |
| **LangGraph** | WebSocket | LangSmith | OpenAI, Anthropic |

Expand Down
2 changes: 1 addition & 1 deletion docs/rag.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ CROSS_ENCODER_MODEL=... # Model name (default: cross-encoder/ms-marco-MiniLM-
| Option | Values | Description |
|--------|--------|-------------|
| `enable_rag` | bool | Enable RAG functionality |
| `embedding_provider` | auto-derived | Embedding model provider (auto-derived from LLM provider: OpenAI→openai, Anthropic→voyage, OpenRouter→sentence_transformers) |
| `embedding_provider` | auto-derived | Embedding model provider (auto-derived from LLM provider: OpenAI→openai, Anthropic→voyage, Google→gemini, OpenRouter→openai, OrcaRouter→sentence_transformers) |
| `pdf_parser` | `pymupdf`, `llamaparse` | PDF parsing method (set via `--pdf-parser` CLI flag) |
| `enable_reranker` | bool | Enable reranking (set via `--reranker` CLI flag: none/cohere/cross_encoder) |

Expand Down
5 changes: 3 additions & 2 deletions fastapi_gen/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -395,11 +395,11 @@ def new(output: Path | None, no_input: bool, name: str | None, minimal: bool) ->
)
@click.option(
"--llm-provider",
type=click.Choice(["openai", "anthropic", "google", "openrouter", "all"]),
type=click.Choice(["openai", "anthropic", "google", "openrouter", "orcarouter", "all"]),
default="openai",
help=(
"LLM provider (default: openai). 'all' installs every SDK and lets users "
"pick the model at runtime. openrouter requires pydantic_ai."
"pick the model at runtime. openrouter/orcarouter requires pydantic_ai."
),
)
@click.option("--redis", is_flag=True, help="Enable Redis")
Expand Down Expand Up @@ -1362,6 +1362,7 @@ def templates() -> None:
console.print(" --llm-provider anthropic Anthropic (claude-opus-4-7)")
console.print(" --llm-provider google Google Gemini (gemini-2.5-flash)")
console.print(" --llm-provider openrouter OpenRouter (pydantic_ai only)")
console.print(" --llm-provider orcarouter OrcaRouter (pydantic_ai only)")
console.print(
" --websockets Enable WebSocket support (real-time chat streaming)"
)
Expand Down
13 changes: 10 additions & 3 deletions fastapi_gen/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ class LLMProviderType(StrEnum):
ANTHROPIC = "anthropic"
GOOGLE = "google"
OPENROUTER = "openrouter"
ORCAROUTER = "orcarouter"
ALL = "all"


Expand Down Expand Up @@ -450,15 +451,15 @@ def validate_option_combinations(self) -> "ProjectConfig":
raise ValueError("Caching requires Redis to be enabled")
if (
self.ai_framework != AIFrameworkType.NONE
and self.llm_provider == LLMProviderType.OPENROUTER
and self.llm_provider in (LLMProviderType.OPENROUTER, LLMProviderType.ORCAROUTER)
and self.ai_framework
not in (
AIFrameworkType.PYDANTIC_AI,
AIFrameworkType.PYDANTIC_DEEP,
)
):
raise ValueError(
f"OpenRouter is only supported with PydanticAI or PydanticDeep, "
f"OpenRouter/OrcaRouter is only supported with PydanticAI or PydanticDeep, "
f"not {self.ai_framework.value}"
)
if (
Expand Down Expand Up @@ -809,6 +810,8 @@ def to_cookiecutter_context(self) -> dict[str, Any]:
"use_google": self.llm_provider in (LLMProviderType.GOOGLE, LLMProviderType.ALL),
"use_openrouter": self.llm_provider
in (LLMProviderType.OPENROUTER, LLMProviderType.ALL),
"use_orcarouter": self.llm_provider
in (LLMProviderType.ORCAROUTER, LLMProviderType.ALL),
"use_all_providers": self.llm_provider == LLMProviderType.ALL,
# Legacy fixed values (always enabled, not user-configurable)
# AI
Expand Down Expand Up @@ -900,19 +903,23 @@ def to_cookiecutter_context(self) -> dict[str, Any]:
if self.llm_provider == LLMProviderType.ANTHROPIC
else EmbeddingProviderType.GEMINI.value
if self.llm_provider == LLMProviderType.GOOGLE
else EmbeddingProviderType.SENTENCE_TRANSFORMERS.value
if self.llm_provider == LLMProviderType.ORCAROUTER
else EmbeddingProviderType.OPENAI.value
),
"use_openai_embeddings": self.rag_features.enable_rag
and self.llm_provider
not in (
LLMProviderType.ANTHROPIC,
LLMProviderType.GOOGLE,
LLMProviderType.ORCAROUTER,
),
"use_voyage_embeddings": self.rag_features.enable_rag
and self.llm_provider == LLMProviderType.ANTHROPIC,
"use_gemini_embeddings": self.rag_features.enable_rag
and self.llm_provider == LLMProviderType.GOOGLE,
"use_sentence_transformers": False,
"use_sentence_transformers": self.rag_features.enable_rag
and self.llm_provider == LLMProviderType.ORCAROUTER,
"enable_reranker": self.rag_features.enable_rag
and self.rag_features.reranker_type != RerankerType.NONE,
"use_cohere_reranker": self.rag_features.enable_rag
Expand Down
5 changes: 4 additions & 1 deletion fastapi_gen/prompts.py
Original file line number Diff line number Diff line change
Expand Up @@ -786,11 +786,14 @@ def prompt_llm_provider(ai_framework: AIFrameworkType) -> LLMProviderType:
questionary.Choice("Google Gemini (gemini-2.5-flash)", value=LLMProviderType.GOOGLE),
]

# OpenRouter available for PydanticAI and PydanticDeep (both use pydantic-ai)
# OpenRouter and OrcaRouter available for PydanticAI and PydanticDeep (both use pydantic-ai)
if ai_framework in (AIFrameworkType.PYDANTIC_AI, AIFrameworkType.PYDANTIC_DEEP):
choices.append(
questionary.Choice("OpenRouter (multi-provider)", value=LLMProviderType.OPENROUTER)
)
choices.append(
questionary.Choice("OrcaRouter (model routing)", value=LLMProviderType.ORCAROUTER)
)

return cast(
LLMProviderType,
Expand Down
9 changes: 5 additions & 4 deletions template/VARIABLES.md
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ These variables are set automatically by the generator.
| `use_qdrant` | bool | `false` | Qdrant vector database is selected | Computed from `vector_store` |
| `use_chromadb` | bool | `false` | ChromaDB vector database is selected (embedded mode) | Computed from `vector_store` |
| `use_pgvector` | bool | `false` | pgvector (PostgreSQL extension) is selected | Computed from `vector_store`, requires PostgreSQL |
| `embedding_provider` | enum | auto-derived | Embedding model provider. Auto-derived from LLM provider: OpenAI→openai, Anthropic→voyage, OpenRouter→sentence_transformers | Auto-derived from `llm_provider` |
| `embedding_provider` | enum | auto-derived | Embedding model provider. Auto-derived from LLM provider: OpenAI→openai, Anthropic→voyage, Google→gemini, OpenRouter→openai, OrcaRouter→sentence_transformers | Auto-derived from `llm_provider` |
| `use_openai_embeddings` | bool | `false` | OpenAI embeddings are selected | Computed from `llm_provider` |
| `use_voyage_embeddings` | bool | `false` | Voyage AI embeddings are selected | Computed from `llm_provider` |
| `use_gemini_embeddings` | bool | `false` | Google Gemini multimodal embeddings are selected | Computed from `llm_provider` |
Expand All @@ -238,7 +238,7 @@ These variables are set automatically by the generator.
**Notes:**

- RAG requires a vector database (Milvus, Qdrant, ChromaDB, or pgvector)
- Embedding provider is auto-derived from LLM provider (OpenAI→openai, Anthropic→voyage, Google→gemini, OpenRouter→sentence_transformers)
- Embedding provider is auto-derived from LLM provider (OpenAI→openai, Anthropic→voyage, Google→gemini, OpenRouter→openai, OrcaRouter→sentence_transformers)
- Reranker is enabled via `--reranker` CLI flag (cohere, cross_encoder)
- Cohere and Cross-Encoder rerankers improve search result relevance
- LlamaParse requires an API key; PyMuPDF is free and local (with tables, OCR fallback)
Expand Down Expand Up @@ -275,11 +275,12 @@ These variables are set automatically by the generator.
| `use_deepagents` | bool | `false` | DeepAgents (agentic coding, LangChain) is selected | Computed from `ai_framework` |
| `use_pydantic_deep` | bool | `false` | PydanticDeep (deep agentic coding, Docker sandbox) is selected | Computed from `ai_framework` |
| `sandbox_backend` | enum | `"state"` | Agent sandbox environment for DeepAgents/PydanticDeep. Values: `state`, `daytona` | Only used when `use_deepagents` or `use_pydantic_deep` is true |
| `llm_provider` | enum | `"openai"` | LLM provider. Values: `openai`, `anthropic`, `google`, `openrouter` | - |
| `llm_provider` | enum | `"openai"` | LLM provider. Values: `openai`, `anthropic`, `google`, `openrouter`, `orcarouter` | - |
| `use_openai` | bool | `true` | OpenAI is selected | Computed from `llm_provider` |
| `use_anthropic` | bool | `false` | Anthropic is selected | Computed from `llm_provider` |
| `use_google` | bool | `false` | Google Gemini is selected | Computed from `llm_provider` |
| `use_openrouter` | bool | `false` | OpenRouter is selected | Computed from `llm_provider` |
| `use_orcarouter` | bool | `false` | OrcaRouter is selected | Computed from `llm_provider` |
| `enable_langsmith` | bool | `false` | Enable LangSmith observability (tracing, prompt management) | Requires LangChain, LangGraph, or DeepAgents |
| `enable_web_search` | bool | `false` | Web search. PydanticAI/PydanticDeep use the model-native WebSearch capability; LangChain/LangGraph/DeepAgents use a Tavily-backed tool (needs `TAVILY_API_KEY`) | Requires an AI framework |
| `enable_web_fetch` | bool | `false` | Web fetch. PydanticAI/PydanticDeep use the model-native WebFetch capability; LangChain/LangGraph/DeepAgents use the portable `fetch_url` tool | Requires an AI framework |
Expand All @@ -298,7 +299,7 @@ These variables are set automatically by the generator.
- PydanticAI uses `iter()` for full event streaming over WebSocket
- LangGraph implements a ReAct (Reasoning + Acting) agent pattern with graph-based architecture
- DeepAgents provides an agentic coding assistant with built-in filesystem tools (ls, read_file, write_file, edit_file, glob, grep) and task management
- OpenRouter with LangChain, LangGraph, or DeepAgents is not supported
- OpenRouter and OrcaRouter with LangChain, LangGraph, or DeepAgents is not supported

---

Expand Down
1 change: 1 addition & 0 deletions template/cookiecutter.json
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@
"use_anthropic": false,
"use_google": false,
"use_openrouter": false,
"use_orcarouter": false,
"use_all_providers": false,
"use_ai": true,
"enable_conversation_persistence": true,
Expand Down
3 changes: 3 additions & 0 deletions template/{{cookiecutter.project_slug}}/ENV_VARS.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@ group is for and which are required vs optional.
{%- if cookiecutter.use_openrouter %}
| `OPENROUTER_API_KEY` | **required** | — | From openrouter.ai |
{%- endif %}
{%- if cookiecutter.use_orcarouter %}
| `ORCAROUTER_API_KEY` | **required** | — | From orcarouter.ai |
{%- endif %}
{%- if cookiecutter.enable_logfire %}
| `LOGFIRE_TOKEN` | optional | — | When set, ships traces to Logfire (logfire.pydantic.dev) |
{%- endif %}
Expand Down
8 changes: 8 additions & 0 deletions template/{{cookiecutter.project_slug}}/MANUAL_STEPS.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,14 @@ These are used to sign JWTs and authenticate service-to-service calls. Rotate at
- [ ] Set `OPENROUTER_API_KEY` in `.env`.
{%- endif %}

{%- if cookiecutter.use_orcarouter %}

## OrcaRouter

- [ ] Create API key at https://www.orcarouter.ai.
- [ ] Set `ORCAROUTER_API_KEY` in `.env`.
{%- endif %}

{%- if cookiecutter.enable_oauth_google %}

## Google OAuth
Expand Down
7 changes: 6 additions & 1 deletion template/{{cookiecutter.project_slug}}/backend/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -208,9 +208,12 @@ GOOGLE_API_KEY=
{%- if cookiecutter.use_openrouter %}
OPENROUTER_API_KEY=
{%- endif %}
{%- if cookiecutter.use_orcarouter %}
ORCAROUTER_API_KEY=
{%- endif %}
{%- if cookiecutter.use_all_providers %}
# Multi-provider deployment — model name must include the provider prefix:
# openai/<model>, anthropic/<model>, google/<model>, openrouter/<provider>/<model>
# openai/<model>, anthropic/<model>, google/<model>, openrouter/<provider>/<model>, orcarouter/<provider>/<model>
AI_MODEL=openai/gpt-5.5
{%- elif cookiecutter.use_openai %}
AI_MODEL=gpt-5.5
Expand All @@ -220,6 +223,8 @@ AI_MODEL=claude-opus-4-7
AI_MODEL=gemini-2.5-flash
{%- elif cookiecutter.use_openrouter %}
AI_MODEL=anthropic/claude-opus-4-7
{%- elif cookiecutter.use_orcarouter %}
AI_MODEL=anthropic/claude-sonnet-4.6
{%- endif %}
AI_TEMPERATURE=0.7
{%- if cookiecutter.use_pydantic_ai %}
Expand Down
Loading