agno 2.2.13__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- agno/__init__.py +8 -0
- agno/agent/__init__.py +51 -0
- agno/agent/agent.py +10405 -0
- agno/api/__init__.py +0 -0
- agno/api/agent.py +28 -0
- agno/api/api.py +40 -0
- agno/api/evals.py +22 -0
- agno/api/os.py +17 -0
- agno/api/routes.py +13 -0
- agno/api/schemas/__init__.py +9 -0
- agno/api/schemas/agent.py +16 -0
- agno/api/schemas/evals.py +16 -0
- agno/api/schemas/os.py +14 -0
- agno/api/schemas/response.py +6 -0
- agno/api/schemas/team.py +16 -0
- agno/api/schemas/utils.py +21 -0
- agno/api/schemas/workflows.py +16 -0
- agno/api/settings.py +53 -0
- agno/api/team.py +30 -0
- agno/api/workflow.py +28 -0
- agno/cloud/aws/base.py +214 -0
- agno/cloud/aws/s3/__init__.py +2 -0
- agno/cloud/aws/s3/api_client.py +43 -0
- agno/cloud/aws/s3/bucket.py +195 -0
- agno/cloud/aws/s3/object.py +57 -0
- agno/culture/__init__.py +3 -0
- agno/culture/manager.py +956 -0
- agno/db/__init__.py +24 -0
- agno/db/async_postgres/__init__.py +3 -0
- agno/db/base.py +598 -0
- agno/db/dynamo/__init__.py +3 -0
- agno/db/dynamo/dynamo.py +2042 -0
- agno/db/dynamo/schemas.py +314 -0
- agno/db/dynamo/utils.py +743 -0
- agno/db/firestore/__init__.py +3 -0
- agno/db/firestore/firestore.py +1795 -0
- agno/db/firestore/schemas.py +140 -0
- agno/db/firestore/utils.py +376 -0
- agno/db/gcs_json/__init__.py +3 -0
- agno/db/gcs_json/gcs_json_db.py +1335 -0
- agno/db/gcs_json/utils.py +228 -0
- agno/db/in_memory/__init__.py +3 -0
- agno/db/in_memory/in_memory_db.py +1160 -0
- agno/db/in_memory/utils.py +230 -0
- agno/db/json/__init__.py +3 -0
- agno/db/json/json_db.py +1328 -0
- agno/db/json/utils.py +230 -0
- agno/db/migrations/__init__.py +0 -0
- agno/db/migrations/v1_to_v2.py +635 -0
- agno/db/mongo/__init__.py +17 -0
- agno/db/mongo/async_mongo.py +2026 -0
- agno/db/mongo/mongo.py +1982 -0
- agno/db/mongo/schemas.py +87 -0
- agno/db/mongo/utils.py +259 -0
- agno/db/mysql/__init__.py +3 -0
- agno/db/mysql/mysql.py +2308 -0
- agno/db/mysql/schemas.py +138 -0
- agno/db/mysql/utils.py +355 -0
- agno/db/postgres/__init__.py +4 -0
- agno/db/postgres/async_postgres.py +1927 -0
- agno/db/postgres/postgres.py +2260 -0
- agno/db/postgres/schemas.py +139 -0
- agno/db/postgres/utils.py +442 -0
- agno/db/redis/__init__.py +3 -0
- agno/db/redis/redis.py +1660 -0
- agno/db/redis/schemas.py +123 -0
- agno/db/redis/utils.py +346 -0
- agno/db/schemas/__init__.py +4 -0
- agno/db/schemas/culture.py +120 -0
- agno/db/schemas/evals.py +33 -0
- agno/db/schemas/knowledge.py +40 -0
- agno/db/schemas/memory.py +46 -0
- agno/db/schemas/metrics.py +0 -0
- agno/db/singlestore/__init__.py +3 -0
- agno/db/singlestore/schemas.py +130 -0
- agno/db/singlestore/singlestore.py +2272 -0
- agno/db/singlestore/utils.py +384 -0
- agno/db/sqlite/__init__.py +4 -0
- agno/db/sqlite/async_sqlite.py +2293 -0
- agno/db/sqlite/schemas.py +133 -0
- agno/db/sqlite/sqlite.py +2288 -0
- agno/db/sqlite/utils.py +431 -0
- agno/db/surrealdb/__init__.py +3 -0
- agno/db/surrealdb/metrics.py +292 -0
- agno/db/surrealdb/models.py +309 -0
- agno/db/surrealdb/queries.py +71 -0
- agno/db/surrealdb/surrealdb.py +1353 -0
- agno/db/surrealdb/utils.py +147 -0
- agno/db/utils.py +116 -0
- agno/debug.py +18 -0
- agno/eval/__init__.py +14 -0
- agno/eval/accuracy.py +834 -0
- agno/eval/performance.py +773 -0
- agno/eval/reliability.py +306 -0
- agno/eval/utils.py +119 -0
- agno/exceptions.py +161 -0
- agno/filters.py +354 -0
- agno/guardrails/__init__.py +6 -0
- agno/guardrails/base.py +19 -0
- agno/guardrails/openai.py +144 -0
- agno/guardrails/pii.py +94 -0
- agno/guardrails/prompt_injection.py +52 -0
- agno/integrations/__init__.py +0 -0
- agno/integrations/discord/__init__.py +3 -0
- agno/integrations/discord/client.py +203 -0
- agno/knowledge/__init__.py +5 -0
- agno/knowledge/chunking/__init__.py +0 -0
- agno/knowledge/chunking/agentic.py +79 -0
- agno/knowledge/chunking/document.py +91 -0
- agno/knowledge/chunking/fixed.py +57 -0
- agno/knowledge/chunking/markdown.py +151 -0
- agno/knowledge/chunking/recursive.py +63 -0
- agno/knowledge/chunking/row.py +39 -0
- agno/knowledge/chunking/semantic.py +86 -0
- agno/knowledge/chunking/strategy.py +165 -0
- agno/knowledge/content.py +74 -0
- agno/knowledge/document/__init__.py +5 -0
- agno/knowledge/document/base.py +58 -0
- agno/knowledge/embedder/__init__.py +5 -0
- agno/knowledge/embedder/aws_bedrock.py +343 -0
- agno/knowledge/embedder/azure_openai.py +210 -0
- agno/knowledge/embedder/base.py +23 -0
- agno/knowledge/embedder/cohere.py +323 -0
- agno/knowledge/embedder/fastembed.py +62 -0
- agno/knowledge/embedder/fireworks.py +13 -0
- agno/knowledge/embedder/google.py +258 -0
- agno/knowledge/embedder/huggingface.py +94 -0
- agno/knowledge/embedder/jina.py +182 -0
- agno/knowledge/embedder/langdb.py +22 -0
- agno/knowledge/embedder/mistral.py +206 -0
- agno/knowledge/embedder/nebius.py +13 -0
- agno/knowledge/embedder/ollama.py +154 -0
- agno/knowledge/embedder/openai.py +195 -0
- agno/knowledge/embedder/sentence_transformer.py +63 -0
- agno/knowledge/embedder/together.py +13 -0
- agno/knowledge/embedder/vllm.py +262 -0
- agno/knowledge/embedder/voyageai.py +165 -0
- agno/knowledge/knowledge.py +1988 -0
- agno/knowledge/reader/__init__.py +7 -0
- agno/knowledge/reader/arxiv_reader.py +81 -0
- agno/knowledge/reader/base.py +95 -0
- agno/knowledge/reader/csv_reader.py +166 -0
- agno/knowledge/reader/docx_reader.py +82 -0
- agno/knowledge/reader/field_labeled_csv_reader.py +292 -0
- agno/knowledge/reader/firecrawl_reader.py +201 -0
- agno/knowledge/reader/json_reader.py +87 -0
- agno/knowledge/reader/markdown_reader.py +137 -0
- agno/knowledge/reader/pdf_reader.py +431 -0
- agno/knowledge/reader/pptx_reader.py +101 -0
- agno/knowledge/reader/reader_factory.py +313 -0
- agno/knowledge/reader/s3_reader.py +89 -0
- agno/knowledge/reader/tavily_reader.py +194 -0
- agno/knowledge/reader/text_reader.py +115 -0
- agno/knowledge/reader/web_search_reader.py +372 -0
- agno/knowledge/reader/website_reader.py +455 -0
- agno/knowledge/reader/wikipedia_reader.py +59 -0
- agno/knowledge/reader/youtube_reader.py +78 -0
- agno/knowledge/remote_content/__init__.py +0 -0
- agno/knowledge/remote_content/remote_content.py +88 -0
- agno/knowledge/reranker/__init__.py +3 -0
- agno/knowledge/reranker/base.py +14 -0
- agno/knowledge/reranker/cohere.py +64 -0
- agno/knowledge/reranker/infinity.py +195 -0
- agno/knowledge/reranker/sentence_transformer.py +54 -0
- agno/knowledge/types.py +39 -0
- agno/knowledge/utils.py +189 -0
- agno/media.py +462 -0
- agno/memory/__init__.py +3 -0
- agno/memory/manager.py +1327 -0
- agno/models/__init__.py +0 -0
- agno/models/aimlapi/__init__.py +5 -0
- agno/models/aimlapi/aimlapi.py +45 -0
- agno/models/anthropic/__init__.py +5 -0
- agno/models/anthropic/claude.py +757 -0
- agno/models/aws/__init__.py +15 -0
- agno/models/aws/bedrock.py +701 -0
- agno/models/aws/claude.py +378 -0
- agno/models/azure/__init__.py +18 -0
- agno/models/azure/ai_foundry.py +485 -0
- agno/models/azure/openai_chat.py +131 -0
- agno/models/base.py +2175 -0
- agno/models/cerebras/__init__.py +12 -0
- agno/models/cerebras/cerebras.py +501 -0
- agno/models/cerebras/cerebras_openai.py +112 -0
- agno/models/cohere/__init__.py +5 -0
- agno/models/cohere/chat.py +389 -0
- agno/models/cometapi/__init__.py +5 -0
- agno/models/cometapi/cometapi.py +57 -0
- agno/models/dashscope/__init__.py +5 -0
- agno/models/dashscope/dashscope.py +91 -0
- agno/models/deepinfra/__init__.py +5 -0
- agno/models/deepinfra/deepinfra.py +28 -0
- agno/models/deepseek/__init__.py +5 -0
- agno/models/deepseek/deepseek.py +61 -0
- agno/models/defaults.py +1 -0
- agno/models/fireworks/__init__.py +5 -0
- agno/models/fireworks/fireworks.py +26 -0
- agno/models/google/__init__.py +5 -0
- agno/models/google/gemini.py +1085 -0
- agno/models/groq/__init__.py +5 -0
- agno/models/groq/groq.py +556 -0
- agno/models/huggingface/__init__.py +5 -0
- agno/models/huggingface/huggingface.py +491 -0
- agno/models/ibm/__init__.py +5 -0
- agno/models/ibm/watsonx.py +422 -0
- agno/models/internlm/__init__.py +3 -0
- agno/models/internlm/internlm.py +26 -0
- agno/models/langdb/__init__.py +1 -0
- agno/models/langdb/langdb.py +48 -0
- agno/models/litellm/__init__.py +14 -0
- agno/models/litellm/chat.py +468 -0
- agno/models/litellm/litellm_openai.py +25 -0
- agno/models/llama_cpp/__init__.py +5 -0
- agno/models/llama_cpp/llama_cpp.py +22 -0
- agno/models/lmstudio/__init__.py +5 -0
- agno/models/lmstudio/lmstudio.py +25 -0
- agno/models/message.py +434 -0
- agno/models/meta/__init__.py +12 -0
- agno/models/meta/llama.py +475 -0
- agno/models/meta/llama_openai.py +78 -0
- agno/models/metrics.py +120 -0
- agno/models/mistral/__init__.py +5 -0
- agno/models/mistral/mistral.py +432 -0
- agno/models/nebius/__init__.py +3 -0
- agno/models/nebius/nebius.py +54 -0
- agno/models/nexus/__init__.py +3 -0
- agno/models/nexus/nexus.py +22 -0
- agno/models/nvidia/__init__.py +5 -0
- agno/models/nvidia/nvidia.py +28 -0
- agno/models/ollama/__init__.py +5 -0
- agno/models/ollama/chat.py +441 -0
- agno/models/openai/__init__.py +9 -0
- agno/models/openai/chat.py +883 -0
- agno/models/openai/like.py +27 -0
- agno/models/openai/responses.py +1050 -0
- agno/models/openrouter/__init__.py +5 -0
- agno/models/openrouter/openrouter.py +66 -0
- agno/models/perplexity/__init__.py +5 -0
- agno/models/perplexity/perplexity.py +187 -0
- agno/models/portkey/__init__.py +3 -0
- agno/models/portkey/portkey.py +81 -0
- agno/models/requesty/__init__.py +5 -0
- agno/models/requesty/requesty.py +52 -0
- agno/models/response.py +199 -0
- agno/models/sambanova/__init__.py +5 -0
- agno/models/sambanova/sambanova.py +28 -0
- agno/models/siliconflow/__init__.py +5 -0
- agno/models/siliconflow/siliconflow.py +25 -0
- agno/models/together/__init__.py +5 -0
- agno/models/together/together.py +25 -0
- agno/models/utils.py +266 -0
- agno/models/vercel/__init__.py +3 -0
- agno/models/vercel/v0.py +26 -0
- agno/models/vertexai/__init__.py +0 -0
- agno/models/vertexai/claude.py +70 -0
- agno/models/vllm/__init__.py +3 -0
- agno/models/vllm/vllm.py +78 -0
- agno/models/xai/__init__.py +3 -0
- agno/models/xai/xai.py +113 -0
- agno/os/__init__.py +3 -0
- agno/os/app.py +876 -0
- agno/os/auth.py +57 -0
- agno/os/config.py +104 -0
- agno/os/interfaces/__init__.py +1 -0
- agno/os/interfaces/a2a/__init__.py +3 -0
- agno/os/interfaces/a2a/a2a.py +42 -0
- agno/os/interfaces/a2a/router.py +250 -0
- agno/os/interfaces/a2a/utils.py +924 -0
- agno/os/interfaces/agui/__init__.py +3 -0
- agno/os/interfaces/agui/agui.py +47 -0
- agno/os/interfaces/agui/router.py +144 -0
- agno/os/interfaces/agui/utils.py +534 -0
- agno/os/interfaces/base.py +25 -0
- agno/os/interfaces/slack/__init__.py +3 -0
- agno/os/interfaces/slack/router.py +148 -0
- agno/os/interfaces/slack/security.py +30 -0
- agno/os/interfaces/slack/slack.py +47 -0
- agno/os/interfaces/whatsapp/__init__.py +3 -0
- agno/os/interfaces/whatsapp/router.py +211 -0
- agno/os/interfaces/whatsapp/security.py +53 -0
- agno/os/interfaces/whatsapp/whatsapp.py +36 -0
- agno/os/mcp.py +292 -0
- agno/os/middleware/__init__.py +7 -0
- agno/os/middleware/jwt.py +233 -0
- agno/os/router.py +1763 -0
- agno/os/routers/__init__.py +3 -0
- agno/os/routers/evals/__init__.py +3 -0
- agno/os/routers/evals/evals.py +430 -0
- agno/os/routers/evals/schemas.py +142 -0
- agno/os/routers/evals/utils.py +162 -0
- agno/os/routers/health.py +31 -0
- agno/os/routers/home.py +52 -0
- agno/os/routers/knowledge/__init__.py +3 -0
- agno/os/routers/knowledge/knowledge.py +997 -0
- agno/os/routers/knowledge/schemas.py +178 -0
- agno/os/routers/memory/__init__.py +3 -0
- agno/os/routers/memory/memory.py +515 -0
- agno/os/routers/memory/schemas.py +62 -0
- agno/os/routers/metrics/__init__.py +3 -0
- agno/os/routers/metrics/metrics.py +190 -0
- agno/os/routers/metrics/schemas.py +47 -0
- agno/os/routers/session/__init__.py +3 -0
- agno/os/routers/session/session.py +997 -0
- agno/os/schema.py +1055 -0
- agno/os/settings.py +43 -0
- agno/os/utils.py +630 -0
- agno/py.typed +0 -0
- agno/reasoning/__init__.py +0 -0
- agno/reasoning/anthropic.py +80 -0
- agno/reasoning/azure_ai_foundry.py +67 -0
- agno/reasoning/deepseek.py +63 -0
- agno/reasoning/default.py +97 -0
- agno/reasoning/gemini.py +73 -0
- agno/reasoning/groq.py +71 -0
- agno/reasoning/helpers.py +63 -0
- agno/reasoning/ollama.py +67 -0
- agno/reasoning/openai.py +86 -0
- agno/reasoning/step.py +31 -0
- agno/reasoning/vertexai.py +76 -0
- agno/run/__init__.py +6 -0
- agno/run/agent.py +787 -0
- agno/run/base.py +229 -0
- agno/run/cancel.py +81 -0
- agno/run/messages.py +32 -0
- agno/run/team.py +753 -0
- agno/run/workflow.py +708 -0
- agno/session/__init__.py +10 -0
- agno/session/agent.py +295 -0
- agno/session/summary.py +265 -0
- agno/session/team.py +392 -0
- agno/session/workflow.py +205 -0
- agno/team/__init__.py +37 -0
- agno/team/team.py +8793 -0
- agno/tools/__init__.py +10 -0
- agno/tools/agentql.py +120 -0
- agno/tools/airflow.py +69 -0
- agno/tools/api.py +122 -0
- agno/tools/apify.py +314 -0
- agno/tools/arxiv.py +127 -0
- agno/tools/aws_lambda.py +53 -0
- agno/tools/aws_ses.py +66 -0
- agno/tools/baidusearch.py +89 -0
- agno/tools/bitbucket.py +292 -0
- agno/tools/brandfetch.py +213 -0
- agno/tools/bravesearch.py +106 -0
- agno/tools/brightdata.py +367 -0
- agno/tools/browserbase.py +209 -0
- agno/tools/calcom.py +255 -0
- agno/tools/calculator.py +151 -0
- agno/tools/cartesia.py +187 -0
- agno/tools/clickup.py +244 -0
- agno/tools/confluence.py +240 -0
- agno/tools/crawl4ai.py +158 -0
- agno/tools/csv_toolkit.py +185 -0
- agno/tools/dalle.py +110 -0
- agno/tools/daytona.py +475 -0
- agno/tools/decorator.py +262 -0
- agno/tools/desi_vocal.py +108 -0
- agno/tools/discord.py +161 -0
- agno/tools/docker.py +716 -0
- agno/tools/duckdb.py +379 -0
- agno/tools/duckduckgo.py +91 -0
- agno/tools/e2b.py +703 -0
- agno/tools/eleven_labs.py +196 -0
- agno/tools/email.py +67 -0
- agno/tools/evm.py +129 -0
- agno/tools/exa.py +396 -0
- agno/tools/fal.py +127 -0
- agno/tools/file.py +240 -0
- agno/tools/file_generation.py +350 -0
- agno/tools/financial_datasets.py +288 -0
- agno/tools/firecrawl.py +143 -0
- agno/tools/function.py +1187 -0
- agno/tools/giphy.py +93 -0
- agno/tools/github.py +1760 -0
- agno/tools/gmail.py +922 -0
- agno/tools/google_bigquery.py +117 -0
- agno/tools/google_drive.py +270 -0
- agno/tools/google_maps.py +253 -0
- agno/tools/googlecalendar.py +674 -0
- agno/tools/googlesearch.py +98 -0
- agno/tools/googlesheets.py +377 -0
- agno/tools/hackernews.py +77 -0
- agno/tools/jina.py +101 -0
- agno/tools/jira.py +170 -0
- agno/tools/knowledge.py +218 -0
- agno/tools/linear.py +426 -0
- agno/tools/linkup.py +58 -0
- agno/tools/local_file_system.py +90 -0
- agno/tools/lumalab.py +183 -0
- agno/tools/mcp/__init__.py +10 -0
- agno/tools/mcp/mcp.py +331 -0
- agno/tools/mcp/multi_mcp.py +347 -0
- agno/tools/mcp/params.py +24 -0
- agno/tools/mcp_toolbox.py +284 -0
- agno/tools/mem0.py +193 -0
- agno/tools/memori.py +339 -0
- agno/tools/memory.py +419 -0
- agno/tools/mlx_transcribe.py +139 -0
- agno/tools/models/__init__.py +0 -0
- agno/tools/models/azure_openai.py +190 -0
- agno/tools/models/gemini.py +203 -0
- agno/tools/models/groq.py +158 -0
- agno/tools/models/morph.py +186 -0
- agno/tools/models/nebius.py +124 -0
- agno/tools/models_labs.py +195 -0
- agno/tools/moviepy_video.py +349 -0
- agno/tools/neo4j.py +134 -0
- agno/tools/newspaper.py +46 -0
- agno/tools/newspaper4k.py +93 -0
- agno/tools/notion.py +204 -0
- agno/tools/openai.py +202 -0
- agno/tools/openbb.py +160 -0
- agno/tools/opencv.py +321 -0
- agno/tools/openweather.py +233 -0
- agno/tools/oxylabs.py +385 -0
- agno/tools/pandas.py +102 -0
- agno/tools/parallel.py +314 -0
- agno/tools/postgres.py +257 -0
- agno/tools/pubmed.py +188 -0
- agno/tools/python.py +205 -0
- agno/tools/reasoning.py +283 -0
- agno/tools/reddit.py +467 -0
- agno/tools/replicate.py +117 -0
- agno/tools/resend.py +62 -0
- agno/tools/scrapegraph.py +222 -0
- agno/tools/searxng.py +152 -0
- agno/tools/serpapi.py +116 -0
- agno/tools/serper.py +255 -0
- agno/tools/shell.py +53 -0
- agno/tools/slack.py +136 -0
- agno/tools/sleep.py +20 -0
- agno/tools/spider.py +116 -0
- agno/tools/sql.py +154 -0
- agno/tools/streamlit/__init__.py +0 -0
- agno/tools/streamlit/components.py +113 -0
- agno/tools/tavily.py +254 -0
- agno/tools/telegram.py +48 -0
- agno/tools/todoist.py +218 -0
- agno/tools/tool_registry.py +1 -0
- agno/tools/toolkit.py +146 -0
- agno/tools/trafilatura.py +388 -0
- agno/tools/trello.py +274 -0
- agno/tools/twilio.py +186 -0
- agno/tools/user_control_flow.py +78 -0
- agno/tools/valyu.py +228 -0
- agno/tools/visualization.py +467 -0
- agno/tools/webbrowser.py +28 -0
- agno/tools/webex.py +76 -0
- agno/tools/website.py +54 -0
- agno/tools/webtools.py +45 -0
- agno/tools/whatsapp.py +286 -0
- agno/tools/wikipedia.py +63 -0
- agno/tools/workflow.py +278 -0
- agno/tools/x.py +335 -0
- agno/tools/yfinance.py +257 -0
- agno/tools/youtube.py +184 -0
- agno/tools/zendesk.py +82 -0
- agno/tools/zep.py +454 -0
- agno/tools/zoom.py +382 -0
- agno/utils/__init__.py +0 -0
- agno/utils/agent.py +820 -0
- agno/utils/audio.py +49 -0
- agno/utils/certs.py +27 -0
- agno/utils/code_execution.py +11 -0
- agno/utils/common.py +132 -0
- agno/utils/dttm.py +13 -0
- agno/utils/enum.py +22 -0
- agno/utils/env.py +11 -0
- agno/utils/events.py +696 -0
- agno/utils/format_str.py +16 -0
- agno/utils/functions.py +166 -0
- agno/utils/gemini.py +426 -0
- agno/utils/hooks.py +57 -0
- agno/utils/http.py +74 -0
- agno/utils/json_schema.py +234 -0
- agno/utils/knowledge.py +36 -0
- agno/utils/location.py +19 -0
- agno/utils/log.py +255 -0
- agno/utils/mcp.py +214 -0
- agno/utils/media.py +352 -0
- agno/utils/merge_dict.py +41 -0
- agno/utils/message.py +118 -0
- agno/utils/models/__init__.py +0 -0
- agno/utils/models/ai_foundry.py +43 -0
- agno/utils/models/claude.py +358 -0
- agno/utils/models/cohere.py +87 -0
- agno/utils/models/llama.py +78 -0
- agno/utils/models/mistral.py +98 -0
- agno/utils/models/openai_responses.py +140 -0
- agno/utils/models/schema_utils.py +153 -0
- agno/utils/models/watsonx.py +41 -0
- agno/utils/openai.py +257 -0
- agno/utils/pickle.py +32 -0
- agno/utils/pprint.py +178 -0
- agno/utils/print_response/__init__.py +0 -0
- agno/utils/print_response/agent.py +842 -0
- agno/utils/print_response/team.py +1724 -0
- agno/utils/print_response/workflow.py +1668 -0
- agno/utils/prompts.py +111 -0
- agno/utils/reasoning.py +108 -0
- agno/utils/response.py +163 -0
- agno/utils/response_iterator.py +17 -0
- agno/utils/safe_formatter.py +24 -0
- agno/utils/serialize.py +32 -0
- agno/utils/shell.py +22 -0
- agno/utils/streamlit.py +487 -0
- agno/utils/string.py +231 -0
- agno/utils/team.py +139 -0
- agno/utils/timer.py +41 -0
- agno/utils/tools.py +102 -0
- agno/utils/web.py +23 -0
- agno/utils/whatsapp.py +305 -0
- agno/utils/yaml_io.py +25 -0
- agno/vectordb/__init__.py +3 -0
- agno/vectordb/base.py +127 -0
- agno/vectordb/cassandra/__init__.py +5 -0
- agno/vectordb/cassandra/cassandra.py +501 -0
- agno/vectordb/cassandra/extra_param_mixin.py +11 -0
- agno/vectordb/cassandra/index.py +13 -0
- agno/vectordb/chroma/__init__.py +5 -0
- agno/vectordb/chroma/chromadb.py +929 -0
- agno/vectordb/clickhouse/__init__.py +9 -0
- agno/vectordb/clickhouse/clickhousedb.py +835 -0
- agno/vectordb/clickhouse/index.py +9 -0
- agno/vectordb/couchbase/__init__.py +3 -0
- agno/vectordb/couchbase/couchbase.py +1442 -0
- agno/vectordb/distance.py +7 -0
- agno/vectordb/lancedb/__init__.py +6 -0
- agno/vectordb/lancedb/lance_db.py +995 -0
- agno/vectordb/langchaindb/__init__.py +5 -0
- agno/vectordb/langchaindb/langchaindb.py +163 -0
- agno/vectordb/lightrag/__init__.py +5 -0
- agno/vectordb/lightrag/lightrag.py +388 -0
- agno/vectordb/llamaindex/__init__.py +3 -0
- agno/vectordb/llamaindex/llamaindexdb.py +166 -0
- agno/vectordb/milvus/__init__.py +4 -0
- agno/vectordb/milvus/milvus.py +1182 -0
- agno/vectordb/mongodb/__init__.py +9 -0
- agno/vectordb/mongodb/mongodb.py +1417 -0
- agno/vectordb/pgvector/__init__.py +12 -0
- agno/vectordb/pgvector/index.py +23 -0
- agno/vectordb/pgvector/pgvector.py +1462 -0
- agno/vectordb/pineconedb/__init__.py +5 -0
- agno/vectordb/pineconedb/pineconedb.py +747 -0
- agno/vectordb/qdrant/__init__.py +5 -0
- agno/vectordb/qdrant/qdrant.py +1134 -0
- agno/vectordb/redis/__init__.py +9 -0
- agno/vectordb/redis/redisdb.py +694 -0
- agno/vectordb/search.py +7 -0
- agno/vectordb/singlestore/__init__.py +10 -0
- agno/vectordb/singlestore/index.py +41 -0
- agno/vectordb/singlestore/singlestore.py +763 -0
- agno/vectordb/surrealdb/__init__.py +3 -0
- agno/vectordb/surrealdb/surrealdb.py +699 -0
- agno/vectordb/upstashdb/__init__.py +5 -0
- agno/vectordb/upstashdb/upstashdb.py +718 -0
- agno/vectordb/weaviate/__init__.py +8 -0
- agno/vectordb/weaviate/index.py +15 -0
- agno/vectordb/weaviate/weaviate.py +1005 -0
- agno/workflow/__init__.py +23 -0
- agno/workflow/agent.py +299 -0
- agno/workflow/condition.py +738 -0
- agno/workflow/loop.py +735 -0
- agno/workflow/parallel.py +824 -0
- agno/workflow/router.py +702 -0
- agno/workflow/step.py +1432 -0
- agno/workflow/steps.py +592 -0
- agno/workflow/types.py +520 -0
- agno/workflow/workflow.py +4321 -0
- agno-2.2.13.dist-info/METADATA +614 -0
- agno-2.2.13.dist-info/RECORD +575 -0
- agno-2.2.13.dist-info/WHEEL +5 -0
- agno-2.2.13.dist-info/licenses/LICENSE +201 -0
- agno-2.2.13.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
from typing import Any, Dict, List, Optional, Union
|
|
2
|
+
|
|
3
|
+
from agno.filters import FilterExpr
|
|
4
|
+
from agno.knowledge.document import Document
|
|
5
|
+
from agno.utils.log import log_debug, log_warning, logger
|
|
6
|
+
from agno.vectordb.base import VectorDb
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class LangChainVectorDb(VectorDb):
|
|
10
|
+
def __init__(
|
|
11
|
+
self,
|
|
12
|
+
vectorstore: Optional[Any] = None,
|
|
13
|
+
search_kwargs: Optional[dict] = None,
|
|
14
|
+
knowledge_retriever: Optional[Any] = None,
|
|
15
|
+
name: Optional[str] = None,
|
|
16
|
+
description: Optional[str] = None,
|
|
17
|
+
):
|
|
18
|
+
"""
|
|
19
|
+
Initialize LangChainVectorDb.
|
|
20
|
+
|
|
21
|
+
Args:
|
|
22
|
+
vectorstore: The LangChain vectorstore instance
|
|
23
|
+
name (Optional[str]): Name of the vector database.
|
|
24
|
+
description (Optional[str]): Description of the vector database.
|
|
25
|
+
search_kwargs: Additional search parameters for the retriever
|
|
26
|
+
knowledge_retriever: An optional LangChain retriever instance
|
|
27
|
+
"""
|
|
28
|
+
self.vectorstore = vectorstore
|
|
29
|
+
# Initialize base class with name and description
|
|
30
|
+
super().__init__(name=name, description=description)
|
|
31
|
+
|
|
32
|
+
self.search_kwargs = search_kwargs
|
|
33
|
+
self.knowledge_retriever = knowledge_retriever
|
|
34
|
+
|
|
35
|
+
def create(self) -> None:
|
|
36
|
+
raise NotImplementedError
|
|
37
|
+
|
|
38
|
+
async def async_create(self) -> None:
|
|
39
|
+
raise NotImplementedError
|
|
40
|
+
|
|
41
|
+
def name_exists(self, name: str) -> bool:
|
|
42
|
+
raise NotImplementedError
|
|
43
|
+
|
|
44
|
+
def async_name_exists(self, name: str) -> bool:
|
|
45
|
+
raise NotImplementedError
|
|
46
|
+
|
|
47
|
+
def id_exists(self, id: str) -> bool:
|
|
48
|
+
raise NotImplementedError
|
|
49
|
+
|
|
50
|
+
def content_hash_exists(self, content_hash: str) -> bool:
|
|
51
|
+
raise NotImplementedError
|
|
52
|
+
|
|
53
|
+
def delete_by_content_id(self, content_id: str) -> None:
|
|
54
|
+
raise NotImplementedError
|
|
55
|
+
|
|
56
|
+
def insert(self, content_hash: str, documents: List[Document], filters: Optional[Dict[str, Any]] = None) -> None:
|
|
57
|
+
logger.warning("LangChainKnowledgeBase.insert() not supported - please check the vectorstore manually.")
|
|
58
|
+
raise NotImplementedError
|
|
59
|
+
|
|
60
|
+
async def async_insert(
|
|
61
|
+
self, content_hash: str, documents: List[Document], filters: Optional[Dict[str, Any]] = None
|
|
62
|
+
) -> None:
|
|
63
|
+
logger.warning("LangChainKnowledgeBase.async_insert() not supported - please check the vectorstore manually.")
|
|
64
|
+
raise NotImplementedError
|
|
65
|
+
|
|
66
|
+
def upsert(self, content_hash: str, documents: List[Document], filters: Optional[Dict[str, Any]] = None) -> None:
|
|
67
|
+
logger.warning("LangChainKnowledgeBase.upsert() not supported - please check the vectorstore manually.")
|
|
68
|
+
raise NotImplementedError
|
|
69
|
+
|
|
70
|
+
async def async_upsert(self, documents: List[Document], filters: Optional[Dict[str, Any]] = None) -> None:
|
|
71
|
+
logger.warning("LangChainKnowledgeBase.async_upsert() not supported - please check the vectorstore manually.")
|
|
72
|
+
raise NotImplementedError
|
|
73
|
+
|
|
74
|
+
def search(
|
|
75
|
+
self, query: str, limit: int = 5, filters: Optional[Union[Dict[str, Any], List[FilterExpr]]] = None
|
|
76
|
+
) -> List[Document]:
|
|
77
|
+
"""Returns relevant documents matching the query"""
|
|
78
|
+
|
|
79
|
+
if isinstance(filters, List):
|
|
80
|
+
log_warning(
|
|
81
|
+
"Filter Expressions are not supported in LangChainDB. No filters will be applied. Use filters as a dictionary."
|
|
82
|
+
)
|
|
83
|
+
filters = None
|
|
84
|
+
|
|
85
|
+
try:
|
|
86
|
+
from langchain_core.documents import Document as LangChainDocument
|
|
87
|
+
from langchain_core.retrievers import BaseRetriever
|
|
88
|
+
except ImportError:
|
|
89
|
+
raise ImportError(
|
|
90
|
+
"The `langchain` package is not installed. Please install it via `pip install langchain`."
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
if self.vectorstore is not None and self.knowledge_retriever is None:
|
|
94
|
+
log_debug("Creating knowledge retriever")
|
|
95
|
+
if self.search_kwargs is None:
|
|
96
|
+
self.search_kwargs = {"k": limit}
|
|
97
|
+
if filters is not None:
|
|
98
|
+
self.search_kwargs.update(filters)
|
|
99
|
+
self.knowledge_retriever = self.vectorstore.as_retriever(search_kwargs=self.search_kwargs)
|
|
100
|
+
|
|
101
|
+
if self.knowledge_retriever is None:
|
|
102
|
+
logger.error("No knowledge retriever provided")
|
|
103
|
+
return []
|
|
104
|
+
|
|
105
|
+
if not isinstance(self.knowledge_retriever, BaseRetriever):
|
|
106
|
+
raise ValueError(f"Knowledge retriever is not of type BaseRetriever: {self.knowledge_retriever}")
|
|
107
|
+
|
|
108
|
+
log_debug(f"Getting {limit} relevant documents for query: {query}")
|
|
109
|
+
lc_documents: List[LangChainDocument] = self.knowledge_retriever.invoke(input=query)
|
|
110
|
+
documents = []
|
|
111
|
+
for lc_doc in lc_documents:
|
|
112
|
+
documents.append(
|
|
113
|
+
Document(
|
|
114
|
+
content=lc_doc.page_content,
|
|
115
|
+
meta_data=lc_doc.metadata,
|
|
116
|
+
)
|
|
117
|
+
)
|
|
118
|
+
return documents
|
|
119
|
+
|
|
120
|
+
async def async_search(
|
|
121
|
+
self, query: str, limit: int = 5, filters: Optional[Union[Dict[str, Any], List[FilterExpr]]] = None
|
|
122
|
+
) -> List[Document]:
|
|
123
|
+
return self.search(query, limit, filters)
|
|
124
|
+
|
|
125
|
+
def drop(self) -> None:
|
|
126
|
+
raise NotImplementedError
|
|
127
|
+
|
|
128
|
+
async def async_drop(self) -> None:
|
|
129
|
+
raise NotImplementedError
|
|
130
|
+
|
|
131
|
+
async def async_exists(self) -> bool:
|
|
132
|
+
raise NotImplementedError
|
|
133
|
+
|
|
134
|
+
def delete(self) -> bool:
|
|
135
|
+
raise NotImplementedError
|
|
136
|
+
|
|
137
|
+
def delete_by_id(self, id: str) -> bool:
|
|
138
|
+
raise NotImplementedError
|
|
139
|
+
|
|
140
|
+
def delete_by_name(self, name: str) -> bool:
|
|
141
|
+
raise NotImplementedError
|
|
142
|
+
|
|
143
|
+
def delete_by_metadata(self, metadata: Dict[str, Any]) -> bool:
|
|
144
|
+
raise NotImplementedError
|
|
145
|
+
|
|
146
|
+
def exists(self) -> bool:
|
|
147
|
+
logger.warning("LangChainKnowledgeBase.exists() not supported - please check the vectorstore manually.")
|
|
148
|
+
return True
|
|
149
|
+
|
|
150
|
+
def update_metadata(self, content_id: str, metadata: Dict[str, Any]) -> None:
|
|
151
|
+
"""
|
|
152
|
+
Update the metadata for documents with the given content_id.
|
|
153
|
+
Not implemented for LangChain wrapper.
|
|
154
|
+
|
|
155
|
+
Args:
|
|
156
|
+
content_id (str): The content ID to update
|
|
157
|
+
metadata (Dict[str, Any]): The metadata to update
|
|
158
|
+
"""
|
|
159
|
+
raise NotImplementedError("update_metadata not supported for LangChain vectorstores")
|
|
160
|
+
|
|
161
|
+
def get_supported_search_types(self) -> List[str]:
|
|
162
|
+
"""Get the supported search types for this vector database."""
|
|
163
|
+
return [] # LangChainVectorDb doesn't use SearchType enum
|
|
@@ -0,0 +1,388 @@
|
|
|
1
|
+
import asyncio
|
|
2
|
+
from typing import Any, Dict, List, Optional, Union
|
|
3
|
+
|
|
4
|
+
import httpx
|
|
5
|
+
|
|
6
|
+
from agno.filters import FilterExpr
|
|
7
|
+
from agno.knowledge.document import Document
|
|
8
|
+
from agno.utils.log import log_debug, log_error, log_info, log_warning
|
|
9
|
+
from agno.vectordb.base import VectorDb
|
|
10
|
+
|
|
11
|
+
DEFAULT_SERVER_URL = "http://localhost:9621"
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class LightRag(VectorDb):
|
|
15
|
+
"""
|
|
16
|
+
LightRAG VectorDB implementation
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
def __init__(
|
|
20
|
+
self,
|
|
21
|
+
server_url: str = DEFAULT_SERVER_URL,
|
|
22
|
+
api_key: Optional[str] = None,
|
|
23
|
+
auth_header_name: str = "X-API-KEY",
|
|
24
|
+
auth_header_format: str = "{api_key}",
|
|
25
|
+
name: Optional[str] = None,
|
|
26
|
+
description: Optional[str] = None,
|
|
27
|
+
):
|
|
28
|
+
self.server_url = server_url
|
|
29
|
+
self.api_key = api_key
|
|
30
|
+
# Initialize base class with name and description
|
|
31
|
+
super().__init__(name=name, description=description)
|
|
32
|
+
|
|
33
|
+
self.auth_header_name = auth_header_name
|
|
34
|
+
self.auth_header_format = auth_header_format
|
|
35
|
+
|
|
36
|
+
def _get_headers(self) -> Dict[str, str]:
|
|
37
|
+
"""Get headers with optional API key authentication."""
|
|
38
|
+
headers = {"Content-Type": "application/json"}
|
|
39
|
+
if self.api_key:
|
|
40
|
+
headers[self.auth_header_name] = self.auth_header_format.format(api_key=self.api_key)
|
|
41
|
+
return headers
|
|
42
|
+
|
|
43
|
+
def _get_auth_headers(self) -> Dict[str, str]:
|
|
44
|
+
"""Get minimal headers with just authentication (for file uploads)."""
|
|
45
|
+
headers = {}
|
|
46
|
+
if self.api_key:
|
|
47
|
+
headers[self.auth_header_name] = self.auth_header_format.format(api_key=self.api_key)
|
|
48
|
+
return headers
|
|
49
|
+
|
|
50
|
+
def create(self) -> None:
|
|
51
|
+
"""Create the vector database"""
|
|
52
|
+
pass
|
|
53
|
+
|
|
54
|
+
async def async_create(self) -> None:
|
|
55
|
+
"""Async create the vector database"""
|
|
56
|
+
pass
|
|
57
|
+
|
|
58
|
+
def name_exists(self, name: str) -> bool:
|
|
59
|
+
"""Check if a document with the given name exists"""
|
|
60
|
+
return False
|
|
61
|
+
|
|
62
|
+
async def async_name_exists(self, name: str) -> bool:
|
|
63
|
+
"""Async check if a document with the given name exists"""
|
|
64
|
+
return False
|
|
65
|
+
|
|
66
|
+
def id_exists(self, id: str) -> bool:
|
|
67
|
+
"""Check if a document with the given ID exists"""
|
|
68
|
+
return False
|
|
69
|
+
|
|
70
|
+
def content_hash_exists(self, content_hash: str) -> bool:
|
|
71
|
+
"""Check if content with the given hash exists"""
|
|
72
|
+
return False
|
|
73
|
+
|
|
74
|
+
def insert(self, content_hash: str, documents: List[Document], filters: Optional[Dict[str, Any]] = None) -> None:
|
|
75
|
+
"""Insert documents into the vector database"""
|
|
76
|
+
pass
|
|
77
|
+
|
|
78
|
+
async def async_insert(
|
|
79
|
+
self, content_hash: str, documents: List[Document], filters: Optional[Dict[str, Any]] = None
|
|
80
|
+
) -> None:
|
|
81
|
+
"""Async insert documents into the vector database"""
|
|
82
|
+
pass
|
|
83
|
+
|
|
84
|
+
def upsert(self, content_hash: str, documents: List[Document], filters: Optional[Dict[str, Any]] = None) -> None:
|
|
85
|
+
"""Upsert documents into the vector database"""
|
|
86
|
+
pass
|
|
87
|
+
|
|
88
|
+
def delete_by_content_id(self, content_id: str) -> None:
|
|
89
|
+
"""Delete documents by content ID"""
|
|
90
|
+
pass
|
|
91
|
+
|
|
92
|
+
async def async_upsert(self, documents: List[Document], filters: Optional[Dict[str, Any]] = None) -> None:
|
|
93
|
+
"""Async upsert documents into the vector database"""
|
|
94
|
+
pass
|
|
95
|
+
|
|
96
|
+
def search(
|
|
97
|
+
self, query: str, limit: int = 5, filters: Optional[Union[Dict[str, Any], List[FilterExpr]]] = None
|
|
98
|
+
) -> List[Document]:
|
|
99
|
+
result = asyncio.run(self.async_search(query, limit=limit, filters=filters))
|
|
100
|
+
return result if result is not None else []
|
|
101
|
+
|
|
102
|
+
async def async_search(
|
|
103
|
+
self, query: str, limit: Optional[int] = None, filters: Optional[Union[Dict[str, Any], List[FilterExpr]]] = None
|
|
104
|
+
) -> Optional[List[Document]]:
|
|
105
|
+
mode: str = "hybrid" # Default mode, can be "local", "global", or "hybrid"
|
|
106
|
+
if filters is not None:
|
|
107
|
+
log_warning("Filters are not supported in LightRAG. No filters will be applied.")
|
|
108
|
+
try:
|
|
109
|
+
async with httpx.AsyncClient(timeout=30.0) as client:
|
|
110
|
+
response = await client.post(
|
|
111
|
+
f"{self.server_url}/query",
|
|
112
|
+
json={"query": query, "mode": "hybrid"},
|
|
113
|
+
headers=self._get_headers(),
|
|
114
|
+
)
|
|
115
|
+
|
|
116
|
+
response.raise_for_status()
|
|
117
|
+
result = response.json()
|
|
118
|
+
|
|
119
|
+
return self._format_lightrag_response(result, query, mode)
|
|
120
|
+
|
|
121
|
+
except httpx.RequestError as e:
|
|
122
|
+
log_error(f"HTTP Request Error: {type(e).__name__}: {str(e)}")
|
|
123
|
+
return []
|
|
124
|
+
except httpx.HTTPStatusError as e:
|
|
125
|
+
log_error(f"HTTP Status Error: {e.response.status_code} - {e.response.text}")
|
|
126
|
+
return []
|
|
127
|
+
except Exception as e:
|
|
128
|
+
log_error(f"Unexpected error during LightRAG server search: {type(e).__name__}: {str(e)}")
|
|
129
|
+
import traceback
|
|
130
|
+
|
|
131
|
+
log_error(f"Full traceback: {traceback.format_exc()}")
|
|
132
|
+
return None
|
|
133
|
+
|
|
134
|
+
def drop(self) -> None:
|
|
135
|
+
"""Drop the vector database"""
|
|
136
|
+
asyncio.run(self.async_drop())
|
|
137
|
+
|
|
138
|
+
async def async_drop(self) -> None:
|
|
139
|
+
"""Async drop the vector database"""
|
|
140
|
+
async with httpx.AsyncClient(timeout=30.0) as client:
|
|
141
|
+
await client.delete(f"{self.server_url}/documents", headers=self._get_headers())
|
|
142
|
+
|
|
143
|
+
async with httpx.AsyncClient(timeout=30.0) as client:
|
|
144
|
+
await client.post(
|
|
145
|
+
f"{self.server_url}/documents/clear_cache",
|
|
146
|
+
json={"modes": ["default", "naive"]},
|
|
147
|
+
headers=self._get_headers(),
|
|
148
|
+
)
|
|
149
|
+
|
|
150
|
+
def exists(self) -> bool:
|
|
151
|
+
"""Check if the vector database exists"""
|
|
152
|
+
return False
|
|
153
|
+
|
|
154
|
+
async def async_exists(self) -> bool:
|
|
155
|
+
"""Async check if the vector database exists"""
|
|
156
|
+
return False
|
|
157
|
+
|
|
158
|
+
def delete(self) -> bool:
|
|
159
|
+
"""Delete all documents from the vector database"""
|
|
160
|
+
return False
|
|
161
|
+
|
|
162
|
+
def delete_by_id(self, id: str) -> bool:
|
|
163
|
+
"""Delete documents by ID"""
|
|
164
|
+
return False
|
|
165
|
+
|
|
166
|
+
def delete_by_name(self, name: str) -> bool:
|
|
167
|
+
"""Delete documents by name"""
|
|
168
|
+
return False
|
|
169
|
+
|
|
170
|
+
def delete_by_metadata(self, metadata: Dict[str, Any]) -> bool:
|
|
171
|
+
"""Delete documents by metadata"""
|
|
172
|
+
return False
|
|
173
|
+
|
|
174
|
+
def delete_by_external_id(self, external_id: str) -> bool:
|
|
175
|
+
"""Delete documents by external ID (sync wrapper)"""
|
|
176
|
+
import asyncio
|
|
177
|
+
|
|
178
|
+
try:
|
|
179
|
+
return asyncio.run(self.async_delete_by_external_id(external_id))
|
|
180
|
+
except Exception as e:
|
|
181
|
+
log_error(f"Error in sync delete_by_external_id: {e}")
|
|
182
|
+
return False
|
|
183
|
+
|
|
184
|
+
async def async_delete_by_external_id(self, external_id: str) -> bool:
|
|
185
|
+
"""Delete documents by external ID"""
|
|
186
|
+
try:
|
|
187
|
+
payload = {"doc_ids": [external_id], "delete_file": False}
|
|
188
|
+
|
|
189
|
+
async with httpx.AsyncClient() as client:
|
|
190
|
+
response = await client.request(
|
|
191
|
+
method="DELETE",
|
|
192
|
+
url=f"{self.server_url}/documents/delete_document",
|
|
193
|
+
headers=self._get_headers(),
|
|
194
|
+
json=payload,
|
|
195
|
+
)
|
|
196
|
+
response.raise_for_status()
|
|
197
|
+
return True
|
|
198
|
+
except Exception as e:
|
|
199
|
+
log_error(f"Error deleting document {external_id}: {e}")
|
|
200
|
+
return False
|
|
201
|
+
|
|
202
|
+
# We use this method when content is coming from unsupported file types that LightRAG can't process
|
|
203
|
+
# For these we process the content in Agno and then insert it into LightRAG using text
|
|
204
|
+
async def _insert_text(self, text: str) -> Dict[str, Any]:
|
|
205
|
+
"""Insert text into the LightRAG server."""
|
|
206
|
+
|
|
207
|
+
async with httpx.AsyncClient() as client:
|
|
208
|
+
response = await client.post(
|
|
209
|
+
f"{self.server_url}/documents/text",
|
|
210
|
+
json={"text": text},
|
|
211
|
+
headers=self._get_headers(),
|
|
212
|
+
)
|
|
213
|
+
response.raise_for_status()
|
|
214
|
+
result = response.json()
|
|
215
|
+
log_debug(f"Text insertion result: {result}")
|
|
216
|
+
return result
|
|
217
|
+
|
|
218
|
+
async def insert_file_bytes(
|
|
219
|
+
self,
|
|
220
|
+
file_content: bytes,
|
|
221
|
+
filename: Optional[str] = None,
|
|
222
|
+
content_type: Optional[str] = None,
|
|
223
|
+
send_metadata: bool = False,
|
|
224
|
+
skip_if_exists: bool = False,
|
|
225
|
+
) -> Optional[str]:
|
|
226
|
+
"""Insert file from raw bytes into the LightRAG server."""
|
|
227
|
+
|
|
228
|
+
if not file_content:
|
|
229
|
+
log_warning("File content is empty.")
|
|
230
|
+
return None
|
|
231
|
+
|
|
232
|
+
if send_metadata and filename and content_type:
|
|
233
|
+
# Send with filename and content type (full UploadFile format)
|
|
234
|
+
files = {"file": (filename, file_content, content_type)}
|
|
235
|
+
else:
|
|
236
|
+
files = {"file": file_content} # type: ignore
|
|
237
|
+
|
|
238
|
+
async with httpx.AsyncClient() as client:
|
|
239
|
+
response = await client.post(
|
|
240
|
+
f"{self.server_url}/documents/upload",
|
|
241
|
+
files=files,
|
|
242
|
+
headers=self._get_auth_headers(),
|
|
243
|
+
)
|
|
244
|
+
response.raise_for_status()
|
|
245
|
+
result = response.json()
|
|
246
|
+
log_info(f"File insertion result: {result}")
|
|
247
|
+
track_id = result["track_id"]
|
|
248
|
+
log_info(f"Track ID: {track_id}")
|
|
249
|
+
result = await self._get_document_id(track_id) # type: ignore
|
|
250
|
+
log_info(f"Document ID: {result}")
|
|
251
|
+
|
|
252
|
+
return result
|
|
253
|
+
|
|
254
|
+
async def insert_text(self, file_source: str, text: str) -> Optional[str]:
|
|
255
|
+
"""Insert text into the LightRAG server."""
|
|
256
|
+
import httpx
|
|
257
|
+
|
|
258
|
+
async with httpx.AsyncClient() as client:
|
|
259
|
+
response = await client.post(
|
|
260
|
+
f"{self.server_url}/documents/text",
|
|
261
|
+
json={"file_source": file_source, "text": text},
|
|
262
|
+
headers=self._get_headers(),
|
|
263
|
+
)
|
|
264
|
+
response.raise_for_status()
|
|
265
|
+
result = response.json()
|
|
266
|
+
|
|
267
|
+
log_info(f"Text insertion result: {result}")
|
|
268
|
+
track_id = result["track_id"]
|
|
269
|
+
log_info(f"Track ID: {track_id}")
|
|
270
|
+
result = await self._get_document_id(track_id) # type: ignore
|
|
271
|
+
log_info(f"Document ID: {result}")
|
|
272
|
+
|
|
273
|
+
return result
|
|
274
|
+
|
|
275
|
+
async def _get_document_id(self, track_id: str) -> Optional[str]:
|
|
276
|
+
"""Get the document ID from the upload ID."""
|
|
277
|
+
async with httpx.AsyncClient() as client:
|
|
278
|
+
response = await client.get(
|
|
279
|
+
f"{self.server_url}/documents/track_status/{track_id}",
|
|
280
|
+
headers=self._get_headers(),
|
|
281
|
+
)
|
|
282
|
+
response.raise_for_status()
|
|
283
|
+
result = response.json()
|
|
284
|
+
|
|
285
|
+
log_debug(f"Document ID result: {result}")
|
|
286
|
+
|
|
287
|
+
# Extract document ID from the documents array
|
|
288
|
+
if "documents" in result and len(result["documents"]) > 0:
|
|
289
|
+
document_id = result["documents"][0]["id"]
|
|
290
|
+
return document_id
|
|
291
|
+
else:
|
|
292
|
+
log_error(f"No documents found in track response: {result}")
|
|
293
|
+
return None
|
|
294
|
+
|
|
295
|
+
def _is_valid_url(self, url: str) -> bool:
|
|
296
|
+
"""Helper to check if URL is valid."""
|
|
297
|
+
# TODO: Define supported extensions or implement proper URL validation
|
|
298
|
+
return True
|
|
299
|
+
|
|
300
|
+
async def lightrag_knowledge_retriever(
|
|
301
|
+
self,
|
|
302
|
+
query: str,
|
|
303
|
+
) -> Optional[List[Document]]:
|
|
304
|
+
"""
|
|
305
|
+
Custom knowledge retriever function to search the LightRAG server for relevant documents.
|
|
306
|
+
|
|
307
|
+
Args:
|
|
308
|
+
query: The search query string
|
|
309
|
+
num_documents: Number of documents to retrieve (currently unused by LightRAG)
|
|
310
|
+
mode: Query mode - "local", "global", or "hybrid"
|
|
311
|
+
lightrag_server_url: URL of the LightRAG server
|
|
312
|
+
|
|
313
|
+
Returns:
|
|
314
|
+
List of retrieved documents or None if search fails
|
|
315
|
+
"""
|
|
316
|
+
|
|
317
|
+
mode: str = "hybrid" # Default mode, can be "local", "global", or "hybrid"
|
|
318
|
+
|
|
319
|
+
try:
|
|
320
|
+
import httpx
|
|
321
|
+
|
|
322
|
+
async with httpx.AsyncClient(timeout=30.0) as client:
|
|
323
|
+
response = await client.post(
|
|
324
|
+
f"{self.server_url}/query",
|
|
325
|
+
json={"query": query, "mode": "hybrid"},
|
|
326
|
+
headers=self._get_headers(),
|
|
327
|
+
)
|
|
328
|
+
|
|
329
|
+
response.raise_for_status()
|
|
330
|
+
result = response.json()
|
|
331
|
+
|
|
332
|
+
return self._format_lightrag_response(result, query, mode)
|
|
333
|
+
|
|
334
|
+
except httpx.RequestError as e:
|
|
335
|
+
log_error(f"HTTP Request Error: {type(e).__name__}: {str(e)}")
|
|
336
|
+
return None
|
|
337
|
+
except httpx.HTTPStatusError as e:
|
|
338
|
+
log_error(f"HTTP Status Error: {e.response.status_code} - {e.response.text}")
|
|
339
|
+
return None
|
|
340
|
+
except Exception as e:
|
|
341
|
+
log_error(f"Unexpected error during LightRAG server search: {type(e).__name__}: {str(e)}")
|
|
342
|
+
import traceback
|
|
343
|
+
|
|
344
|
+
log_error(f"Full traceback: {traceback.format_exc()}")
|
|
345
|
+
return None
|
|
346
|
+
|
|
347
|
+
def _format_lightrag_response(self, result: Any, query: str, mode: str) -> List[Document]:
|
|
348
|
+
"""Format LightRAG server response to expected document format."""
|
|
349
|
+
# LightRAG server returns a dict with 'response' key, but we expect a list of documents
|
|
350
|
+
# Convert the response to the expected format
|
|
351
|
+
if isinstance(result, dict) and "response" in result:
|
|
352
|
+
# Wrap the response in a Document object
|
|
353
|
+
return [
|
|
354
|
+
Document(content=result["response"], meta_data={"source": "lightrag", "query": query, "mode": mode})
|
|
355
|
+
]
|
|
356
|
+
elif isinstance(result, list):
|
|
357
|
+
# Convert list items to Document objects
|
|
358
|
+
documents = []
|
|
359
|
+
for item in result:
|
|
360
|
+
if isinstance(item, dict) and "content" in item:
|
|
361
|
+
documents.append(
|
|
362
|
+
Document(
|
|
363
|
+
content=item["content"],
|
|
364
|
+
meta_data=item.get("metadata", {"source": "lightrag", "query": query, "mode": mode}),
|
|
365
|
+
)
|
|
366
|
+
)
|
|
367
|
+
else:
|
|
368
|
+
documents.append(
|
|
369
|
+
Document(content=str(item), meta_data={"source": "lightrag", "query": query, "mode": mode})
|
|
370
|
+
)
|
|
371
|
+
return documents
|
|
372
|
+
else:
|
|
373
|
+
# If it's a string or other format, wrap it in a Document
|
|
374
|
+
return [Document(content=str(result), meta_data={"source": "lightrag", "query": query, "mode": mode})]
|
|
375
|
+
|
|
376
|
+
def update_metadata(self, content_id: str, metadata: Dict[str, Any]) -> None:
|
|
377
|
+
"""
|
|
378
|
+
Update metadata is not supported for LightRag as it manages its own graph structure.
|
|
379
|
+
|
|
380
|
+
Args:
|
|
381
|
+
content_id (str): The content ID to update
|
|
382
|
+
metadata (Dict[str, Any]): The metadata to update
|
|
383
|
+
"""
|
|
384
|
+
raise NotImplementedError("update_metadata not supported for LightRag - use LightRag's native methods")
|
|
385
|
+
|
|
386
|
+
def get_supported_search_types(self) -> List[str]:
|
|
387
|
+
"""Get the supported search types for this vector database."""
|
|
388
|
+
return [] # LightRag doesn't use SearchType enum
|