Metadata-Version: 2.4
Name: vanna
Version: 2.0.0
Summary: Generate SQL queries from natural language
Author-email: Zain Hoda <zain@vanna.ai>
Requires-Python: >=3.9
Description-Content-Type: text/markdown
Classifier: Programming Language :: Python :: 3
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
License-File: LICENSE
Requires-Dist: pydantic>=2.0.0
Requires-Dist: click>=8.0.0
Requires-Dist: pandas
Requires-Dist: httpx>=0.28.0
Requires-Dist: PyYAML
Requires-Dist: plotly
Requires-Dist: tabulate
Requires-Dist: sqlparse
Requires-Dist: sqlalchemy
Requires-Dist: requests
Requires-Dist: psycopg2-binary ; extra == "all"
Requires-Dist: db-dtypes ; extra == "all"
Requires-Dist: PyMySQL ; extra == "all"
Requires-Dist: google-cloud-bigquery ; extra == "all"
Requires-Dist: snowflake-connector-python ; extra == "all"
Requires-Dist: duckdb ; extra == "all"
Requires-Dist: openai ; extra == "all"
Requires-Dist: qianfan ; extra == "all"
Requires-Dist: mistralai>=1.0.0 ; extra == "all"
Requires-Dist: chromadb>=1.1.0 ; extra == "all"
Requires-Dist: anthropic ; extra == "all"
Requires-Dist: zhipuai ; extra == "all"
Requires-Dist: marqo ; extra == "all"
Requires-Dist: google-generativeai ; extra == "all"
Requires-Dist: google-cloud-aiplatform ; extra == "all"
Requires-Dist: qdrant-client>=1.0.0 ; extra == "all"
Requires-Dist: fastembed ; extra == "all"
Requires-Dist: ollama ; extra == "all"
Requires-Dist: httpx ; extra == "all"
Requires-Dist: opensearch-py ; extra == "all"
Requires-Dist: opensearch-dsl ; extra == "all"
Requires-Dist: transformers ; extra == "all"
Requires-Dist: pinecone ; extra == "all"
Requires-Dist: pymilvus[model] ; extra == "all"
Requires-Dist: weaviate-client ; extra == "all"
Requires-Dist: azure-search-documents ; extra == "all"
Requires-Dist: azure-identity ; extra == "all"
Requires-Dist: azure-common ; extra == "all"
Requires-Dist: faiss-cpu ; extra == "all"
Requires-Dist: boto ; extra == "all"
Requires-Dist: boto3 ; extra == "all"
Requires-Dist: botocore ; extra == "all"
Requires-Dist: langchain_core ; extra == "all"
Requires-Dist: langchain_postgres ; extra == "all"
Requires-Dist: langchain-community ; extra == "all"
Requires-Dist: langchain-huggingface ; extra == "all"
Requires-Dist: xinference-client ; extra == "all"
Requires-Dist: anthropic ; extra == "anthropic"
Requires-Dist: openai ; extra == "azureopenai"
Requires-Dist: azure-identity ; extra == "azureopenai"
Requires-Dist: azure-search-documents ; extra == "azuresearch"
Requires-Dist: azure-identity ; extra == "azuresearch"
Requires-Dist: azure-common ; extra == "azuresearch"
Requires-Dist: fastembed ; extra == "azuresearch"
Requires-Dist: boto3 ; extra == "bedrock"
Requires-Dist: botocore ; extra == "bedrock"
Requires-Dist: google-cloud-bigquery ; extra == "bigquery"
Requires-Dist: chromadb>=1.1.0 ; extra == "chromadb"
Requires-Dist: clickhouse_connect ; extra == "clickhouse"
Requires-Dist: pytest>=7.0.0 ; extra == "dev"
Requires-Dist: pytest-asyncio>=0.21.0 ; extra == "dev"
Requires-Dist: pytest-mock>=3.10.0 ; extra == "dev"
Requires-Dist: pytest-cov>=4.0.0 ; extra == "dev"
Requires-Dist: tox>=4.0.0 ; extra == "dev"
Requires-Dist: mypy ; extra == "dev"
Requires-Dist: ruff ; extra == "dev"
Requires-Dist: pandas-stubs ; extra == "dev"
Requires-Dist: plotly-stubs ; extra == "dev"
Requires-Dist: types-PyYAML ; extra == "dev"
Requires-Dist: types-requests ; extra == "dev"
Requires-Dist: types-tabulate ; extra == "dev"
Requires-Dist: duckdb ; extra == "duckdb"
Requires-Dist: faiss-cpu ; extra == "faiss-cpu"
Requires-Dist: faiss-gpu ; extra == "faiss-gpu"
Requires-Dist: fastapi>=0.68.0 ; extra == "fastapi"
Requires-Dist: uvicorn>=0.15.0 ; extra == "fastapi"
Requires-Dist: flask>=2.0.0 ; extra == "flask"
Requires-Dist: flask-cors>=4.0.0 ; extra == "flask"
Requires-Dist: google-genai ; extra == "gemini"
Requires-Dist: google-generativeai ; extra == "google"
Requires-Dist: google-cloud-aiplatform ; extra == "google"
Requires-Dist: transformers ; extra == "hf"
Requires-Dist: pyhive ; extra == "hive"
Requires-Dist: thrift ; extra == "hive"
Requires-Dist: marqo ; extra == "marqo"
Requires-Dist: pymilvus[model] ; extra == "milvus"
Requires-Dist: mistralai>=1.0.0 ; extra == "mistralai"
Requires-Dist: pyodbc ; extra == "mssql"
Requires-Dist: PyMySQL ; extra == "mysql"
Requires-Dist: ollama ; extra == "ollama"
Requires-Dist: httpx ; extra == "ollama"
Requires-Dist: openai ; extra == "openai"
Requires-Dist: opensearch-py ; extra == "opensearch"
Requires-Dist: opensearch-dsl ; extra == "opensearch"
Requires-Dist: langchain-community ; extra == "opensearch"
Requires-Dist: langchain-huggingface ; extra == "opensearch"
Requires-Dist: oracledb ; extra == "oracle"
Requires-Dist: chromadb<1.0.0 ; extra == "oracle"
Requires-Dist: langchain-postgres>=0.0.12 ; extra == "pgvector"
Requires-Dist: pinecone ; extra == "pinecone"
Requires-Dist: fastembed ; extra == "pinecone"
Requires-Dist: psycopg2-binary ; extra == "postgres"
Requires-Dist: db-dtypes ; extra == "postgres"
Requires-Dist: pyhive ; extra == "presto"
Requires-Dist: thrift ; extra == "presto"
Requires-Dist: qdrant-client>=1.0.0 ; extra == "qdrant"
Requires-Dist: fastembed ; extra == "qdrant"
Requires-Dist: qianfan ; extra == "qianfan"
Requires-Dist: vanna[flask, fastapi] ; extra == "servers"
Requires-Dist: snowflake-connector-python ; extra == "snowflake"
Requires-Dist: pytest>=7.0.0 ; extra == "test"
Requires-Dist: pytest-asyncio>=0.21.0 ; extra == "test"
Requires-Dist: pytest-mock>=3.10.0 ; extra == "test"
Requires-Dist: pytest-cov>=4.0.0 ; extra == "test"
Requires-Dist: tox>=4.0.0 ; extra == "test"
Requires-Dist: vllm ; extra == "vllm"
Requires-Dist: weaviate-client ; extra == "weaviate"
Requires-Dist: xinference-client ; extra == "xinference-client"
Requires-Dist: zhipuai ; extra == "zhipuai"
Project-URL: Bug Tracker, https://github.com/vanna-ai/vanna/issues
Project-URL: Homepage, https://github.com/vanna-ai/vanna
Provides-Extra: all
Provides-Extra: anthropic
Provides-Extra: azureopenai
Provides-Extra: azuresearch
Provides-Extra: bedrock
Provides-Extra: bigquery
Provides-Extra: chromadb
Provides-Extra: clickhouse
Provides-Extra: dev
Provides-Extra: duckdb
Provides-Extra: faiss-cpu
Provides-Extra: faiss-gpu
Provides-Extra: fastapi
Provides-Extra: flask
Provides-Extra: gemini
Provides-Extra: google
Provides-Extra: hf
Provides-Extra: hive
Provides-Extra: marqo
Provides-Extra: milvus
Provides-Extra: mistralai
Provides-Extra: mssql
Provides-Extra: mysql
Provides-Extra: ollama
Provides-Extra: openai
Provides-Extra: opensearch
Provides-Extra: oracle
Provides-Extra: pgvector
Provides-Extra: pinecone
Provides-Extra: postgres
Provides-Extra: presto
Provides-Extra: qdrant
Provides-Extra: qianfan
Provides-Extra: servers
Provides-Extra: snowflake
Provides-Extra: test
Provides-Extra: vllm
Provides-Extra: weaviate
Provides-Extra: xinference-client
Provides-Extra: zhipuai

