agno 0.1.2__py3-none-any.whl → 2.3.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 +44 -5
- agno/agent/agent.py +10531 -2975
- agno/api/agent.py +14 -53
- agno/api/api.py +7 -46
- agno/api/evals.py +22 -0
- agno/api/os.py +17 -0
- agno/api/routes.py +6 -25
- agno/api/schemas/__init__.py +9 -0
- agno/api/schemas/agent.py +6 -9
- agno/api/schemas/evals.py +16 -0
- agno/api/schemas/os.py +14 -0
- agno/api/schemas/team.py +10 -10
- agno/api/schemas/utils.py +21 -0
- agno/api/schemas/workflows.py +16 -0
- agno/api/settings.py +53 -0
- agno/api/team.py +22 -26
- 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/compression/__init__.py +3 -0
- agno/compression/manager.py +247 -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 +946 -0
- agno/db/dynamo/__init__.py +3 -0
- agno/db/dynamo/dynamo.py +2781 -0
- agno/db/dynamo/schemas.py +442 -0
- agno/db/dynamo/utils.py +743 -0
- agno/db/firestore/__init__.py +3 -0
- agno/db/firestore/firestore.py +2379 -0
- agno/db/firestore/schemas.py +181 -0
- agno/db/firestore/utils.py +376 -0
- agno/db/gcs_json/__init__.py +3 -0
- agno/db/gcs_json/gcs_json_db.py +1791 -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 +1312 -0
- agno/db/in_memory/utils.py +230 -0
- agno/db/json/__init__.py +3 -0
- agno/db/json/json_db.py +1777 -0
- agno/db/json/utils.py +230 -0
- agno/db/migrations/manager.py +199 -0
- agno/db/migrations/v1_to_v2.py +635 -0
- agno/db/migrations/versions/v2_3_0.py +938 -0
- agno/db/mongo/__init__.py +17 -0
- agno/db/mongo/async_mongo.py +2760 -0
- agno/db/mongo/mongo.py +2597 -0
- agno/db/mongo/schemas.py +119 -0
- agno/db/mongo/utils.py +276 -0
- agno/db/mysql/__init__.py +4 -0
- agno/db/mysql/async_mysql.py +2912 -0
- agno/db/mysql/mysql.py +2923 -0
- agno/db/mysql/schemas.py +186 -0
- agno/db/mysql/utils.py +488 -0
- agno/db/postgres/__init__.py +4 -0
- agno/db/postgres/async_postgres.py +2579 -0
- agno/db/postgres/postgres.py +2870 -0
- agno/db/postgres/schemas.py +187 -0
- agno/db/postgres/utils.py +442 -0
- agno/db/redis/__init__.py +3 -0
- agno/db/redis/redis.py +2141 -0
- agno/db/redis/schemas.py +159 -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 +34 -0
- agno/db/schemas/knowledge.py +40 -0
- agno/db/schemas/memory.py +61 -0
- agno/db/singlestore/__init__.py +3 -0
- agno/db/singlestore/schemas.py +179 -0
- agno/db/singlestore/singlestore.py +2877 -0
- agno/db/singlestore/utils.py +384 -0
- agno/db/sqlite/__init__.py +4 -0
- agno/db/sqlite/async_sqlite.py +2911 -0
- agno/db/sqlite/schemas.py +181 -0
- agno/db/sqlite/sqlite.py +2908 -0
- agno/db/sqlite/utils.py +429 -0
- agno/db/surrealdb/__init__.py +3 -0
- agno/db/surrealdb/metrics.py +292 -0
- agno/db/surrealdb/models.py +334 -0
- agno/db/surrealdb/queries.py +71 -0
- agno/db/surrealdb/surrealdb.py +1908 -0
- agno/db/surrealdb/utils.py +147 -0
- agno/db/utils.py +118 -0
- agno/eval/__init__.py +24 -0
- agno/eval/accuracy.py +666 -276
- agno/eval/agent_as_judge.py +861 -0
- agno/eval/base.py +29 -0
- agno/eval/performance.py +779 -0
- agno/eval/reliability.py +241 -62
- agno/eval/utils.py +120 -0
- agno/exceptions.py +143 -1
- 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/hooks/__init__.py +3 -0
- agno/hooks/decorator.py +164 -0
- agno/integrations/discord/__init__.py +3 -0
- agno/integrations/discord/client.py +203 -0
- agno/knowledge/__init__.py +5 -1
- agno/{document → knowledge}/chunking/agentic.py +22 -14
- agno/{document → knowledge}/chunking/document.py +2 -2
- agno/{document → knowledge}/chunking/fixed.py +7 -6
- agno/knowledge/chunking/markdown.py +151 -0
- agno/{document → knowledge}/chunking/recursive.py +15 -3
- agno/knowledge/chunking/row.py +39 -0
- agno/knowledge/chunking/semantic.py +91 -0
- agno/knowledge/chunking/strategy.py +165 -0
- agno/knowledge/content.py +74 -0
- agno/knowledge/document/__init__.py +5 -0
- agno/{document → knowledge/document}/base.py +12 -2
- agno/knowledge/embedder/__init__.py +5 -0
- agno/knowledge/embedder/aws_bedrock.py +343 -0
- agno/knowledge/embedder/azure_openai.py +210 -0
- agno/{embedder → knowledge/embedder}/base.py +8 -0
- agno/knowledge/embedder/cohere.py +323 -0
- agno/knowledge/embedder/fastembed.py +62 -0
- agno/{embedder → knowledge/embedder}/fireworks.py +1 -1
- 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/{embedder → knowledge/embedder}/together.py +1 -1
- agno/knowledge/embedder/vllm.py +262 -0
- agno/knowledge/embedder/voyageai.py +165 -0
- agno/knowledge/knowledge.py +3006 -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 +164 -0
- agno/knowledge/reader/docx_reader.py +82 -0
- agno/knowledge/reader/field_labeled_csv_reader.py +290 -0
- agno/knowledge/reader/firecrawl_reader.py +201 -0
- agno/knowledge/reader/json_reader.py +88 -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 +193 -0
- agno/knowledge/reader/text_reader.py +127 -0
- agno/knowledge/reader/web_search_reader.py +325 -0
- agno/knowledge/reader/website_reader.py +455 -0
- agno/knowledge/reader/wikipedia_reader.py +91 -0
- agno/knowledge/reader/youtube_reader.py +78 -0
- agno/knowledge/remote_content/remote_content.py +88 -0
- agno/knowledge/reranker/__init__.py +3 -0
- agno/{reranker → knowledge/reranker}/base.py +1 -1
- agno/{reranker → knowledge/reranker}/cohere.py +2 -2
- 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 +234 -0
- agno/media.py +439 -95
- agno/memory/__init__.py +16 -3
- agno/memory/manager.py +1474 -123
- agno/memory/strategies/__init__.py +15 -0
- agno/memory/strategies/base.py +66 -0
- agno/memory/strategies/summarize.py +196 -0
- agno/memory/strategies/types.py +37 -0
- agno/models/aimlapi/__init__.py +5 -0
- agno/models/aimlapi/aimlapi.py +62 -0
- agno/models/anthropic/__init__.py +4 -0
- agno/models/anthropic/claude.py +960 -496
- agno/models/aws/__init__.py +15 -0
- agno/models/aws/bedrock.py +686 -451
- agno/models/aws/claude.py +190 -183
- agno/models/azure/__init__.py +18 -1
- agno/models/azure/ai_foundry.py +489 -0
- agno/models/azure/openai_chat.py +89 -40
- agno/models/base.py +2477 -550
- agno/models/cerebras/__init__.py +12 -0
- agno/models/cerebras/cerebras.py +565 -0
- agno/models/cerebras/cerebras_openai.py +131 -0
- agno/models/cohere/__init__.py +4 -0
- agno/models/cohere/chat.py +306 -492
- agno/models/cometapi/__init__.py +5 -0
- agno/models/cometapi/cometapi.py +74 -0
- agno/models/dashscope/__init__.py +5 -0
- agno/models/dashscope/dashscope.py +90 -0
- agno/models/deepinfra/__init__.py +5 -0
- agno/models/deepinfra/deepinfra.py +45 -0
- agno/models/deepseek/__init__.py +4 -0
- agno/models/deepseek/deepseek.py +110 -9
- agno/models/fireworks/__init__.py +4 -0
- agno/models/fireworks/fireworks.py +19 -22
- agno/models/google/__init__.py +3 -7
- agno/models/google/gemini.py +1717 -662
- agno/models/google/utils.py +22 -0
- agno/models/groq/__init__.py +4 -0
- agno/models/groq/groq.py +391 -666
- agno/models/huggingface/__init__.py +4 -0
- agno/models/huggingface/huggingface.py +266 -538
- agno/models/ibm/__init__.py +5 -0
- agno/models/ibm/watsonx.py +432 -0
- agno/models/internlm/__init__.py +3 -0
- agno/models/internlm/internlm.py +20 -3
- agno/models/langdb/__init__.py +1 -0
- agno/models/langdb/langdb.py +60 -0
- agno/models/litellm/__init__.py +14 -0
- agno/models/litellm/chat.py +503 -0
- agno/models/litellm/litellm_openai.py +42 -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 +361 -39
- agno/models/meta/__init__.py +12 -0
- agno/models/meta/llama.py +502 -0
- agno/models/meta/llama_openai.py +79 -0
- agno/models/metrics.py +120 -0
- agno/models/mistral/__init__.py +4 -0
- agno/models/mistral/mistral.py +293 -393
- agno/models/nebius/__init__.py +3 -0
- agno/models/nebius/nebius.py +53 -0
- agno/models/nexus/__init__.py +3 -0
- agno/models/nexus/nexus.py +22 -0
- agno/models/nvidia/__init__.py +4 -0
- agno/models/nvidia/nvidia.py +22 -3
- agno/models/ollama/__init__.py +4 -2
- agno/models/ollama/chat.py +257 -492
- agno/models/openai/__init__.py +7 -0
- agno/models/openai/chat.py +725 -770
- agno/models/openai/like.py +16 -2
- agno/models/openai/responses.py +1121 -0
- agno/models/openrouter/__init__.py +4 -0
- agno/models/openrouter/openrouter.py +62 -5
- agno/models/perplexity/__init__.py +5 -0
- agno/models/perplexity/perplexity.py +203 -0
- agno/models/portkey/__init__.py +3 -0
- agno/models/portkey/portkey.py +82 -0
- agno/models/requesty/__init__.py +5 -0
- agno/models/requesty/requesty.py +69 -0
- agno/models/response.py +177 -7
- agno/models/sambanova/__init__.py +4 -0
- agno/models/sambanova/sambanova.py +23 -4
- agno/models/siliconflow/__init__.py +5 -0
- agno/models/siliconflow/siliconflow.py +42 -0
- agno/models/together/__init__.py +4 -0
- agno/models/together/together.py +21 -164
- agno/models/utils.py +266 -0
- agno/models/vercel/__init__.py +3 -0
- agno/models/vercel/v0.py +43 -0
- agno/models/vertexai/__init__.py +0 -1
- agno/models/vertexai/claude.py +190 -0
- agno/models/vllm/__init__.py +3 -0
- agno/models/vllm/vllm.py +83 -0
- agno/models/xai/__init__.py +2 -0
- agno/models/xai/xai.py +111 -7
- agno/os/__init__.py +3 -0
- agno/os/app.py +1027 -0
- agno/os/auth.py +244 -0
- agno/os/config.py +126 -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 +249 -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 +147 -0
- agno/os/interfaces/agui/utils.py +574 -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 +210 -0
- agno/os/interfaces/whatsapp/security.py +55 -0
- agno/os/interfaces/whatsapp/whatsapp.py +36 -0
- agno/os/mcp.py +293 -0
- agno/os/middleware/__init__.py +9 -0
- agno/os/middleware/jwt.py +797 -0
- agno/os/router.py +258 -0
- agno/os/routers/__init__.py +3 -0
- agno/os/routers/agents/__init__.py +3 -0
- agno/os/routers/agents/router.py +599 -0
- agno/os/routers/agents/schema.py +261 -0
- agno/os/routers/evals/__init__.py +3 -0
- agno/os/routers/evals/evals.py +450 -0
- agno/os/routers/evals/schemas.py +174 -0
- agno/os/routers/evals/utils.py +231 -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 +1008 -0
- agno/os/routers/knowledge/schemas.py +178 -0
- agno/os/routers/memory/__init__.py +3 -0
- agno/os/routers/memory/memory.py +661 -0
- agno/os/routers/memory/schemas.py +88 -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/routers/teams/__init__.py +3 -0
- agno/os/routers/teams/router.py +512 -0
- agno/os/routers/teams/schema.py +257 -0
- agno/os/routers/traces/__init__.py +3 -0
- agno/os/routers/traces/schemas.py +414 -0
- agno/os/routers/traces/traces.py +499 -0
- agno/os/routers/workflows/__init__.py +3 -0
- agno/os/routers/workflows/router.py +624 -0
- agno/os/routers/workflows/schema.py +75 -0
- agno/os/schema.py +534 -0
- agno/os/scopes.py +469 -0
- agno/{playground → os}/settings.py +7 -15
- agno/os/utils.py +973 -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 +24 -1
- agno/reasoning/ollama.py +67 -0
- agno/reasoning/openai.py +86 -0
- agno/reasoning/step.py +2 -1
- agno/reasoning/vertexai.py +76 -0
- agno/run/__init__.py +6 -0
- agno/run/agent.py +822 -0
- agno/run/base.py +247 -0
- agno/run/cancel.py +81 -0
- agno/run/requirement.py +181 -0
- agno/run/team.py +767 -0
- agno/run/workflow.py +708 -0
- agno/session/__init__.py +10 -0
- agno/session/agent.py +260 -0
- agno/session/summary.py +265 -0
- agno/session/team.py +342 -0
- agno/session/workflow.py +501 -0
- agno/table.py +10 -0
- agno/team/__init__.py +37 -0
- agno/team/team.py +9536 -0
- agno/tools/__init__.py +7 -0
- agno/tools/agentql.py +120 -0
- agno/tools/airflow.py +22 -12
- agno/tools/api.py +122 -0
- agno/tools/apify.py +276 -83
- agno/tools/{arxiv_toolkit.py → arxiv.py} +20 -12
- agno/tools/aws_lambda.py +28 -7
- agno/tools/aws_ses.py +66 -0
- agno/tools/baidusearch.py +11 -4
- 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 +32 -23
- agno/tools/calculator.py +24 -37
- agno/tools/cartesia.py +187 -0
- agno/tools/{clickup_tool.py → clickup.py} +17 -28
- agno/tools/confluence.py +91 -26
- agno/tools/crawl4ai.py +139 -43
- agno/tools/csv_toolkit.py +28 -22
- agno/tools/dalle.py +36 -22
- agno/tools/daytona.py +475 -0
- agno/tools/decorator.py +169 -14
- agno/tools/desi_vocal.py +23 -11
- agno/tools/discord.py +32 -29
- agno/tools/docker.py +716 -0
- agno/tools/duckdb.py +76 -81
- agno/tools/duckduckgo.py +43 -40
- agno/tools/e2b.py +703 -0
- agno/tools/eleven_labs.py +65 -54
- agno/tools/email.py +13 -5
- agno/tools/evm.py +129 -0
- agno/tools/exa.py +324 -42
- agno/tools/fal.py +39 -35
- agno/tools/file.py +196 -30
- agno/tools/file_generation.py +356 -0
- agno/tools/financial_datasets.py +288 -0
- agno/tools/firecrawl.py +108 -33
- agno/tools/function.py +960 -122
- agno/tools/giphy.py +34 -12
- agno/tools/github.py +1294 -97
- agno/tools/gmail.py +922 -0
- agno/tools/google_bigquery.py +117 -0
- agno/tools/google_drive.py +271 -0
- agno/tools/google_maps.py +253 -0
- agno/tools/googlecalendar.py +607 -107
- agno/tools/googlesheets.py +377 -0
- agno/tools/hackernews.py +20 -12
- agno/tools/jina.py +24 -14
- agno/tools/jira.py +48 -19
- agno/tools/knowledge.py +218 -0
- agno/tools/linear.py +82 -43
- agno/tools/linkup.py +58 -0
- agno/tools/local_file_system.py +15 -7
- agno/tools/lumalab.py +41 -26
- 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/memory.py +419 -0
- agno/tools/mlx_transcribe.py +11 -9
- 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 +163 -82
- agno/tools/moviepy_video.py +18 -13
- agno/tools/nano_banana.py +151 -0
- agno/tools/neo4j.py +134 -0
- agno/tools/newspaper.py +15 -4
- agno/tools/newspaper4k.py +19 -6
- agno/tools/notion.py +204 -0
- agno/tools/openai.py +181 -17
- agno/tools/openbb.py +27 -20
- agno/tools/opencv.py +321 -0
- agno/tools/openweather.py +233 -0
- agno/tools/oxylabs.py +385 -0
- agno/tools/pandas.py +25 -15
- agno/tools/parallel.py +314 -0
- agno/tools/postgres.py +238 -185
- agno/tools/pubmed.py +125 -13
- agno/tools/python.py +48 -35
- agno/tools/reasoning.py +283 -0
- agno/tools/reddit.py +207 -29
- agno/tools/redshift.py +406 -0
- agno/tools/replicate.py +69 -26
- agno/tools/resend.py +11 -6
- agno/tools/scrapegraph.py +179 -19
- agno/tools/searxng.py +23 -31
- agno/tools/serpapi.py +15 -10
- agno/tools/serper.py +255 -0
- agno/tools/shell.py +23 -12
- agno/tools/shopify.py +1519 -0
- agno/tools/slack.py +56 -14
- agno/tools/sleep.py +8 -6
- agno/tools/spider.py +35 -11
- agno/tools/spotify.py +919 -0
- agno/tools/sql.py +34 -19
- agno/tools/tavily.py +158 -8
- agno/tools/telegram.py +18 -8
- agno/tools/todoist.py +218 -0
- agno/tools/toolkit.py +134 -9
- agno/tools/trafilatura.py +388 -0
- agno/tools/trello.py +25 -28
- agno/tools/twilio.py +18 -9
- 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 +23 -19
- agno/tools/webtools.py +45 -0
- agno/tools/whatsapp.py +286 -0
- agno/tools/wikipedia.py +28 -19
- agno/tools/workflow.py +285 -0
- agno/tools/{twitter.py → x.py} +142 -46
- agno/tools/yfinance.py +41 -39
- agno/tools/youtube.py +34 -17
- agno/tools/zendesk.py +15 -5
- agno/tools/zep.py +454 -0
- agno/tools/zoom.py +86 -37
- agno/tracing/__init__.py +12 -0
- agno/tracing/exporter.py +157 -0
- agno/tracing/schemas.py +276 -0
- agno/tracing/setup.py +111 -0
- agno/utils/agent.py +938 -0
- agno/utils/audio.py +37 -1
- agno/utils/certs.py +27 -0
- agno/utils/code_execution.py +11 -0
- agno/utils/common.py +103 -20
- agno/utils/cryptography.py +22 -0
- agno/utils/dttm.py +33 -0
- agno/utils/events.py +700 -0
- agno/utils/functions.py +107 -37
- agno/utils/gemini.py +426 -0
- agno/utils/hooks.py +171 -0
- agno/utils/http.py +185 -0
- agno/utils/json_schema.py +159 -37
- agno/utils/knowledge.py +36 -0
- agno/utils/location.py +19 -0
- agno/utils/log.py +221 -8
- agno/utils/mcp.py +214 -0
- agno/utils/media.py +335 -14
- agno/utils/merge_dict.py +22 -1
- agno/utils/message.py +77 -2
- agno/utils/models/ai_foundry.py +50 -0
- agno/utils/models/claude.py +373 -0
- agno/utils/models/cohere.py +94 -0
- agno/utils/models/llama.py +85 -0
- agno/utils/models/mistral.py +100 -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 +1 -1
- agno/utils/pprint.py +124 -8
- agno/utils/print_response/agent.py +930 -0
- agno/utils/print_response/team.py +1914 -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/serialize.py +32 -0
- agno/utils/shell.py +4 -4
- agno/utils/streamlit.py +487 -0
- agno/utils/string.py +204 -51
- agno/utils/team.py +139 -0
- agno/utils/timer.py +9 -2
- agno/utils/tokens.py +657 -0
- agno/utils/tools.py +19 -1
- agno/utils/whatsapp.py +305 -0
- agno/utils/yaml_io.py +3 -3
- agno/vectordb/__init__.py +2 -0
- agno/vectordb/base.py +87 -9
- agno/vectordb/cassandra/__init__.py +5 -1
- agno/vectordb/cassandra/cassandra.py +383 -27
- agno/vectordb/chroma/__init__.py +4 -0
- agno/vectordb/chroma/chromadb.py +748 -83
- agno/vectordb/clickhouse/__init__.py +7 -1
- agno/vectordb/clickhouse/clickhousedb.py +554 -53
- agno/vectordb/couchbase/__init__.py +3 -0
- agno/vectordb/couchbase/couchbase.py +1446 -0
- agno/vectordb/lancedb/__init__.py +5 -0
- agno/vectordb/lancedb/lance_db.py +730 -98
- 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 +3 -0
- agno/vectordb/milvus/milvus.py +966 -78
- agno/vectordb/mongodb/__init__.py +9 -1
- agno/vectordb/mongodb/mongodb.py +1175 -172
- agno/vectordb/pgvector/__init__.py +8 -0
- agno/vectordb/pgvector/pgvector.py +599 -115
- agno/vectordb/pineconedb/__init__.py +5 -1
- agno/vectordb/pineconedb/pineconedb.py +406 -43
- agno/vectordb/qdrant/__init__.py +4 -0
- agno/vectordb/qdrant/qdrant.py +914 -61
- agno/vectordb/redis/__init__.py +9 -0
- agno/vectordb/redis/redisdb.py +682 -0
- agno/vectordb/singlestore/__init__.py +8 -1
- agno/vectordb/singlestore/singlestore.py +771 -0
- agno/vectordb/surrealdb/__init__.py +3 -0
- agno/vectordb/surrealdb/surrealdb.py +663 -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 +1009 -0
- agno/workflow/__init__.py +23 -1
- agno/workflow/agent.py +299 -0
- agno/workflow/condition.py +759 -0
- agno/workflow/loop.py +756 -0
- agno/workflow/parallel.py +853 -0
- agno/workflow/router.py +723 -0
- agno/workflow/step.py +1564 -0
- agno/workflow/steps.py +613 -0
- agno/workflow/types.py +556 -0
- agno/workflow/workflow.py +4327 -514
- agno-2.3.13.dist-info/METADATA +639 -0
- agno-2.3.13.dist-info/RECORD +613 -0
- {agno-0.1.2.dist-info → agno-2.3.13.dist-info}/WHEEL +1 -1
- agno-2.3.13.dist-info/licenses/LICENSE +201 -0
- agno/api/playground.py +0 -91
- agno/api/schemas/playground.py +0 -22
- agno/api/schemas/user.py +0 -22
- agno/api/schemas/workspace.py +0 -46
- agno/api/user.py +0 -160
- agno/api/workspace.py +0 -151
- agno/cli/auth_server.py +0 -118
- agno/cli/config.py +0 -275
- agno/cli/console.py +0 -88
- agno/cli/credentials.py +0 -23
- agno/cli/entrypoint.py +0 -571
- agno/cli/operator.py +0 -355
- agno/cli/settings.py +0 -85
- agno/cli/ws/ws_cli.py +0 -817
- agno/constants.py +0 -13
- agno/document/__init__.py +0 -1
- agno/document/chunking/semantic.py +0 -47
- agno/document/chunking/strategy.py +0 -31
- agno/document/reader/__init__.py +0 -1
- agno/document/reader/arxiv_reader.py +0 -41
- agno/document/reader/base.py +0 -22
- agno/document/reader/csv_reader.py +0 -84
- agno/document/reader/docx_reader.py +0 -46
- agno/document/reader/firecrawl_reader.py +0 -99
- agno/document/reader/json_reader.py +0 -43
- agno/document/reader/pdf_reader.py +0 -219
- agno/document/reader/s3/pdf_reader.py +0 -46
- agno/document/reader/s3/text_reader.py +0 -51
- agno/document/reader/text_reader.py +0 -41
- agno/document/reader/website_reader.py +0 -175
- agno/document/reader/youtube_reader.py +0 -50
- agno/embedder/__init__.py +0 -1
- agno/embedder/azure_openai.py +0 -86
- agno/embedder/cohere.py +0 -72
- agno/embedder/fastembed.py +0 -37
- agno/embedder/google.py +0 -73
- agno/embedder/huggingface.py +0 -54
- agno/embedder/mistral.py +0 -80
- agno/embedder/ollama.py +0 -57
- agno/embedder/openai.py +0 -74
- agno/embedder/sentence_transformer.py +0 -38
- agno/embedder/voyageai.py +0 -64
- agno/eval/perf.py +0 -201
- agno/file/__init__.py +0 -1
- agno/file/file.py +0 -16
- agno/file/local/csv.py +0 -32
- agno/file/local/txt.py +0 -19
- agno/infra/app.py +0 -240
- agno/infra/base.py +0 -144
- agno/infra/context.py +0 -20
- agno/infra/db_app.py +0 -52
- agno/infra/resource.py +0 -205
- agno/infra/resources.py +0 -55
- agno/knowledge/agent.py +0 -230
- agno/knowledge/arxiv.py +0 -22
- agno/knowledge/combined.py +0 -22
- agno/knowledge/csv.py +0 -28
- agno/knowledge/csv_url.py +0 -19
- agno/knowledge/document.py +0 -20
- agno/knowledge/docx.py +0 -30
- agno/knowledge/json.py +0 -28
- agno/knowledge/langchain.py +0 -71
- agno/knowledge/llamaindex.py +0 -66
- agno/knowledge/pdf.py +0 -28
- agno/knowledge/pdf_url.py +0 -26
- agno/knowledge/s3/base.py +0 -60
- agno/knowledge/s3/pdf.py +0 -21
- agno/knowledge/s3/text.py +0 -23
- agno/knowledge/text.py +0 -30
- agno/knowledge/website.py +0 -88
- agno/knowledge/wikipedia.py +0 -31
- agno/knowledge/youtube.py +0 -22
- agno/memory/agent.py +0 -392
- agno/memory/classifier.py +0 -104
- agno/memory/db/__init__.py +0 -1
- agno/memory/db/base.py +0 -42
- agno/memory/db/mongodb.py +0 -189
- agno/memory/db/postgres.py +0 -203
- agno/memory/db/sqlite.py +0 -193
- agno/memory/memory.py +0 -15
- agno/memory/row.py +0 -36
- agno/memory/summarizer.py +0 -192
- agno/memory/summary.py +0 -19
- agno/memory/workflow.py +0 -38
- agno/models/google/gemini_openai.py +0 -26
- agno/models/ollama/hermes.py +0 -221
- agno/models/ollama/tools.py +0 -362
- agno/models/vertexai/gemini.py +0 -595
- agno/playground/__init__.py +0 -3
- agno/playground/async_router.py +0 -421
- agno/playground/deploy.py +0 -249
- agno/playground/operator.py +0 -92
- agno/playground/playground.py +0 -91
- agno/playground/schemas.py +0 -76
- agno/playground/serve.py +0 -55
- agno/playground/sync_router.py +0 -405
- agno/reasoning/agent.py +0 -68
- agno/run/response.py +0 -112
- agno/storage/agent/__init__.py +0 -0
- agno/storage/agent/base.py +0 -38
- agno/storage/agent/dynamodb.py +0 -350
- agno/storage/agent/json.py +0 -92
- agno/storage/agent/mongodb.py +0 -228
- agno/storage/agent/postgres.py +0 -367
- agno/storage/agent/session.py +0 -79
- agno/storage/agent/singlestore.py +0 -303
- agno/storage/agent/sqlite.py +0 -357
- agno/storage/agent/yaml.py +0 -93
- agno/storage/workflow/__init__.py +0 -0
- agno/storage/workflow/base.py +0 -40
- agno/storage/workflow/mongodb.py +0 -233
- agno/storage/workflow/postgres.py +0 -366
- agno/storage/workflow/session.py +0 -60
- agno/storage/workflow/sqlite.py +0 -359
- agno/tools/googlesearch.py +0 -88
- agno/utils/defaults.py +0 -57
- agno/utils/filesystem.py +0 -39
- agno/utils/git.py +0 -52
- agno/utils/json_io.py +0 -30
- agno/utils/load_env.py +0 -19
- agno/utils/py_io.py +0 -19
- agno/utils/pyproject.py +0 -18
- agno/utils/resource_filter.py +0 -31
- agno/vectordb/singlestore/s2vectordb.py +0 -390
- agno/vectordb/singlestore/s2vectordb2.py +0 -355
- agno/workspace/__init__.py +0 -0
- agno/workspace/config.py +0 -325
- agno/workspace/enums.py +0 -6
- agno/workspace/helpers.py +0 -48
- agno/workspace/operator.py +0 -758
- agno/workspace/settings.py +0 -63
- agno-0.1.2.dist-info/LICENSE +0 -375
- agno-0.1.2.dist-info/METADATA +0 -502
- agno-0.1.2.dist-info/RECORD +0 -352
- agno-0.1.2.dist-info/entry_points.txt +0 -3
- /agno/{cli → db/migrations}/__init__.py +0 -0
- /agno/{cli/ws → db/migrations/versions}/__init__.py +0 -0
- /agno/{document/chunking/__init__.py → db/schemas/metrics.py} +0 -0
- /agno/{document/reader/s3 → integrations}/__init__.py +0 -0
- /agno/{file/local → knowledge/chunking}/__init__.py +0 -0
- /agno/{infra → knowledge/remote_content}/__init__.py +0 -0
- /agno/{knowledge/s3 → tools/models}/__init__.py +0 -0
- /agno/{reranker → utils/models}/__init__.py +0 -0
- /agno/{storage → utils/print_response}/__init__.py +0 -0
- {agno-0.1.2.dist-info → agno-2.3.13.dist-info}/top_level.txt +0 -0
agno/tools/scrapegraph.py
CHANGED
|
@@ -1,62 +1,222 @@
|
|
|
1
1
|
import json
|
|
2
|
-
import
|
|
3
|
-
from typing import Optional
|
|
2
|
+
from os import getenv
|
|
3
|
+
from typing import Any, List, Optional
|
|
4
4
|
|
|
5
5
|
from agno.tools import Toolkit
|
|
6
|
+
from agno.utils.log import log_debug, log_error
|
|
6
7
|
|
|
7
8
|
try:
|
|
8
9
|
from scrapegraph_py import Client
|
|
10
|
+
from scrapegraph_py.logger import sgai_logger
|
|
9
11
|
except ImportError:
|
|
10
12
|
raise ImportError("`scrapegraph-py` not installed. Please install using `pip install scrapegraph-py`")
|
|
11
13
|
|
|
14
|
+
# Set logging level
|
|
15
|
+
sgai_logger.set_logging(level="INFO")
|
|
16
|
+
|
|
12
17
|
|
|
13
18
|
class ScrapeGraphTools(Toolkit):
|
|
14
19
|
def __init__(
|
|
15
20
|
self,
|
|
16
21
|
api_key: Optional[str] = None,
|
|
17
|
-
|
|
18
|
-
|
|
22
|
+
enable_smartscraper: bool = True,
|
|
23
|
+
enable_markdownify: bool = False,
|
|
24
|
+
enable_crawl: bool = False,
|
|
25
|
+
enable_searchscraper: bool = False,
|
|
26
|
+
enable_agentic_crawler: bool = False,
|
|
27
|
+
enable_scrape: bool = False,
|
|
28
|
+
render_heavy_js: bool = False,
|
|
29
|
+
all: bool = False,
|
|
30
|
+
**kwargs,
|
|
19
31
|
):
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
self.api_key: Optional[str] = api_key or os.getenv("SGAI_API_KEY")
|
|
32
|
+
self.api_key: Optional[str] = api_key or getenv("SGAI_API_KEY")
|
|
23
33
|
self.client = Client(api_key=self.api_key)
|
|
34
|
+
self.render_heavy_js = render_heavy_js
|
|
24
35
|
|
|
25
36
|
# Start with smartscraper by default
|
|
26
37
|
# Only enable markdownify if smartscraper is False
|
|
27
|
-
if not
|
|
28
|
-
|
|
38
|
+
if not enable_smartscraper and not all:
|
|
39
|
+
enable_markdownify = True
|
|
40
|
+
|
|
41
|
+
tools: List[Any] = []
|
|
42
|
+
if enable_smartscraper or all:
|
|
43
|
+
tools.append(self.smartscraper)
|
|
44
|
+
if enable_markdownify or all:
|
|
45
|
+
tools.append(self.markdownify)
|
|
46
|
+
if enable_crawl or all:
|
|
47
|
+
tools.append(self.crawl)
|
|
48
|
+
if enable_searchscraper or all:
|
|
49
|
+
tools.append(self.searchscraper)
|
|
50
|
+
if enable_agentic_crawler or all:
|
|
51
|
+
tools.append(self.agentic_crawler)
|
|
52
|
+
if enable_scrape or all:
|
|
53
|
+
tools.append(self.scrape)
|
|
29
54
|
|
|
30
|
-
|
|
31
|
-
self.register(self.smartscraper)
|
|
32
|
-
if markdownify:
|
|
33
|
-
self.register(self.markdownify)
|
|
55
|
+
super().__init__(name="scrapegraph_tools", tools=tools, **kwargs)
|
|
34
56
|
|
|
35
57
|
def smartscraper(self, url: str, prompt: str) -> str:
|
|
36
|
-
"""
|
|
58
|
+
"""Extract structured data from a webpage using LLM.
|
|
37
59
|
Args:
|
|
38
60
|
url (str): The URL to scrape
|
|
39
61
|
prompt (str): Natural language prompt describing what to extract
|
|
40
62
|
Returns:
|
|
41
63
|
The structured data extracted from the webpage
|
|
42
64
|
"""
|
|
43
|
-
|
|
44
65
|
try:
|
|
66
|
+
log_debug(f"ScrapeGraph smartscraper request for URL: {url}")
|
|
45
67
|
response = self.client.smartscraper(website_url=url, user_prompt=prompt)
|
|
46
68
|
return json.dumps(response["result"])
|
|
47
69
|
except Exception as e:
|
|
48
|
-
|
|
70
|
+
error_msg = f"Smartscraper failed: {str(e)}"
|
|
71
|
+
log_error(error_msg)
|
|
72
|
+
return f"Error: {error_msg}"
|
|
49
73
|
|
|
50
74
|
def markdownify(self, url: str) -> str:
|
|
51
|
-
"""
|
|
75
|
+
"""Convert a webpage to markdown format.
|
|
52
76
|
Args:
|
|
53
77
|
url (str): The URL to convert
|
|
54
78
|
Returns:
|
|
55
79
|
The markdown version of the webpage
|
|
56
80
|
"""
|
|
57
|
-
|
|
58
81
|
try:
|
|
82
|
+
log_debug(f"ScrapeGraph markdownify request for URL: {url}")
|
|
59
83
|
response = self.client.markdownify(website_url=url)
|
|
60
84
|
return response["result"]
|
|
61
85
|
except Exception as e:
|
|
62
|
-
|
|
86
|
+
error_msg = f"Markdownify failed: {str(e)}"
|
|
87
|
+
log_error(error_msg)
|
|
88
|
+
return f"Error: {error_msg}"
|
|
89
|
+
|
|
90
|
+
def crawl(
|
|
91
|
+
self,
|
|
92
|
+
url: str,
|
|
93
|
+
prompt: str,
|
|
94
|
+
schema: dict,
|
|
95
|
+
cache_website: bool = True,
|
|
96
|
+
depth: int = 2,
|
|
97
|
+
max_pages: int = 2,
|
|
98
|
+
same_domain_only: bool = True,
|
|
99
|
+
batch_size: int = 1,
|
|
100
|
+
) -> str:
|
|
101
|
+
"""Crawl a website and extract structured data
|
|
102
|
+
Args:
|
|
103
|
+
url (str): The URL to crawl
|
|
104
|
+
prompt (str): Natural language prompt describing what to extract
|
|
105
|
+
schema (dict): JSON schema for extraction
|
|
106
|
+
cache_website (bool): Whether to cache the website
|
|
107
|
+
depth (int): Crawl depth
|
|
108
|
+
max_pages (int): Max number of pages to crawl
|
|
109
|
+
same_domain_only (bool): Restrict to same domain
|
|
110
|
+
batch_size (int): Batch size for crawling
|
|
111
|
+
Returns:
|
|
112
|
+
The structured data extracted from the website
|
|
113
|
+
"""
|
|
114
|
+
try:
|
|
115
|
+
log_debug(f"ScrapeGraph crawl request for URL: {url}")
|
|
116
|
+
response = self.client.crawl(
|
|
117
|
+
url=url,
|
|
118
|
+
prompt=prompt,
|
|
119
|
+
data_schema=schema,
|
|
120
|
+
cache_website=cache_website,
|
|
121
|
+
depth=depth,
|
|
122
|
+
max_pages=max_pages,
|
|
123
|
+
same_domain_only=same_domain_only,
|
|
124
|
+
batch_size=batch_size,
|
|
125
|
+
)
|
|
126
|
+
return json.dumps(response, indent=2)
|
|
127
|
+
except Exception as e:
|
|
128
|
+
error_msg = f"Crawl failed: {str(e)}"
|
|
129
|
+
log_error(error_msg)
|
|
130
|
+
return f"Error: {error_msg}"
|
|
131
|
+
|
|
132
|
+
def agentic_crawler(
|
|
133
|
+
self,
|
|
134
|
+
url: str,
|
|
135
|
+
steps: List[str],
|
|
136
|
+
use_session: bool = True,
|
|
137
|
+
user_prompt: Optional[str] = None,
|
|
138
|
+
output_schema: Optional[dict] = None,
|
|
139
|
+
ai_extraction: bool = False,
|
|
140
|
+
) -> str:
|
|
141
|
+
"""Perform agentic crawling with automated browser actions and optional AI extraction.
|
|
142
|
+
|
|
143
|
+
This tool can:
|
|
144
|
+
1. Navigate to a website
|
|
145
|
+
2. Perform a series of automated actions (like filling forms, clicking buttons)
|
|
146
|
+
3. Extract the resulting HTML content as markdown
|
|
147
|
+
4. Optionally use AI to extract structured data
|
|
148
|
+
|
|
149
|
+
Args:
|
|
150
|
+
url (str): The URL to scrape
|
|
151
|
+
steps (List[str]): List of steps to perform on the webpage (e.g., ["Type email in input box", "click login"])
|
|
152
|
+
use_session (bool): Whether to use session for the scraping (default: True)
|
|
153
|
+
user_prompt (Optional[str]): Prompt for AI extraction (only used when ai_extraction=True)
|
|
154
|
+
output_schema (Optional[dict]): Schema for structured data extraction (only used when ai_extraction=True)
|
|
155
|
+
ai_extraction (bool): Whether to use AI for data extraction from the scraped content (default: False)
|
|
156
|
+
|
|
157
|
+
Returns:
|
|
158
|
+
JSON string containing the scraping results, including request_id, status, and extracted data
|
|
159
|
+
"""
|
|
160
|
+
try:
|
|
161
|
+
log_debug(f"ScrapeGraph agentic_crawler request for URL: {url}")
|
|
162
|
+
|
|
163
|
+
# Prepare parameters for the API call
|
|
164
|
+
params = {"url": url, "steps": steps, "use_session": use_session, "ai_extraction": ai_extraction}
|
|
165
|
+
|
|
166
|
+
# Add optional parameters only if they are provided
|
|
167
|
+
if user_prompt:
|
|
168
|
+
params["user_prompt"] = user_prompt
|
|
169
|
+
if output_schema:
|
|
170
|
+
params["output_schema"] = output_schema
|
|
171
|
+
|
|
172
|
+
# Call the agentic scraper API
|
|
173
|
+
response = self.client.agenticscraper(**params)
|
|
174
|
+
return json.dumps(response, indent=2)
|
|
175
|
+
|
|
176
|
+
except Exception as e:
|
|
177
|
+
error_msg = f"Agentic crawler failed: {str(e)}"
|
|
178
|
+
log_error(error_msg)
|
|
179
|
+
return f"Error: {error_msg}"
|
|
180
|
+
|
|
181
|
+
def searchscraper(self, user_prompt: str) -> str:
|
|
182
|
+
"""Search the web and extract information from the web.
|
|
183
|
+
Args:
|
|
184
|
+
user_prompt (str): Search query
|
|
185
|
+
Returns:
|
|
186
|
+
JSON of the search results
|
|
187
|
+
"""
|
|
188
|
+
try:
|
|
189
|
+
log_debug(f"ScrapeGraph searchscraper request with prompt: {user_prompt}")
|
|
190
|
+
response = self.client.searchscraper(user_prompt=user_prompt)
|
|
191
|
+
return json.dumps(response["result"])
|
|
192
|
+
except Exception as e:
|
|
193
|
+
error_msg = f"Searchscraper failed: {str(e)}"
|
|
194
|
+
log_error(error_msg)
|
|
195
|
+
return f"Error: {error_msg}"
|
|
196
|
+
|
|
197
|
+
def scrape(
|
|
198
|
+
self,
|
|
199
|
+
website_url: str,
|
|
200
|
+
headers: Optional[dict] = None,
|
|
201
|
+
) -> str:
|
|
202
|
+
"""Get raw HTML content from a website using the ScrapeGraphAI scrape API.
|
|
203
|
+
|
|
204
|
+
Args:
|
|
205
|
+
website_url (str): The URL of the website to scrape
|
|
206
|
+
headers (Optional[dict]): Optional headers to send with the request
|
|
207
|
+
|
|
208
|
+
Returns:
|
|
209
|
+
JSON string containing the HTML content and metadata
|
|
210
|
+
"""
|
|
211
|
+
try:
|
|
212
|
+
log_debug(f"ScrapeGraph scrape request for URL: {website_url}")
|
|
213
|
+
response = self.client.scrape(
|
|
214
|
+
website_url=website_url,
|
|
215
|
+
headers=headers,
|
|
216
|
+
render_heavy_js=self.render_heavy_js,
|
|
217
|
+
)
|
|
218
|
+
return json.dumps(response, indent=2)
|
|
219
|
+
except Exception as e:
|
|
220
|
+
error_msg = f"Scrape failed: {str(e)}"
|
|
221
|
+
log_error(error_msg)
|
|
222
|
+
return f"Error: {error_msg}"
|
agno/tools/searxng.py
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import json
|
|
2
2
|
import urllib.parse
|
|
3
|
-
from typing import List, Optional
|
|
3
|
+
from typing import Any, List, Optional
|
|
4
4
|
|
|
5
5
|
import httpx
|
|
6
6
|
|
|
7
|
-
from agno.tools
|
|
8
|
-
from agno.utils.log import
|
|
7
|
+
from agno.tools import Toolkit
|
|
8
|
+
from agno.utils.log import log_info
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
class Searxng(Toolkit):
|
|
@@ -14,38 +14,26 @@ class Searxng(Toolkit):
|
|
|
14
14
|
host: str,
|
|
15
15
|
engines: List[str] = [],
|
|
16
16
|
fixed_max_results: Optional[int] = None,
|
|
17
|
-
|
|
18
|
-
it: bool = False,
|
|
19
|
-
map: bool = False,
|
|
20
|
-
music: bool = False,
|
|
21
|
-
news: bool = False,
|
|
22
|
-
science: bool = False,
|
|
23
|
-
videos: bool = False,
|
|
17
|
+
**kwargs,
|
|
24
18
|
):
|
|
25
|
-
super().__init__(name="searxng")
|
|
26
|
-
|
|
27
19
|
self.host = host
|
|
28
20
|
self.engines = engines
|
|
29
21
|
self.fixed_max_results = fixed_max_results
|
|
30
22
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
self.
|
|
35
|
-
|
|
36
|
-
self.
|
|
37
|
-
|
|
38
|
-
self.
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
if videos:
|
|
46
|
-
self.register(self.video_search)
|
|
47
|
-
|
|
48
|
-
def search(self, query: str, max_results: int = 5) -> str:
|
|
23
|
+
tools: List[Any] = [
|
|
24
|
+
self.search_web,
|
|
25
|
+
self.image_search,
|
|
26
|
+
self.it_search,
|
|
27
|
+
self.map_search,
|
|
28
|
+
self.music_search,
|
|
29
|
+
self.news_search,
|
|
30
|
+
self.science_search,
|
|
31
|
+
self.video_search,
|
|
32
|
+
]
|
|
33
|
+
|
|
34
|
+
super().__init__(name="searxng", tools=tools, **kwargs)
|
|
35
|
+
|
|
36
|
+
def search_web(self, query: str, max_results: int = 5) -> str:
|
|
49
37
|
"""Use this function to search the web.
|
|
50
38
|
|
|
51
39
|
Args:
|
|
@@ -150,7 +138,7 @@ class Searxng(Toolkit):
|
|
|
150
138
|
if category:
|
|
151
139
|
url += f"&categories={category}"
|
|
152
140
|
|
|
153
|
-
|
|
141
|
+
log_info(f"Fetching results from searxng: {url}")
|
|
154
142
|
try:
|
|
155
143
|
resp = httpx.get(url).json()
|
|
156
144
|
results = self.fixed_max_results or max_results
|
|
@@ -158,3 +146,7 @@ class Searxng(Toolkit):
|
|
|
158
146
|
return json.dumps(resp)
|
|
159
147
|
except Exception as e:
|
|
160
148
|
return f"Error fetching results from searxng: {e}"
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
# Alias for consistency with other tools
|
|
152
|
+
SearxngTools = Searxng
|
agno/tools/serpapi.py
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import json
|
|
2
2
|
from os import getenv
|
|
3
|
-
from typing import Optional
|
|
3
|
+
from typing import Any, List, Optional
|
|
4
4
|
|
|
5
5
|
from agno.tools import Toolkit
|
|
6
|
-
from agno.utils.log import logger
|
|
6
|
+
from agno.utils.log import log_info, logger
|
|
7
7
|
|
|
8
8
|
try:
|
|
9
9
|
import serpapi
|
|
@@ -15,17 +15,22 @@ class SerpApiTools(Toolkit):
|
|
|
15
15
|
def __init__(
|
|
16
16
|
self,
|
|
17
17
|
api_key: Optional[str] = None,
|
|
18
|
-
|
|
18
|
+
enable_search_google: bool = True,
|
|
19
|
+
enable_search_youtube: bool = False,
|
|
20
|
+
all: bool = False,
|
|
21
|
+
**kwargs,
|
|
19
22
|
):
|
|
20
|
-
super().__init__(name="serpapi_tools")
|
|
21
|
-
|
|
22
23
|
self.api_key = api_key or getenv("SERP_API_KEY")
|
|
23
24
|
if not self.api_key:
|
|
24
25
|
logger.warning("No Serpapi API key provided")
|
|
25
26
|
|
|
26
|
-
|
|
27
|
-
if
|
|
28
|
-
|
|
27
|
+
tools: List[Any] = []
|
|
28
|
+
if all or enable_search_google:
|
|
29
|
+
tools.append(self.search_google)
|
|
30
|
+
if all or enable_search_youtube:
|
|
31
|
+
tools.append(self.search_youtube)
|
|
32
|
+
|
|
33
|
+
super().__init__(name="serpapi_tools", tools=tools, **kwargs)
|
|
29
34
|
|
|
30
35
|
def search_google(self, query: str, num_results: int = 10) -> str:
|
|
31
36
|
"""
|
|
@@ -51,7 +56,7 @@ class SerpApiTools(Toolkit):
|
|
|
51
56
|
if not query:
|
|
52
57
|
return "Please provide a query to search for"
|
|
53
58
|
|
|
54
|
-
|
|
59
|
+
log_info(f"Searching Google for: {query}")
|
|
55
60
|
|
|
56
61
|
params = {"q": query, "api_key": self.api_key, "num": num_results}
|
|
57
62
|
|
|
@@ -92,7 +97,7 @@ class SerpApiTools(Toolkit):
|
|
|
92
97
|
if not query:
|
|
93
98
|
return "Please provide a query to search for"
|
|
94
99
|
|
|
95
|
-
|
|
100
|
+
log_info(f"Searching Youtube for: {query}")
|
|
96
101
|
|
|
97
102
|
params = {"search_query": query, "api_key": self.api_key}
|
|
98
103
|
|
agno/tools/serper.py
ADDED
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
import json
|
|
2
|
+
from os import getenv
|
|
3
|
+
from typing import Any, Dict, List, Optional
|
|
4
|
+
|
|
5
|
+
import requests
|
|
6
|
+
|
|
7
|
+
from agno.tools import Toolkit
|
|
8
|
+
from agno.utils.log import log_debug, log_error, log_warning
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class SerperTools(Toolkit):
|
|
12
|
+
def __init__(
|
|
13
|
+
self,
|
|
14
|
+
api_key: Optional[str] = None,
|
|
15
|
+
location: str = "us",
|
|
16
|
+
language: str = "en",
|
|
17
|
+
num_results: int = 10,
|
|
18
|
+
date_range: Optional[str] = None,
|
|
19
|
+
enable_search: bool = True,
|
|
20
|
+
enable_search_news: bool = True,
|
|
21
|
+
enable_search_scholar: bool = True,
|
|
22
|
+
enable_scrape_webpage: bool = True,
|
|
23
|
+
all: bool = False,
|
|
24
|
+
**kwargs,
|
|
25
|
+
):
|
|
26
|
+
"""
|
|
27
|
+
Initialize the SerperTools.
|
|
28
|
+
|
|
29
|
+
Args:
|
|
30
|
+
api_key Optional[str]: The Serper API key.
|
|
31
|
+
location Optional[str]: The Google location code for search results.
|
|
32
|
+
language Optional[str]: The language code for search results.
|
|
33
|
+
num_results Optional[int]: The number of search results to retrieve.
|
|
34
|
+
date_range Optional[str]: Default date range filter for searches.
|
|
35
|
+
"""
|
|
36
|
+
self.api_key = api_key or getenv("SERPER_API_KEY")
|
|
37
|
+
if not self.api_key:
|
|
38
|
+
log_debug("No Serper API key provided")
|
|
39
|
+
|
|
40
|
+
self.location = location
|
|
41
|
+
self.language = language
|
|
42
|
+
self.num_results = num_results
|
|
43
|
+
self.date_range = date_range
|
|
44
|
+
|
|
45
|
+
tools: List[Any] = []
|
|
46
|
+
if all or enable_search:
|
|
47
|
+
tools.append(self.search_web)
|
|
48
|
+
if all or enable_search_news:
|
|
49
|
+
tools.append(self.search_news)
|
|
50
|
+
if all or enable_search_scholar:
|
|
51
|
+
tools.append(self.search_scholar)
|
|
52
|
+
if all or enable_scrape_webpage:
|
|
53
|
+
tools.append(self.scrape_webpage)
|
|
54
|
+
|
|
55
|
+
super().__init__(name="serper_tools", tools=tools, **kwargs)
|
|
56
|
+
|
|
57
|
+
def _make_request(self, endpoint: str, params: Dict[str, Any]) -> Dict[str, Any]:
|
|
58
|
+
"""
|
|
59
|
+
Makes a request to the Serper API.
|
|
60
|
+
|
|
61
|
+
Args:
|
|
62
|
+
endpoint (str): The API endpoint
|
|
63
|
+
params (Dict[str, Any]): Request parameters
|
|
64
|
+
|
|
65
|
+
Returns:
|
|
66
|
+
Dict[str, Any]: Search response
|
|
67
|
+
"""
|
|
68
|
+
try:
|
|
69
|
+
if not self.api_key:
|
|
70
|
+
log_error("No Serper API key provided")
|
|
71
|
+
return {"success": False, "error": "Please provide a Serper API key"}
|
|
72
|
+
|
|
73
|
+
url = f"https://google.serper.dev/{endpoint}"
|
|
74
|
+
if endpoint == "scrape":
|
|
75
|
+
url = "https://scrape.serper.dev"
|
|
76
|
+
|
|
77
|
+
headers = {"X-API-KEY": self.api_key, "Content-Type": "application/json"}
|
|
78
|
+
|
|
79
|
+
# Add optional parameters
|
|
80
|
+
if self.date_range:
|
|
81
|
+
params["tbs"] = self.date_range
|
|
82
|
+
if self.location:
|
|
83
|
+
params["gl"] = self.location
|
|
84
|
+
|
|
85
|
+
if self.language:
|
|
86
|
+
params["hl"] = self.language
|
|
87
|
+
|
|
88
|
+
payload = json.dumps(params)
|
|
89
|
+
|
|
90
|
+
log_debug(f"Making request to {url} with params: {params}")
|
|
91
|
+
response = requests.request("POST", url, headers=headers, data=payload)
|
|
92
|
+
response.raise_for_status()
|
|
93
|
+
|
|
94
|
+
log_debug(f"Successfully received response from {endpoint} endpoint")
|
|
95
|
+
return {"success": True, "data": response.json(), "raw_response": response.text}
|
|
96
|
+
except Exception as e:
|
|
97
|
+
log_error(f"Serper API error: {str(e)}")
|
|
98
|
+
return {"success": False, "error": str(e)}
|
|
99
|
+
|
|
100
|
+
def search_web(
|
|
101
|
+
self,
|
|
102
|
+
query: str,
|
|
103
|
+
num_results: Optional[int] = None,
|
|
104
|
+
) -> str:
|
|
105
|
+
"""
|
|
106
|
+
Searches Google for the provided query using the Serper API.
|
|
107
|
+
|
|
108
|
+
Args:
|
|
109
|
+
query (str): The search query to search for on Google.
|
|
110
|
+
num_results (int, optional): Number of search results to retrieve.
|
|
111
|
+
|
|
112
|
+
Returns:
|
|
113
|
+
str: A JSON-formatted string containing the search results or an error message if the search fails.
|
|
114
|
+
"""
|
|
115
|
+
try:
|
|
116
|
+
if not query:
|
|
117
|
+
return json.dumps({"error": "Please provide a query to search for"}, indent=2)
|
|
118
|
+
|
|
119
|
+
log_debug(f"Searching Google for: {query}")
|
|
120
|
+
|
|
121
|
+
params = {
|
|
122
|
+
"q": query,
|
|
123
|
+
"num": num_results or self.num_results,
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
result = self._make_request("search", params)
|
|
127
|
+
|
|
128
|
+
if result["success"]:
|
|
129
|
+
log_debug(f"Successfully found Google search results for query: {query}")
|
|
130
|
+
return result["raw_response"]
|
|
131
|
+
else:
|
|
132
|
+
log_error(f"Error searching Google for query {query}: {result['error']}")
|
|
133
|
+
return json.dumps({"error": result["error"]}, indent=2)
|
|
134
|
+
|
|
135
|
+
except Exception as e:
|
|
136
|
+
log_error(f"Unexpected error searching Google for query {query}: {e}")
|
|
137
|
+
return json.dumps({"error": f"An unexpected error occurred: {str(e)}"}, indent=2)
|
|
138
|
+
|
|
139
|
+
def search_news(
|
|
140
|
+
self,
|
|
141
|
+
query: str,
|
|
142
|
+
num_results: Optional[int] = None,
|
|
143
|
+
) -> str:
|
|
144
|
+
"""
|
|
145
|
+
Searches for news articles using the Serper News API.
|
|
146
|
+
|
|
147
|
+
Args:
|
|
148
|
+
query (str): The search query for news articles.
|
|
149
|
+
num_results (int, optional): Number of news results to retrieve.
|
|
150
|
+
|
|
151
|
+
Returns:
|
|
152
|
+
str: A JSON-formatted string containing the news search results or an error message.
|
|
153
|
+
"""
|
|
154
|
+
try:
|
|
155
|
+
if not query:
|
|
156
|
+
return json.dumps({"error": "Please provide a query to search for news"}, indent=2)
|
|
157
|
+
|
|
158
|
+
log_debug(f"Searching news for: {query}")
|
|
159
|
+
|
|
160
|
+
params = {
|
|
161
|
+
"q": query,
|
|
162
|
+
"num": num_results or self.num_results,
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
result = self._make_request("news", params)
|
|
166
|
+
|
|
167
|
+
if result["success"]:
|
|
168
|
+
log_debug(f"Successfully found {num_results or self.num_results} news articles for query: {query}")
|
|
169
|
+
return result["raw_response"]
|
|
170
|
+
else:
|
|
171
|
+
log_error(f"Error searching news for query {query}: {result['error']}")
|
|
172
|
+
return json.dumps({"error": result["error"]}, indent=2)
|
|
173
|
+
|
|
174
|
+
except Exception as e:
|
|
175
|
+
log_error(f"Unexpected error searching news for query {query}: {e}")
|
|
176
|
+
return json.dumps({"error": f"An unexpected error occurred: {str(e)}"}, indent=2)
|
|
177
|
+
|
|
178
|
+
def search_scholar(
|
|
179
|
+
self,
|
|
180
|
+
query: str,
|
|
181
|
+
num_results: Optional[int] = None,
|
|
182
|
+
) -> str:
|
|
183
|
+
"""
|
|
184
|
+
Searches for academic papers using Google Scholar via Serper API.
|
|
185
|
+
|
|
186
|
+
Args:
|
|
187
|
+
query (str): The search query for academic papers.
|
|
188
|
+
num_results (int, optional): Number of academic papers to retrieve.
|
|
189
|
+
|
|
190
|
+
Returns:
|
|
191
|
+
str: A JSON-formatted string containing the scholar search results or an error message.
|
|
192
|
+
"""
|
|
193
|
+
try:
|
|
194
|
+
if not query:
|
|
195
|
+
return json.dumps({"error": "Please provide a query to search for academic papers"}, indent=2)
|
|
196
|
+
|
|
197
|
+
log_debug(f"Searching scholar for: {query}")
|
|
198
|
+
|
|
199
|
+
params = {
|
|
200
|
+
"q": query,
|
|
201
|
+
"num": num_results or self.num_results,
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
result = self._make_request("scholar", params)
|
|
205
|
+
|
|
206
|
+
if result["success"]:
|
|
207
|
+
log_debug(f"Successfully found academic papers for query: {query}")
|
|
208
|
+
return result["raw_response"]
|
|
209
|
+
else:
|
|
210
|
+
log_error(f"Error searching scholar for query {query}: {result['error']}")
|
|
211
|
+
return json.dumps({"error": result["error"]}, indent=2)
|
|
212
|
+
|
|
213
|
+
except Exception as e:
|
|
214
|
+
log_error(f"Unexpected error searching scholar for query {query}: {e}")
|
|
215
|
+
return json.dumps({"error": f"An unexpected error occurred: {str(e)}"}, indent=2)
|
|
216
|
+
|
|
217
|
+
def scrape_webpage(
|
|
218
|
+
self,
|
|
219
|
+
url: str,
|
|
220
|
+
markdown: bool = False,
|
|
221
|
+
) -> str:
|
|
222
|
+
"""
|
|
223
|
+
Scrapes and extracts content from a webpage using the Serper scraping API.
|
|
224
|
+
|
|
225
|
+
Args:
|
|
226
|
+
url (str): The URL of the webpage to scrape.
|
|
227
|
+
markdown (bool, optional): Return content in markdown format (default: False).
|
|
228
|
+
|
|
229
|
+
Returns:
|
|
230
|
+
str: A JSON-formatted string containing the scraped webpage content or an error message.
|
|
231
|
+
"""
|
|
232
|
+
try:
|
|
233
|
+
if not url:
|
|
234
|
+
log_warning("No URL provided to scrape")
|
|
235
|
+
return json.dumps({"error": "Please provide a URL to scrape"}, indent=2)
|
|
236
|
+
|
|
237
|
+
log_debug(f"Scraping webpage: {url}")
|
|
238
|
+
|
|
239
|
+
params = {
|
|
240
|
+
"url": url,
|
|
241
|
+
"includeMarkdown": markdown,
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
result = self._make_request("scrape", params)
|
|
245
|
+
|
|
246
|
+
if result["success"]:
|
|
247
|
+
log_debug(f"Successfully scraped webpage: {url}")
|
|
248
|
+
return result["raw_response"]
|
|
249
|
+
else:
|
|
250
|
+
log_error(f"Error scraping webpage {url}: {result['error']}")
|
|
251
|
+
return json.dumps({"error": result["error"]}, indent=2)
|
|
252
|
+
|
|
253
|
+
except Exception as e:
|
|
254
|
+
log_error(f"Unexpected error scraping webpage {url}: {e}")
|
|
255
|
+
return json.dumps({"error": f"An unexpected error occurred: {str(e)}"}, indent=2)
|