diff --git a/.github/resources/gifs/demo.gif b/.github/resources/gifs/demo.gif new file mode 100644 index 0000000..1bdbd35 Binary files /dev/null and b/.github/resources/gifs/demo.gif differ diff --git a/.github/images/logo-dark.svg b/.github/resources/images/logo-dark.svg similarity index 100% rename from .github/images/logo-dark.svg rename to .github/resources/images/logo-dark.svg diff --git a/.github/images/logo-light.svg b/.github/resources/images/logo-light.svg similarity index 100% rename from .github/images/logo-light.svg rename to .github/resources/images/logo-light.svg diff --git a/README.md b/README.md index 751f42e..8245986 100644 --- a/README.md +++ b/README.md @@ -1,22 +1,22 @@
- - - TinyGent Logo + + + TinyGent Logo
-

Tiny platform for amazing agents.

+

✨ Tiny platform for amazing agents ✨

- Homepage | Documentation + 🏠 Homepage | 📚 Documentation | 💡 Examples | 🚀 Quick Start

-Tinygent is a tiny agentic framework - lightweight, easy to use (hopefully), and efficient (also hopefully ;-0) library for building and deploying generative AI applications. It provides a simple interface for working with various models and tools, making it ideal for developers who want to quickly prototype and deploy AI solutions. +🤖 Tinygent is a tiny agentic framework - lightweight, easy to use (hopefully), and efficient (also hopefully ;-0) library for building and deploying generative AI applications. It provides a simple interface for working with various models and tools, making it ideal for developers who want to quickly prototype and deploy AI solutions. -## Create an agent +## 🎯 Create an agent ```python # uv sync --extra openai @@ -38,16 +38,16 @@ agent = build_agent( print(agent.run('What is the weather like in Prague?')) ``` -## Getting Started +## 🚀 Getting Started -### Prerequisites +### 📋 Prerequisites Before you begin using tinygent, ensure that you meet the following software prerequisites. - Install [Git](https://git-scm.com/) - Install [uv](https://docs.astral.sh/uv/getting-started/installation/) -### Install From Source +### 💻 Install From Source 1. Clone the tinygent repository to your local machine. ```bash @@ -80,59 +80,90 @@ Before you begin using tinygent, ensure that you meet the following software pre uv pip install -e . ``` -## Examples (Quick Start) +## 🎬 See It In Action -1. Ensure you have set the `OPENAI_API_KEY` environment variable to allow the example to use OpenAI's API. An API key can be obtained from [`openai.com`](https://openai.com/). +
+ TinyChat Demo +
+ +## 🏗️ Architecture + +```mermaid +%%{init: {'theme': 'base', 'themeVariables': {'primaryColor': '#e1f5ff', 'primaryTextColor': '#0d47a1', 'primaryBorderColor': '#42a5f5', 'lineColor': '#1976d2', 'secondaryColor': '#fff4e1', 'tertiaryColor': '#f0e1ff'}}}%% +flowchart LR + User[User Code]:::userNode + Factory[Factories]:::factoryNode + Runtime[Runtime Registry]:::runtimeNode + Components[Agents & Tools & Memory]:::componentNode + Packages[Provider Packages]:::packageNode + + User a@--> Factory + Factory b@--> Runtime + Runtime c@--> Components + Packages d@-.-> Runtime + + a@{animate: true} + b@{animate: true} + c@{animate: true} + d@{animate: true} + + linkStyle 0 stroke-width:2px + linkStyle 1 stroke-width:2px + linkStyle 2 stroke-width:2px + linkStyle 3 stroke-width:2px,stroke-dasharray: 5 5 + + classDef userNode fill:#e1f5ff,stroke:#1976d2,stroke-width:2px,color:#0d47a1 + classDef factoryNode fill:#fff4e1,stroke:#f57c00,stroke-width:2px,color:#e65100 + classDef runtimeNode fill:#f0e1ff,stroke:#7b1fa2,stroke-width:2px,color:#4a148c + classDef componentNode fill:#e1ffe1,stroke:#388e3c,stroke-width:2px,color:#1b5e20 + classDef packageNode fill:#ffe1e1,stroke:#d32f2f,stroke-width:2px,color:#b71c1c +``` + +Tinygent uses a registry-based plugin architecture: **Packages** register components into the **Runtime**. **Factories** query the Runtime to build **Components** for your code. + +## 💡 Examples (Quick Start) + +1. 🔑 Ensure you have set the `OPENAI_API_KEY` environment variable to allow the example to use OpenAI's API. An API key can be obtained from [`openai.com`](https://openai.com/). ```bash export OPENAI_API_KEY="your_openai_api_key" ``` -2. Run the examples using `uv`: +2. ▶️ Run the examples using `uv`: ```bash uv run examples/agents/multi-step/main.py ``` -3. Explore more examples below: - -### Basics - -1. [Tool Usage](examples/tool-usage) -2. [LLM Usage](examples/llm-usage) -3. [Function Calling](examples/function-calling) - -### Memory - -1. [Chat Buffer Memory](examples/memory/basic-chat-memory) -2. [Summary Buffer Memory](examples/memory/buffer-summary-memory) -3. [Window Buffer Memory](examples/memory/buffer-window-chat-memory) -4. [Combined Memory](examples/memory/combined-memory) - -### Tools - -1. [Basic Tools](examples/tool-usage/main.py) -2. [Reasoning Tools](examples/tool-usage/main.py) -3. [JIT Tools](examples/tool-usage/main.py) - -### Agents - -1. [Middlewares in Agents](examples/agents/middleware/) -2. [ReAct Agent](examples/agents/react/) -3. [Multi-Step Agent](examples/agents/multi-step/) -4. [Squad Agent](examples/agents/squad/) -5. [Modular Agentic Planner Agent](examples/agents/map/) - -### Packages - -1. [Brave Tools](packages/tiny_brave/) -2. [Tiny Chat](packages/tiny_chat) -3. [Tiny OpenAI](packages/tiny_openai) -4. [Tiny MistralAI](packages/tiny_mistralai) -5. [Tiny Gemini](packages/tiny_gemini) -6. [Tiny Anthropic](packages/tiny_anthropic) -7. [Tiny VoyageAI](packages/tiny_voyageai) -8. [Tiny Graph](packages/tiny_graph) - -## Linting & Formatting +3. 🔍 Explore more examples below: + +### 📚 Features & Examples + +| Name | Type | Description | +|------|------|-------------| +| [Tool Usage](examples/tool-usage) | Basics | Basic tool creation and usage | +| [LLM Usage](examples/llm-usage) | Basics | Direct LLM interaction patterns | +| [Function Calling](examples/function-calling) | Basics | Function calling with LLMs | +| [Chat Buffer Memory](examples/memory/basic-chat-memory) | Memory | Store complete conversation history | +| [Summary Buffer Memory](examples/memory/buffer-summary-memory) | Memory | Summarize older messages to save tokens | +| [Window Buffer Memory](examples/memory/buffer-window-chat-memory) | Memory | Keep only recent N messages | +| [Combined Memory](examples/memory/combined-memory) | Memory | Combine multiple memory strategies | +| [Basic Tools](examples/tool-usage/main.py) | Tools | Simple tool definitions with `@tool` | +| [Reasoning Tools](examples/tool-usage/main.py) | Tools | Tools that provide reasoning traces | +| [JIT Tools](examples/tool-usage/main.py) | Tools | Just-in-time compiled tools | +| [Middlewares in Agents](examples/agents/middleware/) | Agents | Add custom processing layers to agents | +| [ReAct Agent](examples/agents/react/) | Agents | Reasoning and acting pattern | +| [Multi-Step Agent](examples/agents/multi-step/) | Agents | Break down complex tasks into steps | +| [Squad Agent](examples/agents/squad/) | Agents | Coordinate multiple specialized agents | +| [Modular Agentic Planner](examples/agents/map/) | Agents | Advanced planning with modular architecture | +| [Tiny OpenAI](packages/tiny_openai) | Package | OpenAI LLMs and embeddings | +| [Tiny Anthropic](packages/tiny_anthropic) | Package | Anthropic Claude LLMs | +| [Tiny MistralAI](packages/tiny_mistralai) | Package | Mistral AI LLMs | +| [Tiny Gemini](packages/tiny_gemini) | Package | Google Gemini LLMs | +| [Tiny VoyageAI](packages/tiny_voyageai) | Package | VoyageAI embedding models | +| [Brave Tools](packages/tiny_brave/) | Package | Brave search integration | +| [Tiny Chat](packages/tiny_chat) | Package | FastAPI-based chat interface | +| [Tiny Graph](packages/tiny_graph) | Package | Neo4j knowledge graph integration | + +## ✅ Linting & Formatting To ensure code quality, formatting consistency, and type safety, run: diff --git a/docs/index.md b/docs/index.md index 6da40be..773267b 100644 --- a/docs/index.md +++ b/docs/index.md @@ -16,7 +16,7 @@ Built with modern Python best practices, Tinygent provides: ## Why Tinygent? -### **Easy to Learn, Hard to Master** +### **Start Simple, Scale Your Way** Tinygent follows the principle of progressive disclosure - start simple, grow complex only when needed. diff --git a/examples/chat-app/main.py b/examples/chat-app/main.py index 82e3b43..ab7d854 100644 --- a/examples/chat-app/main.py +++ b/examples/chat-app/main.py @@ -1,4 +1,3 @@ -from pathlib import Path from typing import Any import uuid @@ -6,37 +5,71 @@ from tiny_brave import NewsSearchApiResponse from tiny_brave import NewsSearchRequest +from tiny_brave import WebSearchApiResponse +from tiny_brave import WebSearchRequest from tiny_brave import brave_news_search +from tiny_brave import brave_web_search import tiny_chat as tc -from tinygent.agents import TinyReActAgent from tinygent.agents.middleware import TinyBaseMiddleware +from tinygent.agents.middleware import TinyToolCallLimiterMiddleware from tinygent.cli.utils import discover_and_register_components from tinygent.core.datamodels.tool import AbstractTool -from tinygent.core.factory import build_llm +from tinygent.core.factory import build_agent from tinygent.core.types import TinyModel from tinygent.logging import setup_logger from tinygent.memory import BufferChatMemory -from tinygent.prompts import ReActPromptTemplate from tinygent.tools import register_tool -from tinygent.utils import tiny_yaml_load logger = setup_logger('debug') discover_and_register_components() -class BraveNewsConfig(TinyModel): +class BraveConfig(TinyModel): query: str = Field(..., description='The search query string.') @register_tool -async def brave_news(data: BraveNewsConfig): - result = await brave_news_search(NewsSearchRequest(q=data.query)) +async def brave_news(data: BraveConfig): + """Search recent news articles from news publishers (headlines, journalism, press, media coverage).""" + raw = await brave_news_search(NewsSearchRequest(q=data.query)) - return result + return NewsSearchApiResponse.model_validate(raw) + + +@register_tool +async def brave_web(data: BraveConfig): + """Search general web pages (blogs, docs, forums, websites, informational pages).""" + raw = await brave_web_search(WebSearchRequest(q=data.query)) + + return WebSearchApiResponse.model_validate(raw) class ChatClientMiddleware(TinyBaseMiddleware): + @staticmethod + async def _send_sources(run_id: str, result: Any) -> bool: + if not isinstance(result, (NewsSearchApiResponse, WebSearchApiResponse)): + return False + + items = ( + result.results + if isinstance(result, NewsSearchApiResponse) + else result.web.results + if result.web + else [] + ) + + for item in items: + await tc.AgentSourceMessage( + parent_id=run_id, + name=item.title, + url=item.url, + favicon=item.meta_url.favicon if item.meta_url else None, + description=item.description, + ).send() + + return True + async def on_answer( self, *, run_id: str, answer: str, kwargs: dict[str, Any] ) -> None: @@ -70,31 +103,19 @@ async def after_tool_call( content=result, ).send() - try: - news_response = NewsSearchApiResponse.model_validate(result) - for article in news_response.results: - await tc.AgentSourceMessage( - parent_id=run_id, - name=article.title, - url=article.url, - favicon=article.meta_url.favicon if article.meta_url else None, - description=article.description, - ).send() - - except Exception: + if not await self._send_sources(run_id, result): logger.exception('Failed to parse tool call.') -agent = TinyReActAgent( - llm=build_llm('openai:gpt-4o'), - tools=[brave_news], +agent = build_agent( + 'react', + llm='openai:gpt-4o', + tools=[brave_news, brave_web], memory=BufferChatMemory(), - prompt_template=ReActPromptTemplate( - **tiny_yaml_load( - str(Path(__file__).parent.parent / 'agents' / 'react' / 'prompts.yaml') - ) - ), - middleware=[ChatClientMiddleware()], + middleware=[ + ChatClientMiddleware(), + TinyToolCallLimiterMiddleware(tool_name='brave_web', max_tool_calls=1), + ], ) diff --git a/examples/quick-start/README.md b/examples/quick-start/README.md new file mode 100644 index 0000000..4f47b56 --- /dev/null +++ b/examples/quick-start/README.md @@ -0,0 +1,88 @@ +# Quick Start + +A minimal example demonstrating how to create a ReAct agent with a custom tool using Tinygent. + +## What This Example Does + +This example creates a simple agent that can answer questions about the weather by using a custom `get_weather` tool. It demonstrates: + +- Defining a custom tool with the `@tool` decorator +- Building a ReAct agent using the factory pattern +- Running the agent with a simple query + +## Prerequisites + +- Python 3.12 +- OpenAI API key +- `uv` package manager ([installation guide](https://docs.astral.sh/uv/getting-started/installation/)) + +## Setup + +1. Set your OpenAI API key: + ```bash + export OPENAI_API_KEY="your_openai_api_key" + ``` + +2. Install dependencies: + ```bash + uv sync --extra openai + ``` + +## Run the Example + +```bash +uv run examples/quick-start/main.py +``` + +## Expected Output + +The agent will: +1. Receive the query "What is the weather like in Prague?" +2. Reason about which tool to use +3. Call the `get_weather` tool with location="Prague" +4. Return a natural language response based on the tool output + +Example output: +``` +The weather in Prague is sunny with a high of 75°F. +``` + +## Code Breakdown + +```python +@tool +def get_weather(location: str) -> str: + """Get the current weather in a given location.""" + return f'The weather in {location} is sunny with a high of 75°F.' +``` +The `@tool` decorator registers a Python function as a tool that the agent can use. The docstring is used to help the agent understand when to use this tool. + +```python +agent = build_agent( + 'react', + llm='openai:gpt-4o-mini', + tools=[get_weather], +) +``` +`build_agent()` creates a ReAct agent using: +- `'react'` - The agent type (ReAct pattern: Reasoning + Acting) +- `llm='openai:gpt-4o-mini'` - The LLM to use (format: `provider:model`) +- `tools=[get_weather]` - List of tools available to the agent + +```python +print(agent.run('What is the weather like in Prague?')) +``` +`agent.run()` executes the agent with the given query and returns the final response. + +## Next Steps + +Explore more advanced examples: + +- [Multi-Step Agent](../agents/multi-step/) - Agent that breaks down complex tasks +- [Tool Usage](../tool-usage/) - Advanced tool patterns (reasoning, JIT) +- [Memory Examples](../memory/) - Adding conversation memory to agents +- [Squad Agent](../agents/squad/) - Coordinating multiple agents + +## Documentation + +Visit the [Tinygent documentation](https://filchy.github.io/tinygent) for comprehensive guides and API references. diff --git a/examples/quick-start/main.py b/examples/quick-start/main.py new file mode 100644 index 0000000..5599d40 --- /dev/null +++ b/examples/quick-start/main.py @@ -0,0 +1,20 @@ +from tinygent.core.factory import build_agent +from tinygent.logging import setup_logger +from tinygent.tools import tool + +setup_logger('debug') + + +@tool +def get_weather(location: str) -> str: + """Get the current weather in a given location.""" + return f'The weather in {location} is sunny with a high of 75°F.' + + +agent = build_agent( + 'react', + llm='openai:gpt-4o-mini', + tools=[get_weather], +) + +print(agent.run('What is the weather like in Prague?')) diff --git a/tinygent/agents/base_agent.py b/tinygent/agents/base_agent.py index c18ec5f..4d8cb80 100644 --- a/tinygent/agents/base_agent.py +++ b/tinygent/agents/base_agent.py @@ -103,9 +103,9 @@ def __init__( middleware: Sequence[AbstractMiddleware] = [], ) -> None: self.llm = llm - self.memory = memory self.middleware = middleware + self._memory = memory self._tools = tools self._final_answer: str | None = None @@ -115,6 +115,10 @@ def reset(self) -> None: self.memory.clear() self._final_answer = None + @property + def memory(self) -> AbstractMemory: + return self._memory + @property def tools(self) -> Sequence[AbstractTool]: return self._tools diff --git a/tinygent/core/datamodels/agent.py b/tinygent/core/datamodels/agent.py index 580406e..3b85d5d 100644 --- a/tinygent/core/datamodels/agent.py +++ b/tinygent/core/datamodels/agent.py @@ -8,6 +8,7 @@ from typing import TypeVar from tinygent.agents.middleware.agent import TinyMiddlewareAgent +from tinygent.core.datamodels.memory import AbstractMemory from tinygent.core.datamodels.messages import AllTinyMessages from tinygent.core.types.builder import TinyModelBuildable @@ -27,6 +28,12 @@ def build(self) -> AgentType: class AbstractAgent(TinyMiddlewareAgent, ABC): """Abstract base class for agents.""" + @property + @abstractmethod + def memory(self) -> AbstractMemory: + """Get agents memory instance.""" + raise NotImplementedError('Subclasses must implement this method.') + @abstractmethod def reset(self) -> None: """Reset the agent's internal state.""" diff --git a/uv.lock b/uv.lock index 1c7594d..2190ae6 100644 --- a/uv.lock +++ b/uv.lock @@ -3,15 +3,15 @@ requires-python = "==3.12.*" [manifest] members = [ - "tiny-anthropic", - "tiny-brave", - "tiny-chat", - "tiny-gemini", - "tiny-graph", - "tiny-mistralai", - "tiny-openai", - "tiny-voyageai", "tinygent", + "tinygent-anthropic", + "tinygent-brave", + "tinygent-chat", + "tinygent-gemini", + "tinygent-graph", + "tinygent-mistralai", + "tinygent-openai", + "tinygent-voyageai", ] [[package]] @@ -1639,8 +1639,83 @@ wheels = [ ] [[package]] -name = "tiny-anthropic" -version = "0.1.0" +name = "tinygent" +version = "0.1.1" +source = { editable = "." } +dependencies = [ + { name = "async-lru" }, + { name = "jinja2" }, + { name = "langchain-core" }, + { name = "opentelemetry-exporter-otlp" }, + { name = "opentelemetry-sdk" }, + { name = "pydantic" }, + { name = "pyyaml" }, + { name = "typer" }, +] + +[package.optional-dependencies] +anthropic = [ + { name = "tinygent-anthropic" }, +] +brave = [ + { name = "tinygent-brave" }, +] +chat = [ + { name = "tinygent-chat" }, +] +dev = [ + { name = "mypy" }, + { name = "ruff" }, +] +docs = [ + { name = "mkdocs" }, + { name = "mkdocs-material" }, + { name = "mkdocstrings", extra = ["python"] }, +] +gemini = [ + { name = "tinygent-gemini" }, +] +graph = [ + { name = "tinygent-graph" }, +] +mistralai = [ + { name = "tinygent-mistralai" }, +] +openai = [ + { name = "tinygent-openai" }, +] +voyageai = [ + { name = "tinygent-voyageai" }, +] + +[package.metadata] +requires-dist = [ + { name = "async-lru", specifier = ">=2.0.5" }, + { name = "jinja2", specifier = ">=3.1.6" }, + { name = "langchain-core", specifier = ">=0.3.74" }, + { name = "mkdocs", marker = "extra == 'docs'", specifier = ">=1.6.1" }, + { name = "mkdocs-material", marker = "extra == 'docs'", specifier = ">=9.7.1" }, + { name = "mkdocstrings", extras = ["python"], marker = "extra == 'docs'", specifier = ">=1.0.2" }, + { name = "mypy", marker = "extra == 'dev'", specifier = ">=1.17.1" }, + { name = "opentelemetry-exporter-otlp", specifier = ">=1.38.0" }, + { name = "opentelemetry-sdk", specifier = ">=1.38.0" }, + { name = "pydantic", specifier = ">=2.11.7" }, + { name = "pyyaml", specifier = ">=6.0.2" }, + { name = "ruff", marker = "extra == 'dev'", specifier = ">=0.12.11" }, + { name = "tinygent-anthropic", marker = "extra == 'anthropic'", editable = "packages/tiny_anthropic" }, + { name = "tinygent-brave", marker = "extra == 'brave'", editable = "packages/tiny_brave" }, + { name = "tinygent-chat", marker = "extra == 'chat'", editable = "packages/tiny_chat" }, + { name = "tinygent-gemini", marker = "extra == 'gemini'", editable = "packages/tiny_gemini" }, + { name = "tinygent-graph", marker = "extra == 'graph'", editable = "packages/tiny_graph" }, + { name = "tinygent-mistralai", marker = "extra == 'mistralai'", editable = "packages/tiny_mistralai" }, + { name = "tinygent-openai", marker = "extra == 'openai'", editable = "packages/tiny_openai" }, + { name = "tinygent-voyageai", marker = "extra == 'voyageai'", editable = "packages/tiny_voyageai" }, + { name = "typer", specifier = ">=0.19.2" }, +] + +[[package]] +name = "tinygent-anthropic" +version = "0.1.1" source = { editable = "packages/tiny_anthropic" } dependencies = [ { name = "anthropic" }, @@ -1654,8 +1729,8 @@ requires-dist = [ ] [[package]] -name = "tiny-brave" -version = "0.1.0" +name = "tinygent-brave" +version = "0.1.1" source = { editable = "packages/tiny_brave" } dependencies = [ { name = "httpx" }, @@ -1671,8 +1746,8 @@ requires-dist = [ ] [[package]] -name = "tiny-chat" -version = "0.1.0" +name = "tinygent-chat" +version = "0.1.1" source = { editable = "packages/tiny_chat" } dependencies = [ { name = "fastapi" }, @@ -1692,8 +1767,8 @@ requires-dist = [ ] [[package]] -name = "tiny-gemini" -version = "0.1.0" +name = "tinygent-gemini" +version = "0.1.1" source = { editable = "packages/tiny_gemini" } dependencies = [ { name = "google-genai" }, @@ -1707,8 +1782,8 @@ requires-dist = [ ] [[package]] -name = "tiny-graph" -version = "0.1.0" +name = "tinygent-graph" +version = "0.1.1" source = { editable = "packages/tiny_graph" } dependencies = [ { name = "neo4j" }, @@ -1722,8 +1797,8 @@ requires-dist = [ ] [[package]] -name = "tiny-mistralai" -version = "0.1.0" +name = "tinygent-mistralai" +version = "0.1.1" source = { editable = "packages/tiny_mistralai" } dependencies = [ { name = "mistral-common" }, @@ -1741,8 +1816,8 @@ requires-dist = [ ] [[package]] -name = "tiny-openai" -version = "0.1.0" +name = "tinygent-openai" +version = "0.1.1" source = { editable = "packages/tiny_openai" } dependencies = [ { name = "langchain-core" }, @@ -1760,8 +1835,8 @@ requires-dist = [ ] [[package]] -name = "tiny-voyageai" -version = "0.1.0" +name = "tinygent-voyageai" +version = "0.1.1" source = { editable = "packages/tiny_voyageai" } dependencies = [ { name = "tinygent" }, @@ -1774,81 +1849,6 @@ requires-dist = [ { name = "voyageai", specifier = ">=0.3.7" }, ] -[[package]] -name = "tinygent" -version = "0.1.0" -source = { editable = "." } -dependencies = [ - { name = "async-lru" }, - { name = "jinja2" }, - { name = "langchain-core" }, - { name = "opentelemetry-exporter-otlp" }, - { name = "opentelemetry-sdk" }, - { name = "pydantic" }, - { name = "pyyaml" }, - { name = "typer" }, -] - -[package.optional-dependencies] -anthropic = [ - { name = "tiny-anthropic" }, -] -brave = [ - { name = "tiny-brave" }, -] -chat = [ - { name = "tiny-chat" }, -] -dev = [ - { name = "mypy" }, - { name = "ruff" }, -] -docs = [ - { name = "mkdocs" }, - { name = "mkdocs-material" }, - { name = "mkdocstrings", extra = ["python"] }, -] -gemini = [ - { name = "tiny-gemini" }, -] -graph = [ - { name = "tiny-graph" }, -] -mistralai = [ - { name = "tiny-mistralai" }, -] -openai = [ - { name = "tiny-openai" }, -] -voyageai = [ - { name = "tiny-voyageai" }, -] - -[package.metadata] -requires-dist = [ - { name = "async-lru", specifier = ">=2.0.5" }, - { name = "jinja2", specifier = ">=3.1.6" }, - { name = "langchain-core", specifier = ">=0.3.74" }, - { name = "mkdocs", marker = "extra == 'docs'", specifier = ">=1.6.1" }, - { name = "mkdocs-material", marker = "extra == 'docs'", specifier = ">=9.7.1" }, - { name = "mkdocstrings", extras = ["python"], marker = "extra == 'docs'", specifier = ">=1.0.2" }, - { name = "mypy", marker = "extra == 'dev'", specifier = ">=1.17.1" }, - { name = "opentelemetry-exporter-otlp", specifier = ">=1.38.0" }, - { name = "opentelemetry-sdk", specifier = ">=1.38.0" }, - { name = "pydantic", specifier = ">=2.11.7" }, - { name = "pyyaml", specifier = ">=6.0.2" }, - { name = "ruff", marker = "extra == 'dev'", specifier = ">=0.12.11" }, - { name = "tiny-anthropic", marker = "extra == 'anthropic'", editable = "packages/tiny_anthropic" }, - { name = "tiny-brave", marker = "extra == 'brave'", editable = "packages/tiny_brave" }, - { name = "tiny-chat", marker = "extra == 'chat'", editable = "packages/tiny_chat" }, - { name = "tiny-gemini", marker = "extra == 'gemini'", editable = "packages/tiny_gemini" }, - { name = "tiny-graph", marker = "extra == 'graph'", editable = "packages/tiny_graph" }, - { name = "tiny-mistralai", marker = "extra == 'mistralai'", editable = "packages/tiny_mistralai" }, - { name = "tiny-openai", marker = "extra == 'openai'", editable = "packages/tiny_openai" }, - { name = "tiny-voyageai", marker = "extra == 'voyageai'", editable = "packages/tiny_voyageai" }, - { name = "typer", specifier = ">=0.19.2" }, -] - [[package]] name = "tokenizers" version = "0.22.2"