# Vanna 2.0: Turn Questions into Data Insights

**Natural language → SQL → Answers.** Now with enterprise security and user-aware permissions.

[![Python](https://img.shields.io/badge/python-3.8+-blue.svg)](https://python.org)
[![License](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE)
[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)

https://github.com/user-attachments/assets/476cd421-d0b0-46af-8b29-0f40c73d6d83


![Vanna2 Demo](img/architecture.png)

---

## What's New in 2.0

🔐 **User-Aware at Every Layer** — Queries automatically filtered per user permissions

🎨 **Modern Web Interface** — Beautiful pre-built `<vanna-chat>` component

⚡ **Streaming Responses** — Real-time tables, charts, and progress updates

🔒 **Enterprise Security** — Row-level security, audit logs, rate limiting

🔄 **Production-Ready** — FastAPI integration, observability, lifecycle hooks

> **Upgrading from 0.x?** See the [Migration Guide](MIGRATION_GUIDE.md) | [What changed?](#migration-notes)

---

## Get Started

### Try it with Sample Data

[Quickstart](https://vanna.ai/docs/quick-start)

### Configure

[Configure](https://vanna.ai/docs/configure)

### Web Component

```html
<!-- Drop into any existing webpage -->
<script src="https://img.vanna.ai/vanna-components.js"></script>
<vanna-chat
  sse-endpoint="https://your-api.com/chat"
  theme="dark">
</vanna-chat>
```

Uses your existing cookies/JWTs. Works with React, Vue, or plain HTML.

---

## What You Get

Ask a question in natural language and get back:

**1. Streaming Progress Updates**

**2. SQL Code Block (By default only shown to "admin" users)**

**3. Interactive Data Table**

**4. Charts** (Plotly visualizations)

**5. Natural Language Summary**

All streamed in real-time to your web component.

---

## Why Vanna 2.0?

### ✅ Get Started Instantly
* Production chat interface
* Custom agent with your database
* Embed in any webpage

### ✅ Enterprise-Ready Security
**User-aware at every layer** — Identity flows through system prompts, tool execution, and SQL filtering
**Row-level security** — Queries automatically filtered per user permissions
**Audit logs** — Every query tracked per user for compliance
**Rate limiting** — Per-user quotas via lifecycle hooks

### ✅ Beautiful Web UI Included
**Pre-built `<vanna-chat>` component** — No need to build your own chat interface
**Streaming tables & charts** — Rich components, not just text
**Responsive & customizable** — Works on mobile, desktop, light/dark themes
**Framework-agnostic** — React, Vue, plain HTML

### ✅ Works With Your Stack
**Any LLM:** OpenAI, Anthropic, Ollama, Azure, Google Gemini, AWS Bedrock, Mistral, Others
**Any Database:** PostgreSQL, MySQL, Snowflake, BigQuery, Redshift, SQLite, Oracle, SQL Server, DuckDB, ClickHouse, Others
**Your Auth System:** Bring your own — cookies, JWTs, OAuth tokens
**Your Framework:** FastAPI, Flask

### ✅ Extensible But Opinionated
**Custom tools** — Extend the `Tool` base class
**Lifecycle hooks** — Quota checking, logging, content filtering
**LLM middlewares** — Caching, prompt engineering
**Observability** — Built-in tracing and metrics

---

## Architecture

![Vanna2 Diagram](img/vanna2.svg)

---

## How It Works

```mermaid
sequenceDiagram
    participant U as 👤 User
    participant W as 🌐 <vanna-chat>
    participant S as 🐍 Your Server
    participant A as 🤖 Agent
    participant T as 🧰 Tools

    U->>W: "Show Q4 sales"
    W->>S: POST /api/vanna/v2/chat_sse (with auth)
    S->>A: User(id=alice, groups=[read_sales])
    A->>T: Execute SQL tool (user-aware)
    T->>T: Apply row-level security
    T->>A: Filtered results
    A->>W: Stream: Table → Chart → Summary
    W->>U: Display beautiful UI
```

**Key Concepts:**

1. **User Resolver** — You define how to extract user identity from requests (cookies, JWTs, etc.)
2. **User-Aware Tools** — Tools automatically check permissions based on user's group memberships
3. **Streaming Components** — Backend streams structured UI components (tables, charts) to frontend
4. **Built-in Web UI** — Pre-built `<vanna-chat>` component renders everything beautifully

---

## Production Setup with Your Auth

Here's a complete example integrating Vanna with your existing FastAPI app and authentication:

```python
from fastapi import FastAPI
from vanna import Agent
from vanna.servers.fastapi.routes import register_chat_routes
from vanna.servers.base import ChatHandler
from vanna.core.user import UserResolver, User, RequestContext
from vanna.integrations.anthropic import AnthropicLlmService
from vanna.tools import RunSqlTool
from vanna.integrations.sqlite import SqliteRunner
from vanna.core.registry import ToolRegistry

# Your existing FastAPI app
app = FastAPI()

# 1. Define your user resolver (using YOUR auth system)
class MyUserResolver(UserResolver):
    async def resolve_user(self, request_context: RequestContext) -> User:
        # Extract from cookies, JWTs, or session
        token = request_context.get_header('Authorization')
        user_data = self.decode_jwt(token)  # Your existing logic

        return User(
            id=user_data['id'],
            email=user_data['email'],
            group_memberships=user_data['groups']  # Used for permissions
        )

# 2. Set up agent with tools
llm = AnthropicLlmService(model="claude-sonnet-4-5")
tools = ToolRegistry()
tools.register(RunSqlTool(sql_runner=SqliteRunner("./data.db")))

agent = Agent(
    llm_service=llm,
    tool_registry=tools,
    user_resolver=MyUserResolver()
)

# 3. Add Vanna routes to your app
chat_handler = ChatHandler(agent)
register_chat_routes(app, chat_handler)

# Now you have:
# - POST /api/vanna/v2/chat_sse (streaming endpoint)
# - GET / (optional web UI)
```

**Then in your frontend:**
```html
<vanna-chat sse-endpoint="/api/vanna/v2/chat_sse"></vanna-chat>
```

See [Full Documentation](https://vanna.ai/docs) for custom tools, lifecycle hooks, and advanced configuration

---

## Custom Tools

Extend Vanna with custom tools for your specific use case:

```python
from vanna.core.tool import Tool, ToolContext, ToolResult
from pydantic import BaseModel, Field
from typing import Type

class EmailArgs(BaseModel):
    recipient: str = Field(description="Email recipient")
    subject: str = Field(description="Email subject")

class EmailTool(Tool[EmailArgs]):
    @property
    def name(self) -> str:
        return "send_email"

    @property
    def access_groups(self) -> list[str]:
        return ["send_email"]  # Permission check

    def get_args_schema(self) -> Type[EmailArgs]:
        return EmailArgs

    async def execute(self, context: ToolContext, args: EmailArgs) -> ToolResult:
        user = context.user  # Automatically injected

        # Your business logic
        await self.email_service.send(
            from_email=user.email,
            to=args.recipient,
            subject=args.subject
        )

        return ToolResult(success=True, result_for_llm=f"Email sent to {args.recipient}")

# Register your tool
tools.register(EmailTool())
```

---

## Advanced Features

Vanna 2.0 includes powerful enterprise features for production use:

**Lifecycle Hooks** — Add quota checking, custom logging, content filtering at key points in the request lifecycle

**LLM Middlewares** — Implement caching, prompt engineering, or cost tracking around LLM calls

**Conversation Storage** — Persist and retrieve conversation history per user

**Observability** — Built-in tracing and metrics integration

**Context Enrichers** — Add RAG, memory, or documentation to enhance agent responses

**Agent Configuration** — Control streaming, temperature, max iterations, and more

---

## Use Cases

**Vanna is ideal for:**
- 📊 Data analytics applications with natural language interfaces
- 🔐 Multi-tenant SaaS needing user-aware permissions
- 🎨 Teams wanting a pre-built web component + backend
- 🏢 Enterprise environments with security/audit requirements
- 📈 Applications needing rich streaming responses (tables, charts, SQL)
- 🔄 Integrating with existing authentication systems

---

## Community & Support

- 📖 **[Full Documentation](https://vanna.ai/docs)** — Complete guides and API reference
- 💡 **[GitHub Discussions](https://github.com/vanna-ai/vanna/discussions)** — Feature requests and Q&A
- 🐛 **[GitHub Issues](https://github.com/vanna-ai/vanna/issues)** — Bug reports
- 📧 **Enterprise Support** — support@vanna.ai

---

## Migration Notes

**Upgrading from Vanna 0.x?**

Vanna 2.0 is a complete rewrite focused on user-aware agents and production deployments. Key changes:

- **New API**: Agent-based instead of `VannaBase` class methods
- **User-aware**: Every component now knows the user identity
- **Streaming**: Rich UI components instead of text/dataframes
- **Web-first**: Built-in `<vanna-chat>` component and server

**Migration path:**

1. **Quick wrap** — Use `LegacyVannaAdapter` to wrap your existing Vanna 0.x instance and get the new web UI immediately
2. **Gradual migration** — Incrementally move to the new Agent API and tools

See the complete [Migration Guide](MIGRATION_GUIDE.md) for step-by-step instructions.

---

## License

MIT License — See [LICENSE](LICENSE) for details.

---

**Built with ❤️ by the Vanna team** | [Website](https://vanna.ai) | [Docs](https://vanna.ai/docs) | [Discussions](https://github.com/vanna-ai/vanna/discussions)

