ai-parrot 0.17.2__cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.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.
- agentui/.prettierrc +15 -0
- agentui/QUICKSTART.md +272 -0
- agentui/README.md +59 -0
- agentui/env.example +16 -0
- agentui/jsconfig.json +14 -0
- agentui/package-lock.json +4242 -0
- agentui/package.json +34 -0
- agentui/scripts/postinstall/apply-patches.mjs +260 -0
- agentui/src/app.css +61 -0
- agentui/src/app.d.ts +13 -0
- agentui/src/app.html +12 -0
- agentui/src/components/LoadingSpinner.svelte +64 -0
- agentui/src/components/ThemeSwitcher.svelte +159 -0
- agentui/src/components/index.js +4 -0
- agentui/src/lib/api/bots.ts +60 -0
- agentui/src/lib/api/chat.ts +22 -0
- agentui/src/lib/api/http.ts +25 -0
- agentui/src/lib/components/BotCard.svelte +33 -0
- agentui/src/lib/components/ChatBubble.svelte +63 -0
- agentui/src/lib/components/Toast.svelte +21 -0
- agentui/src/lib/config.ts +20 -0
- agentui/src/lib/stores/auth.svelte.ts +73 -0
- agentui/src/lib/stores/theme.svelte.js +64 -0
- agentui/src/lib/stores/toast.svelte.ts +31 -0
- agentui/src/lib/utils/conversation.ts +39 -0
- agentui/src/routes/+layout.svelte +20 -0
- agentui/src/routes/+page.svelte +232 -0
- agentui/src/routes/login/+page.svelte +200 -0
- agentui/src/routes/talk/[agentId]/+page.svelte +297 -0
- agentui/src/routes/talk/[agentId]/+page.ts +7 -0
- agentui/static/README.md +1 -0
- agentui/svelte.config.js +11 -0
- agentui/tailwind.config.ts +53 -0
- agentui/tsconfig.json +3 -0
- agentui/vite.config.ts +10 -0
- ai_parrot-0.17.2.dist-info/METADATA +472 -0
- ai_parrot-0.17.2.dist-info/RECORD +535 -0
- ai_parrot-0.17.2.dist-info/WHEEL +6 -0
- ai_parrot-0.17.2.dist-info/entry_points.txt +2 -0
- ai_parrot-0.17.2.dist-info/licenses/LICENSE +21 -0
- ai_parrot-0.17.2.dist-info/top_level.txt +6 -0
- crew-builder/.prettierrc +15 -0
- crew-builder/QUICKSTART.md +259 -0
- crew-builder/README.md +113 -0
- crew-builder/env.example +17 -0
- crew-builder/jsconfig.json +14 -0
- crew-builder/package-lock.json +4182 -0
- crew-builder/package.json +37 -0
- crew-builder/scripts/postinstall/apply-patches.mjs +260 -0
- crew-builder/src/app.css +62 -0
- crew-builder/src/app.d.ts +13 -0
- crew-builder/src/app.html +12 -0
- crew-builder/src/components/LoadingSpinner.svelte +64 -0
- crew-builder/src/components/ThemeSwitcher.svelte +149 -0
- crew-builder/src/components/index.js +9 -0
- crew-builder/src/lib/api/bots.ts +60 -0
- crew-builder/src/lib/api/chat.ts +80 -0
- crew-builder/src/lib/api/client.ts +56 -0
- crew-builder/src/lib/api/crew/crew.ts +136 -0
- crew-builder/src/lib/api/index.ts +5 -0
- crew-builder/src/lib/api/o365/auth.ts +65 -0
- crew-builder/src/lib/auth/auth.ts +54 -0
- crew-builder/src/lib/components/AgentNode.svelte +43 -0
- crew-builder/src/lib/components/BotCard.svelte +33 -0
- crew-builder/src/lib/components/ChatBubble.svelte +67 -0
- crew-builder/src/lib/components/ConfigPanel.svelte +278 -0
- crew-builder/src/lib/components/JsonTreeNode.svelte +76 -0
- crew-builder/src/lib/components/JsonViewer.svelte +24 -0
- crew-builder/src/lib/components/MarkdownEditor.svelte +48 -0
- crew-builder/src/lib/components/ThemeToggle.svelte +36 -0
- crew-builder/src/lib/components/Toast.svelte +67 -0
- crew-builder/src/lib/components/Toolbar.svelte +157 -0
- crew-builder/src/lib/components/index.ts +10 -0
- crew-builder/src/lib/config.ts +8 -0
- crew-builder/src/lib/stores/auth.svelte.ts +228 -0
- crew-builder/src/lib/stores/crewStore.ts +369 -0
- crew-builder/src/lib/stores/theme.svelte.js +145 -0
- crew-builder/src/lib/stores/toast.svelte.ts +69 -0
- crew-builder/src/lib/utils/conversation.ts +39 -0
- crew-builder/src/lib/utils/markdown.ts +122 -0
- crew-builder/src/lib/utils/talkHistory.ts +47 -0
- crew-builder/src/routes/+layout.svelte +20 -0
- crew-builder/src/routes/+page.svelte +539 -0
- crew-builder/src/routes/agents/+page.svelte +247 -0
- crew-builder/src/routes/agents/[agentId]/+page.svelte +288 -0
- crew-builder/src/routes/agents/[agentId]/+page.ts +7 -0
- crew-builder/src/routes/builder/+page.svelte +204 -0
- crew-builder/src/routes/crew/ask/+page.svelte +1052 -0
- crew-builder/src/routes/crew/ask/+page.ts +1 -0
- crew-builder/src/routes/integrations/o365/+page.svelte +304 -0
- crew-builder/src/routes/login/+page.svelte +197 -0
- crew-builder/src/routes/talk/[agentId]/+page.svelte +487 -0
- crew-builder/src/routes/talk/[agentId]/+page.ts +7 -0
- crew-builder/static/README.md +1 -0
- crew-builder/svelte.config.js +11 -0
- crew-builder/tailwind.config.ts +53 -0
- crew-builder/tsconfig.json +3 -0
- crew-builder/vite.config.ts +10 -0
- mcp_servers/calculator_server.py +309 -0
- parrot/__init__.py +27 -0
- parrot/__pycache__/__init__.cpython-310.pyc +0 -0
- parrot/__pycache__/version.cpython-310.pyc +0 -0
- parrot/_version.py +34 -0
- parrot/a2a/__init__.py +48 -0
- parrot/a2a/client.py +658 -0
- parrot/a2a/discovery.py +89 -0
- parrot/a2a/mixin.py +257 -0
- parrot/a2a/models.py +376 -0
- parrot/a2a/server.py +770 -0
- parrot/agents/__init__.py +29 -0
- parrot/bots/__init__.py +12 -0
- parrot/bots/a2a_agent.py +19 -0
- parrot/bots/abstract.py +3139 -0
- parrot/bots/agent.py +1129 -0
- parrot/bots/basic.py +9 -0
- parrot/bots/chatbot.py +669 -0
- parrot/bots/data.py +1618 -0
- parrot/bots/database/__init__.py +5 -0
- parrot/bots/database/abstract.py +3071 -0
- parrot/bots/database/cache.py +286 -0
- parrot/bots/database/models.py +468 -0
- parrot/bots/database/prompts.py +154 -0
- parrot/bots/database/retries.py +98 -0
- parrot/bots/database/router.py +269 -0
- parrot/bots/database/sql.py +41 -0
- parrot/bots/db/__init__.py +6 -0
- parrot/bots/db/abstract.py +556 -0
- parrot/bots/db/bigquery.py +602 -0
- parrot/bots/db/cache.py +85 -0
- parrot/bots/db/documentdb.py +668 -0
- parrot/bots/db/elastic.py +1014 -0
- parrot/bots/db/influx.py +898 -0
- parrot/bots/db/mock.py +96 -0
- parrot/bots/db/multi.py +783 -0
- parrot/bots/db/prompts.py +185 -0
- parrot/bots/db/sql.py +1255 -0
- parrot/bots/db/tools.py +212 -0
- parrot/bots/document.py +680 -0
- parrot/bots/hrbot.py +15 -0
- parrot/bots/kb.py +170 -0
- parrot/bots/mcp.py +36 -0
- parrot/bots/orchestration/README.md +463 -0
- parrot/bots/orchestration/__init__.py +1 -0
- parrot/bots/orchestration/agent.py +155 -0
- parrot/bots/orchestration/crew.py +3330 -0
- parrot/bots/orchestration/fsm.py +1179 -0
- parrot/bots/orchestration/hr.py +434 -0
- parrot/bots/orchestration/storage/__init__.py +4 -0
- parrot/bots/orchestration/storage/memory.py +100 -0
- parrot/bots/orchestration/storage/mixin.py +119 -0
- parrot/bots/orchestration/verify.py +202 -0
- parrot/bots/product.py +204 -0
- parrot/bots/prompts/__init__.py +96 -0
- parrot/bots/prompts/agents.py +155 -0
- parrot/bots/prompts/data.py +216 -0
- parrot/bots/prompts/output_generation.py +8 -0
- parrot/bots/scraper/__init__.py +3 -0
- parrot/bots/scraper/models.py +122 -0
- parrot/bots/scraper/scraper.py +1173 -0
- parrot/bots/scraper/templates.py +115 -0
- parrot/bots/stores/__init__.py +5 -0
- parrot/bots/stores/local.py +172 -0
- parrot/bots/webdev.py +81 -0
- parrot/cli.py +17 -0
- parrot/clients/__init__.py +16 -0
- parrot/clients/base.py +1491 -0
- parrot/clients/claude.py +1191 -0
- parrot/clients/factory.py +129 -0
- parrot/clients/google.py +4567 -0
- parrot/clients/gpt.py +1975 -0
- parrot/clients/grok.py +432 -0
- parrot/clients/groq.py +986 -0
- parrot/clients/hf.py +582 -0
- parrot/clients/models.py +18 -0
- parrot/conf.py +395 -0
- parrot/embeddings/__init__.py +9 -0
- parrot/embeddings/base.py +157 -0
- parrot/embeddings/google.py +98 -0
- parrot/embeddings/huggingface.py +74 -0
- parrot/embeddings/openai.py +84 -0
- parrot/embeddings/processor.py +88 -0
- parrot/exceptions.c +13868 -0
- parrot/exceptions.cpython-310-x86_64-linux-gnu.so +0 -0
- parrot/exceptions.pxd +22 -0
- parrot/exceptions.pxi +15 -0
- parrot/exceptions.pyx +44 -0
- parrot/generators/__init__.py +29 -0
- parrot/generators/base.py +200 -0
- parrot/generators/html.py +293 -0
- parrot/generators/react.py +205 -0
- parrot/generators/streamlit.py +203 -0
- parrot/generators/template.py +105 -0
- parrot/handlers/__init__.py +4 -0
- parrot/handlers/agent.py +861 -0
- parrot/handlers/agents/__init__.py +1 -0
- parrot/handlers/agents/abstract.py +900 -0
- parrot/handlers/bots.py +338 -0
- parrot/handlers/chat.py +915 -0
- parrot/handlers/creation.sql +192 -0
- parrot/handlers/crew/ARCHITECTURE.md +362 -0
- parrot/handlers/crew/README_BOTMANAGER_PERSISTENCE.md +303 -0
- parrot/handlers/crew/README_REDIS_PERSISTENCE.md +366 -0
- parrot/handlers/crew/__init__.py +0 -0
- parrot/handlers/crew/handler.py +801 -0
- parrot/handlers/crew/models.py +229 -0
- parrot/handlers/crew/redis_persistence.py +523 -0
- parrot/handlers/jobs/__init__.py +10 -0
- parrot/handlers/jobs/job.py +384 -0
- parrot/handlers/jobs/mixin.py +627 -0
- parrot/handlers/jobs/models.py +115 -0
- parrot/handlers/jobs/worker.py +31 -0
- parrot/handlers/models.py +596 -0
- parrot/handlers/o365_auth.py +105 -0
- parrot/handlers/stream.py +337 -0
- parrot/interfaces/__init__.py +6 -0
- parrot/interfaces/aws.py +143 -0
- parrot/interfaces/credentials.py +113 -0
- parrot/interfaces/database.py +27 -0
- parrot/interfaces/google.py +1123 -0
- parrot/interfaces/hierarchy.py +1227 -0
- parrot/interfaces/http.py +651 -0
- parrot/interfaces/images/__init__.py +0 -0
- parrot/interfaces/images/plugins/__init__.py +24 -0
- parrot/interfaces/images/plugins/abstract.py +58 -0
- parrot/interfaces/images/plugins/analisys.py +148 -0
- parrot/interfaces/images/plugins/classify.py +150 -0
- parrot/interfaces/images/plugins/classifybase.py +182 -0
- parrot/interfaces/images/plugins/detect.py +150 -0
- parrot/interfaces/images/plugins/exif.py +1103 -0
- parrot/interfaces/images/plugins/hash.py +52 -0
- parrot/interfaces/images/plugins/vision.py +104 -0
- parrot/interfaces/images/plugins/yolo.py +66 -0
- parrot/interfaces/images/plugins/zerodetect.py +197 -0
- parrot/interfaces/o365.py +978 -0
- parrot/interfaces/onedrive.py +822 -0
- parrot/interfaces/sharepoint.py +1435 -0
- parrot/interfaces/soap.py +257 -0
- parrot/loaders/__init__.py +8 -0
- parrot/loaders/abstract.py +1131 -0
- parrot/loaders/audio.py +199 -0
- parrot/loaders/basepdf.py +53 -0
- parrot/loaders/basevideo.py +1568 -0
- parrot/loaders/csv.py +409 -0
- parrot/loaders/docx.py +116 -0
- parrot/loaders/epubloader.py +316 -0
- parrot/loaders/excel.py +199 -0
- parrot/loaders/factory.py +55 -0
- parrot/loaders/files/__init__.py +0 -0
- parrot/loaders/files/abstract.py +39 -0
- parrot/loaders/files/html.py +26 -0
- parrot/loaders/files/text.py +63 -0
- parrot/loaders/html.py +152 -0
- parrot/loaders/markdown.py +442 -0
- parrot/loaders/pdf.py +373 -0
- parrot/loaders/pdfmark.py +320 -0
- parrot/loaders/pdftables.py +506 -0
- parrot/loaders/ppt.py +476 -0
- parrot/loaders/qa.py +63 -0
- parrot/loaders/splitters/__init__.py +10 -0
- parrot/loaders/splitters/base.py +138 -0
- parrot/loaders/splitters/md.py +228 -0
- parrot/loaders/splitters/token.py +143 -0
- parrot/loaders/txt.py +26 -0
- parrot/loaders/video.py +89 -0
- parrot/loaders/videolocal.py +218 -0
- parrot/loaders/videounderstanding.py +377 -0
- parrot/loaders/vimeo.py +167 -0
- parrot/loaders/web.py +599 -0
- parrot/loaders/youtube.py +504 -0
- parrot/manager/__init__.py +5 -0
- parrot/manager/manager.py +1030 -0
- parrot/mcp/__init__.py +28 -0
- parrot/mcp/adapter.py +105 -0
- parrot/mcp/cli.py +174 -0
- parrot/mcp/client.py +119 -0
- parrot/mcp/config.py +75 -0
- parrot/mcp/integration.py +842 -0
- parrot/mcp/oauth.py +933 -0
- parrot/mcp/server.py +225 -0
- parrot/mcp/transports/__init__.py +3 -0
- parrot/mcp/transports/base.py +279 -0
- parrot/mcp/transports/grpc_session.py +163 -0
- parrot/mcp/transports/http.py +312 -0
- parrot/mcp/transports/mcp.proto +108 -0
- parrot/mcp/transports/quic.py +1082 -0
- parrot/mcp/transports/sse.py +330 -0
- parrot/mcp/transports/stdio.py +309 -0
- parrot/mcp/transports/unix.py +395 -0
- parrot/mcp/transports/websocket.py +547 -0
- parrot/memory/__init__.py +16 -0
- parrot/memory/abstract.py +209 -0
- parrot/memory/agent.py +32 -0
- parrot/memory/cache.py +175 -0
- parrot/memory/core.py +555 -0
- parrot/memory/file.py +153 -0
- parrot/memory/mem.py +131 -0
- parrot/memory/redis.py +613 -0
- parrot/models/__init__.py +46 -0
- parrot/models/basic.py +118 -0
- parrot/models/compliance.py +208 -0
- parrot/models/crew.py +395 -0
- parrot/models/detections.py +654 -0
- parrot/models/generation.py +85 -0
- parrot/models/google.py +223 -0
- parrot/models/groq.py +23 -0
- parrot/models/openai.py +30 -0
- parrot/models/outputs.py +285 -0
- parrot/models/responses.py +938 -0
- parrot/notifications/__init__.py +743 -0
- parrot/openapi/__init__.py +3 -0
- parrot/openapi/components.yaml +641 -0
- parrot/openapi/config.py +322 -0
- parrot/outputs/__init__.py +32 -0
- parrot/outputs/formats/__init__.py +108 -0
- parrot/outputs/formats/altair.py +359 -0
- parrot/outputs/formats/application.py +122 -0
- parrot/outputs/formats/base.py +351 -0
- parrot/outputs/formats/bokeh.py +356 -0
- parrot/outputs/formats/card.py +424 -0
- parrot/outputs/formats/chart.py +436 -0
- parrot/outputs/formats/d3.py +255 -0
- parrot/outputs/formats/echarts.py +310 -0
- parrot/outputs/formats/generators/__init__.py +0 -0
- parrot/outputs/formats/generators/abstract.py +61 -0
- parrot/outputs/formats/generators/panel.py +145 -0
- parrot/outputs/formats/generators/streamlit.py +86 -0
- parrot/outputs/formats/generators/terminal.py +63 -0
- parrot/outputs/formats/holoviews.py +310 -0
- parrot/outputs/formats/html.py +147 -0
- parrot/outputs/formats/jinja2.py +46 -0
- parrot/outputs/formats/json.py +87 -0
- parrot/outputs/formats/map.py +933 -0
- parrot/outputs/formats/markdown.py +172 -0
- parrot/outputs/formats/matplotlib.py +237 -0
- parrot/outputs/formats/mixins/__init__.py +0 -0
- parrot/outputs/formats/mixins/emaps.py +855 -0
- parrot/outputs/formats/plotly.py +341 -0
- parrot/outputs/formats/seaborn.py +310 -0
- parrot/outputs/formats/table.py +397 -0
- parrot/outputs/formats/template_report.py +138 -0
- parrot/outputs/formats/yaml.py +125 -0
- parrot/outputs/formatter.py +152 -0
- parrot/outputs/templates/__init__.py +95 -0
- parrot/pipelines/__init__.py +0 -0
- parrot/pipelines/abstract.py +210 -0
- parrot/pipelines/detector.py +124 -0
- parrot/pipelines/models.py +90 -0
- parrot/pipelines/planogram.py +3002 -0
- parrot/pipelines/table.sql +97 -0
- parrot/plugins/__init__.py +106 -0
- parrot/plugins/importer.py +80 -0
- parrot/py.typed +0 -0
- parrot/registry/__init__.py +18 -0
- parrot/registry/registry.py +594 -0
- parrot/scheduler/__init__.py +1189 -0
- parrot/scheduler/models.py +60 -0
- parrot/security/__init__.py +16 -0
- parrot/security/prompt_injection.py +268 -0
- parrot/security/security_events.sql +25 -0
- parrot/services/__init__.py +1 -0
- parrot/services/mcp/__init__.py +8 -0
- parrot/services/mcp/config.py +13 -0
- parrot/services/mcp/server.py +295 -0
- parrot/services/o365_remote_auth.py +235 -0
- parrot/stores/__init__.py +7 -0
- parrot/stores/abstract.py +352 -0
- parrot/stores/arango.py +1090 -0
- parrot/stores/bigquery.py +1377 -0
- parrot/stores/cache.py +106 -0
- parrot/stores/empty.py +10 -0
- parrot/stores/faiss_store.py +1157 -0
- parrot/stores/kb/__init__.py +9 -0
- parrot/stores/kb/abstract.py +68 -0
- parrot/stores/kb/cache.py +165 -0
- parrot/stores/kb/doc.py +325 -0
- parrot/stores/kb/hierarchy.py +346 -0
- parrot/stores/kb/local.py +457 -0
- parrot/stores/kb/prompt.py +28 -0
- parrot/stores/kb/redis.py +659 -0
- parrot/stores/kb/store.py +115 -0
- parrot/stores/kb/user.py +374 -0
- parrot/stores/models.py +59 -0
- parrot/stores/pgvector.py +3 -0
- parrot/stores/postgres.py +2853 -0
- parrot/stores/utils/__init__.py +0 -0
- parrot/stores/utils/chunking.py +197 -0
- parrot/telemetry/__init__.py +3 -0
- parrot/telemetry/mixin.py +111 -0
- parrot/template/__init__.py +3 -0
- parrot/template/engine.py +259 -0
- parrot/tools/__init__.py +23 -0
- parrot/tools/abstract.py +644 -0
- parrot/tools/agent.py +363 -0
- parrot/tools/arangodbsearch.py +537 -0
- parrot/tools/arxiv_tool.py +188 -0
- parrot/tools/calculator/__init__.py +3 -0
- parrot/tools/calculator/operations/__init__.py +38 -0
- parrot/tools/calculator/operations/calculus.py +80 -0
- parrot/tools/calculator/operations/statistics.py +76 -0
- parrot/tools/calculator/tool.py +150 -0
- parrot/tools/cloudwatch.py +988 -0
- parrot/tools/codeinterpreter/__init__.py +127 -0
- parrot/tools/codeinterpreter/executor.py +371 -0
- parrot/tools/codeinterpreter/internals.py +473 -0
- parrot/tools/codeinterpreter/models.py +643 -0
- parrot/tools/codeinterpreter/prompts.py +224 -0
- parrot/tools/codeinterpreter/tool.py +664 -0
- parrot/tools/company_info/__init__.py +6 -0
- parrot/tools/company_info/tool.py +1138 -0
- parrot/tools/correlationanalysis.py +437 -0
- parrot/tools/database/abstract.py +286 -0
- parrot/tools/database/bq.py +115 -0
- parrot/tools/database/cache.py +284 -0
- parrot/tools/database/models.py +95 -0
- parrot/tools/database/pg.py +343 -0
- parrot/tools/databasequery.py +1159 -0
- parrot/tools/db.py +1800 -0
- parrot/tools/ddgo.py +370 -0
- parrot/tools/decorators.py +271 -0
- parrot/tools/dftohtml.py +282 -0
- parrot/tools/document.py +549 -0
- parrot/tools/ecs.py +819 -0
- parrot/tools/edareport.py +368 -0
- parrot/tools/elasticsearch.py +1049 -0
- parrot/tools/employees.py +462 -0
- parrot/tools/epson/__init__.py +96 -0
- parrot/tools/excel.py +683 -0
- parrot/tools/file/__init__.py +13 -0
- parrot/tools/file/abstract.py +76 -0
- parrot/tools/file/gcs.py +378 -0
- parrot/tools/file/local.py +284 -0
- parrot/tools/file/s3.py +511 -0
- parrot/tools/file/tmp.py +309 -0
- parrot/tools/file/tool.py +501 -0
- parrot/tools/file_reader.py +129 -0
- parrot/tools/flowtask/__init__.py +19 -0
- parrot/tools/flowtask/tool.py +761 -0
- parrot/tools/gittoolkit.py +508 -0
- parrot/tools/google/__init__.py +18 -0
- parrot/tools/google/base.py +169 -0
- parrot/tools/google/tools.py +1251 -0
- parrot/tools/googlelocation.py +5 -0
- parrot/tools/googleroutes.py +5 -0
- parrot/tools/googlesearch.py +5 -0
- parrot/tools/googlesitesearch.py +5 -0
- parrot/tools/googlevoice.py +2 -0
- parrot/tools/gvoice.py +695 -0
- parrot/tools/ibisworld/README.md +225 -0
- parrot/tools/ibisworld/__init__.py +11 -0
- parrot/tools/ibisworld/tool.py +366 -0
- parrot/tools/jiratoolkit.py +1718 -0
- parrot/tools/manager.py +1098 -0
- parrot/tools/math.py +152 -0
- parrot/tools/metadata.py +476 -0
- parrot/tools/msteams.py +1621 -0
- parrot/tools/msword.py +635 -0
- parrot/tools/multidb.py +580 -0
- parrot/tools/multistoresearch.py +369 -0
- parrot/tools/networkninja.py +167 -0
- parrot/tools/nextstop/__init__.py +4 -0
- parrot/tools/nextstop/base.py +286 -0
- parrot/tools/nextstop/employee.py +733 -0
- parrot/tools/nextstop/store.py +462 -0
- parrot/tools/notification.py +435 -0
- parrot/tools/o365/__init__.py +42 -0
- parrot/tools/o365/base.py +295 -0
- parrot/tools/o365/bundle.py +522 -0
- parrot/tools/o365/events.py +554 -0
- parrot/tools/o365/mail.py +992 -0
- parrot/tools/o365/onedrive.py +497 -0
- parrot/tools/o365/sharepoint.py +641 -0
- parrot/tools/openapi_toolkit.py +904 -0
- parrot/tools/openweather.py +527 -0
- parrot/tools/pdfprint.py +1001 -0
- parrot/tools/powerbi.py +518 -0
- parrot/tools/powerpoint.py +1113 -0
- parrot/tools/pricestool.py +146 -0
- parrot/tools/products/__init__.py +246 -0
- parrot/tools/prophet_tool.py +171 -0
- parrot/tools/pythonpandas.py +630 -0
- parrot/tools/pythonrepl.py +910 -0
- parrot/tools/qsource.py +436 -0
- parrot/tools/querytoolkit.py +395 -0
- parrot/tools/quickeda.py +827 -0
- parrot/tools/resttool.py +553 -0
- parrot/tools/retail/__init__.py +0 -0
- parrot/tools/retail/bby.py +528 -0
- parrot/tools/sandboxtool.py +703 -0
- parrot/tools/sassie/__init__.py +352 -0
- parrot/tools/scraping/__init__.py +7 -0
- parrot/tools/scraping/docs/select.md +466 -0
- parrot/tools/scraping/documentation.md +1278 -0
- parrot/tools/scraping/driver.py +436 -0
- parrot/tools/scraping/models.py +576 -0
- parrot/tools/scraping/options.py +85 -0
- parrot/tools/scraping/orchestrator.py +517 -0
- parrot/tools/scraping/readme.md +740 -0
- parrot/tools/scraping/tool.py +3115 -0
- parrot/tools/seasonaldetection.py +642 -0
- parrot/tools/shell_tool/__init__.py +5 -0
- parrot/tools/shell_tool/actions.py +408 -0
- parrot/tools/shell_tool/engine.py +155 -0
- parrot/tools/shell_tool/models.py +322 -0
- parrot/tools/shell_tool/tool.py +442 -0
- parrot/tools/site_search.py +214 -0
- parrot/tools/textfile.py +418 -0
- parrot/tools/think.py +378 -0
- parrot/tools/toolkit.py +298 -0
- parrot/tools/webapp_tool.py +187 -0
- parrot/tools/whatif.py +1279 -0
- parrot/tools/workday/MULTI_WSDL_EXAMPLE.md +249 -0
- parrot/tools/workday/__init__.py +6 -0
- parrot/tools/workday/models.py +1389 -0
- parrot/tools/workday/tool.py +1293 -0
- parrot/tools/yfinance_tool.py +306 -0
- parrot/tools/zipcode.py +217 -0
- parrot/utils/__init__.py +2 -0
- parrot/utils/helpers.py +73 -0
- parrot/utils/parsers/__init__.py +5 -0
- parrot/utils/parsers/toml.c +12078 -0
- parrot/utils/parsers/toml.cpython-310-x86_64-linux-gnu.so +0 -0
- parrot/utils/parsers/toml.pyx +21 -0
- parrot/utils/toml.py +11 -0
- parrot/utils/types.cpp +20936 -0
- parrot/utils/types.cpython-310-x86_64-linux-gnu.so +0 -0
- parrot/utils/types.pyx +213 -0
- parrot/utils/uv.py +11 -0
- parrot/version.py +10 -0
- parrot/yaml-rs/Cargo.lock +350 -0
- parrot/yaml-rs/Cargo.toml +19 -0
- parrot/yaml-rs/pyproject.toml +19 -0
- parrot/yaml-rs/python/yaml_rs/__init__.py +81 -0
- parrot/yaml-rs/src/lib.rs +222 -0
- requirements/docker-compose.yml +24 -0
- requirements/requirements-dev.txt +21 -0
parrot/tools/math.py
ADDED
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
from typing import Dict, Any, Optional
|
|
2
|
+
import math as mathlib
|
|
3
|
+
from pydantic import BaseModel, Field, field_validator
|
|
4
|
+
from .abstract import AbstractTool
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
# MathTool Arguments Schema
|
|
8
|
+
class MathToolArgs(BaseModel):
|
|
9
|
+
"""Arguments schema for MathTool."""
|
|
10
|
+
a: float = Field(description="The number for unary operations, or the first number for binary operations.")
|
|
11
|
+
operation: str = Field(
|
|
12
|
+
description="Mathematical operation. Supports: add, subtract, multiply, divide, sqrt."
|
|
13
|
+
)
|
|
14
|
+
b: Optional[float] = Field(
|
|
15
|
+
default=None,
|
|
16
|
+
description="The second number for binary operations. Not used for unary operations like square root."
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
@field_validator('operation')
|
|
21
|
+
@classmethod
|
|
22
|
+
def validate_operation(cls, v: str) -> str:
|
|
23
|
+
"""Normalize operation names to internal format."""
|
|
24
|
+
# Mapping of various operation names to internal names
|
|
25
|
+
operation_mapping = {
|
|
26
|
+
# Standard names
|
|
27
|
+
'add': 'add',
|
|
28
|
+
'subtract': 'subtract',
|
|
29
|
+
'multiply': 'multiply',
|
|
30
|
+
'divide': 'divide',
|
|
31
|
+
# Alternative names
|
|
32
|
+
'addition': 'add',
|
|
33
|
+
'subtraction': 'subtract',
|
|
34
|
+
'multiplication': 'multiply',
|
|
35
|
+
'division': 'divide',
|
|
36
|
+
# Math symbols
|
|
37
|
+
'+': 'add',
|
|
38
|
+
'-': 'subtract',
|
|
39
|
+
'*': 'multiply',
|
|
40
|
+
'/': 'divide',
|
|
41
|
+
'÷': 'divide',
|
|
42
|
+
'×': 'multiply',
|
|
43
|
+
# Common variations
|
|
44
|
+
'plus': 'add',
|
|
45
|
+
'minus': 'subtract',
|
|
46
|
+
'times': 'multiply',
|
|
47
|
+
'sum': 'add',
|
|
48
|
+
'difference': 'subtract',
|
|
49
|
+
'product': 'multiply',
|
|
50
|
+
'quotient': 'divide',
|
|
51
|
+
'sqrt': 'sqrt',
|
|
52
|
+
'square_root': 'sqrt',
|
|
53
|
+
'square root': 'sqrt'
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
normalized = v.lower().strip()
|
|
57
|
+
if normalized in operation_mapping:
|
|
58
|
+
return operation_mapping[normalized]
|
|
59
|
+
|
|
60
|
+
# If not found, provide helpful error message
|
|
61
|
+
valid_operations = list(set(operation_mapping.values()))
|
|
62
|
+
raise ValueError(
|
|
63
|
+
f"Unsupported operation: '{v}'. "
|
|
64
|
+
f"Supported operations: {', '.join(valid_operations)} "
|
|
65
|
+
f"or their aliases: {', '.join(operation_mapping.keys())}"
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
class MathTool(AbstractTool):
|
|
69
|
+
"""A tool for performing basic arithmetic operations."""
|
|
70
|
+
|
|
71
|
+
name = "MathTool"
|
|
72
|
+
description = "Performs basic arithmetic operations: addition, subtraction, multiplication, division and square root. Accepts various operation names like 'add', 'addition', '+', 'plus', etc."
|
|
73
|
+
args_schema = MathToolArgs
|
|
74
|
+
|
|
75
|
+
def __init__(self, **kwargs):
|
|
76
|
+
super().__init__(**kwargs)
|
|
77
|
+
|
|
78
|
+
async def _execute(self, a: float, operation: str = 'add', b: float = None, **kwargs) -> Dict[str, Any]:
|
|
79
|
+
"""
|
|
80
|
+
Execute the mathematical operation.
|
|
81
|
+
|
|
82
|
+
Args:
|
|
83
|
+
a: First number
|
|
84
|
+
b: Second number
|
|
85
|
+
operation: Operation to perform (already normalized by validator)
|
|
86
|
+
|
|
87
|
+
Returns:
|
|
88
|
+
Dictionary with the result
|
|
89
|
+
"""
|
|
90
|
+
unary_operations = {
|
|
91
|
+
"sqrt": self.sqrt
|
|
92
|
+
}
|
|
93
|
+
binary_operations = {
|
|
94
|
+
"add": self.add,
|
|
95
|
+
"subtract": self.subtract,
|
|
96
|
+
"multiply": self.multiply,
|
|
97
|
+
"divide": self.divide
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
if operation in unary_operations:
|
|
101
|
+
result = unary_operations[operation](a)
|
|
102
|
+
operands = [a]
|
|
103
|
+
elif operation in binary_operations:
|
|
104
|
+
if b is None:
|
|
105
|
+
raise ValueError(f"Operation '{operation}' requires a second number ('b').")
|
|
106
|
+
result = binary_operations[operation](a, b)
|
|
107
|
+
operands = [a, b]
|
|
108
|
+
else:
|
|
109
|
+
raise ValueError(f"Unsupported operation: {operation}")
|
|
110
|
+
|
|
111
|
+
return {
|
|
112
|
+
"operation": operation,
|
|
113
|
+
"operands": operands,
|
|
114
|
+
"result": result,
|
|
115
|
+
"expression": self._format_expression(a, operation, result, b)
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
def add(self, a: float, b: float) -> float:
|
|
119
|
+
"""Add two numbers."""
|
|
120
|
+
return a + b
|
|
121
|
+
|
|
122
|
+
def subtract(self, a: float, b: float) -> float:
|
|
123
|
+
"""Subtract two numbers."""
|
|
124
|
+
return a - b
|
|
125
|
+
|
|
126
|
+
def multiply(self, a: float, b: float) -> float:
|
|
127
|
+
"""Multiply two numbers."""
|
|
128
|
+
return a * b
|
|
129
|
+
|
|
130
|
+
def divide(self, a: float, b: float) -> float:
|
|
131
|
+
"""Divide two numbers."""
|
|
132
|
+
if b == 0:
|
|
133
|
+
raise ValueError("Cannot divide by zero")
|
|
134
|
+
return a / b
|
|
135
|
+
|
|
136
|
+
def sqrt(self, a: float) -> float:
|
|
137
|
+
"""Calculate the square root of a number."""
|
|
138
|
+
if a < 0:
|
|
139
|
+
raise ValueError("Cannot calculate the square root of a negative number.")
|
|
140
|
+
return mathlib.sqrt(a)
|
|
141
|
+
|
|
142
|
+
def _format_expression(self, a: float, operation: str, result: float, b: Optional[float] = None) -> str:
|
|
143
|
+
"""Format the mathematical expression as a string."""
|
|
144
|
+
if b is not None: # Binary operation
|
|
145
|
+
operators = {"add": "+", "subtract": "-", "multiply": "*", "divide": "/"}
|
|
146
|
+
operator = operators.get(operation, operation)
|
|
147
|
+
return f"{a} {operator} {b} = {result}"
|
|
148
|
+
else: # Unary operation
|
|
149
|
+
if operation == 'sqrt':
|
|
150
|
+
return f"sqrt({a}) = {result}"
|
|
151
|
+
# Add other unary operations here if needed
|
|
152
|
+
return f"{operation}({a}) = {result}"
|
parrot/tools/metadata.py
ADDED
|
@@ -0,0 +1,476 @@
|
|
|
1
|
+
"""Metadata tool for describing DataFrame schemas to the LLM."""
|
|
2
|
+
from typing import Any, Dict, Optional
|
|
3
|
+
from pydantic import Field
|
|
4
|
+
import numpy as np
|
|
5
|
+
import pandas as pd
|
|
6
|
+
from .abstract import AbstractTool, AbstractToolArgsSchema, ToolResult
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class MetadataToolArgs(AbstractToolArgsSchema):
|
|
10
|
+
"""Arguments for the MetadataTool."""
|
|
11
|
+
|
|
12
|
+
dataframe: Optional[str] = Field(
|
|
13
|
+
default=None,
|
|
14
|
+
description="Name of the DataFrame to inspect"
|
|
15
|
+
)
|
|
16
|
+
column: Optional[str] = Field(
|
|
17
|
+
default=None,
|
|
18
|
+
description="Specific column within the DataFrame to describe"
|
|
19
|
+
)
|
|
20
|
+
include_eda: bool = Field(
|
|
21
|
+
default=True,
|
|
22
|
+
description="Add Exploratory data analysis summary (statistics, missing values, memory usage)"
|
|
23
|
+
)
|
|
24
|
+
include_samples: bool = Field(
|
|
25
|
+
default=True,
|
|
26
|
+
description="Include sample rows from the DataFrame"
|
|
27
|
+
)
|
|
28
|
+
include_column_stats: bool = Field(
|
|
29
|
+
default=False,
|
|
30
|
+
description="Include detailed statistics for numeric and categorical columns"
|
|
31
|
+
)
|
|
32
|
+
include_eda: bool = Field(
|
|
33
|
+
default=False,
|
|
34
|
+
description="Add Exploratory data analysis summary (statistics, missing values, memory usage)"
|
|
35
|
+
)
|
|
36
|
+
include_samples: bool = Field(
|
|
37
|
+
default=False,
|
|
38
|
+
description="Include sample rows from the DataFrame"
|
|
39
|
+
)
|
|
40
|
+
include_column_stats: bool = Field(
|
|
41
|
+
default=False,
|
|
42
|
+
description="Include detailed statistics for numeric and categorical columns"
|
|
43
|
+
)
|
|
44
|
+
column: str | None = Field(
|
|
45
|
+
default=None,
|
|
46
|
+
description="Specific column within the DataFrame to describe"
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
class MetadataTool(AbstractTool):
|
|
52
|
+
"""
|
|
53
|
+
Expose DataFrame metadata with comprehensive EDA capabilities.
|
|
54
|
+
|
|
55
|
+
Provides:
|
|
56
|
+
- DataFrame schemas (columns, dtypes, shapes)
|
|
57
|
+
- EDA summaries (row counts, column types, missing values, memory usage)
|
|
58
|
+
- Sample rows for quick data inspection
|
|
59
|
+
- Detailed column statistics (optional)
|
|
60
|
+
"""
|
|
61
|
+
|
|
62
|
+
name = "dataframe_metadata"
|
|
63
|
+
description = (
|
|
64
|
+
"Retrieve comprehensive metadata about a single DataFrame including schema, "
|
|
65
|
+
"exploratory data analysis (EDA) statistics, column descriptions, and sample rows. "
|
|
66
|
+
"Use this tool to understand DataFrame structure, data types, missing values, "
|
|
67
|
+
"and basic statistics before performing analysis. Call this tool for one DataFrame at a time."
|
|
68
|
+
)
|
|
69
|
+
args_schema = MetadataToolArgs
|
|
70
|
+
|
|
71
|
+
def __init__(
|
|
72
|
+
self,
|
|
73
|
+
metadata: Optional[Dict[str, Dict[str, Any]]] = None,
|
|
74
|
+
alias_map: Optional[Dict[str, str]] = None,
|
|
75
|
+
dataframes: Optional[Dict[str, pd.DataFrame]] = None,
|
|
76
|
+
**kwargs
|
|
77
|
+
) -> None:
|
|
78
|
+
"""
|
|
79
|
+
Initialize MetadataTool.
|
|
80
|
+
|
|
81
|
+
Args:
|
|
82
|
+
metadata: Pre-computed metadata dictionary
|
|
83
|
+
alias_map: Mapping of DataFrame names to standardized aliases (df1, df2, etc.)
|
|
84
|
+
dataframes: Reference to actual DataFrames for dynamic EDA generation
|
|
85
|
+
**kwargs: Additional tool configuration
|
|
86
|
+
"""
|
|
87
|
+
super().__init__(**kwargs)
|
|
88
|
+
self.metadata: Dict[str, Dict[str, Any]] = metadata or {}
|
|
89
|
+
self.alias_map: Dict[str, str] = alias_map or {}
|
|
90
|
+
self.dataframes: Dict[str, pd.DataFrame] = dataframes or {}
|
|
91
|
+
|
|
92
|
+
def update_metadata(
|
|
93
|
+
self,
|
|
94
|
+
metadata: Dict[str, Dict[str, Any]],
|
|
95
|
+
alias_map: Optional[Dict[str, str]] = None,
|
|
96
|
+
dataframes: Optional[Dict[str, pd.DataFrame]] = None
|
|
97
|
+
) -> None:
|
|
98
|
+
"""
|
|
99
|
+
Update the internal metadata dictionary, alias map, and dataframes.
|
|
100
|
+
|
|
101
|
+
Args:
|
|
102
|
+
metadata: New metadata dictionary
|
|
103
|
+
alias_map: New alias mapping
|
|
104
|
+
dataframes: New DataFrame references
|
|
105
|
+
"""
|
|
106
|
+
self.metadata = metadata or {}
|
|
107
|
+
self.alias_map = alias_map or {}
|
|
108
|
+
if dataframes is not None:
|
|
109
|
+
self.dataframes = dataframes
|
|
110
|
+
|
|
111
|
+
async def _execute(
|
|
112
|
+
self,
|
|
113
|
+
dataframe: Optional[str] = None,
|
|
114
|
+
column: Optional[str] = None,
|
|
115
|
+
include_eda: bool = True,
|
|
116
|
+
include_samples: bool = True,
|
|
117
|
+
include_column_stats: bool = False,
|
|
118
|
+
**_: Any
|
|
119
|
+
) -> ToolResult:
|
|
120
|
+
"""
|
|
121
|
+
Execute metadata retrieval with optional EDA generation.
|
|
122
|
+
|
|
123
|
+
Args:
|
|
124
|
+
dataframe: Name or alias of the DataFrame to inspect
|
|
125
|
+
column: Specific column to describe
|
|
126
|
+
include_eda: Generate EDA summary dynamically
|
|
127
|
+
include_samples: Include sample rows
|
|
128
|
+
include_column_stats: Include detailed column statistics
|
|
129
|
+
|
|
130
|
+
Returns:
|
|
131
|
+
ToolResult with metadata and optional EDA information
|
|
132
|
+
"""
|
|
133
|
+
if not self.metadata:
|
|
134
|
+
return ToolResult(
|
|
135
|
+
status="success",
|
|
136
|
+
result={"message": "No metadata available. No DataFrames are currently loaded."},
|
|
137
|
+
metadata={"tool_name": self.name}
|
|
138
|
+
)
|
|
139
|
+
|
|
140
|
+
if dataframe:
|
|
141
|
+
try:
|
|
142
|
+
result = self._describe_dataframe(
|
|
143
|
+
dataframe,
|
|
144
|
+
column,
|
|
145
|
+
include_eda=include_eda,
|
|
146
|
+
include_samples=include_samples,
|
|
147
|
+
include_column_stats=include_column_stats
|
|
148
|
+
)
|
|
149
|
+
except ValueError as exc:
|
|
150
|
+
return ToolResult(
|
|
151
|
+
status="error",
|
|
152
|
+
result=None,
|
|
153
|
+
error=str(exc),
|
|
154
|
+
metadata={
|
|
155
|
+
"tool_name": self.name,
|
|
156
|
+
"dataframe": dataframe,
|
|
157
|
+
"column": column
|
|
158
|
+
}
|
|
159
|
+
)
|
|
160
|
+
else:
|
|
161
|
+
# List all available DataFrames
|
|
162
|
+
result = self._list_available_dataframes()
|
|
163
|
+
|
|
164
|
+
return ToolResult(
|
|
165
|
+
status="success",
|
|
166
|
+
result=result,
|
|
167
|
+
metadata={
|
|
168
|
+
"tool_name": self.name,
|
|
169
|
+
"dataframe": dataframe,
|
|
170
|
+
"column": column,
|
|
171
|
+
"include_eda": include_eda
|
|
172
|
+
}
|
|
173
|
+
)
|
|
174
|
+
|
|
175
|
+
def _list_available_dataframes(self) -> Dict[str, Any]:
|
|
176
|
+
"""List all available DataFrames with basic information."""
|
|
177
|
+
return {
|
|
178
|
+
"message": "Available DataFrames for analysis",
|
|
179
|
+
"total_dataframes": len(self.metadata),
|
|
180
|
+
"dataframes": [
|
|
181
|
+
{
|
|
182
|
+
"name": name,
|
|
183
|
+
"standardized_name": self.alias_map.get(name),
|
|
184
|
+
"description": meta.get('description'),
|
|
185
|
+
"shape": meta.get('shape'),
|
|
186
|
+
"row_count": meta.get('row_count'),
|
|
187
|
+
"column_count": meta.get('column_count'),
|
|
188
|
+
"columns": list(meta.get('columns', {}).keys()),
|
|
189
|
+
"memory_mb": meta.get('memory_usage_mb')
|
|
190
|
+
}
|
|
191
|
+
for name, meta in self.metadata.items()
|
|
192
|
+
]
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
def _describe_dataframe(
|
|
196
|
+
self,
|
|
197
|
+
dataframe: str,
|
|
198
|
+
column: Optional[str] = None,
|
|
199
|
+
include_eda: bool = True,
|
|
200
|
+
include_samples: bool = True,
|
|
201
|
+
include_column_stats: bool = False
|
|
202
|
+
) -> Dict[str, Any]:
|
|
203
|
+
"""
|
|
204
|
+
Describe a DataFrame and optionally a specific column.
|
|
205
|
+
|
|
206
|
+
Args:
|
|
207
|
+
dataframe: DataFrame name or alias
|
|
208
|
+
column: Optional specific column to describe
|
|
209
|
+
include_eda: Generate dynamic EDA summary
|
|
210
|
+
include_samples: Include sample rows
|
|
211
|
+
include_column_stats: Include detailed column statistics
|
|
212
|
+
|
|
213
|
+
Returns:
|
|
214
|
+
Comprehensive DataFrame or column description
|
|
215
|
+
"""
|
|
216
|
+
df_name = self._resolve_dataframe_name(dataframe)
|
|
217
|
+
df_meta = self.metadata.get(df_name)
|
|
218
|
+
|
|
219
|
+
if not df_meta:
|
|
220
|
+
raise ValueError(
|
|
221
|
+
f"DataFrame '{dataframe}' metadata not found. "
|
|
222
|
+
f"Available DataFrames: {list(self.metadata.keys())}"
|
|
223
|
+
)
|
|
224
|
+
|
|
225
|
+
# Handle single column request
|
|
226
|
+
if column:
|
|
227
|
+
return self._describe_column(df_name, column, df_meta)
|
|
228
|
+
|
|
229
|
+
# Build comprehensive DataFrame description
|
|
230
|
+
response = {
|
|
231
|
+
"dataframe": df_name,
|
|
232
|
+
"standardized_name": self.alias_map.get(df_name),
|
|
233
|
+
"description": df_meta.get('description'),
|
|
234
|
+
"shape": df_meta.get('shape'),
|
|
235
|
+
"row_count": df_meta.get('row_count'),
|
|
236
|
+
"column_count": df_meta.get('column_count'),
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
# Add pre-computed metadata fields
|
|
240
|
+
response |= {
|
|
241
|
+
key: value
|
|
242
|
+
for key, value in df_meta.items()
|
|
243
|
+
if key not in ['name', 'columns', 'sample_data', 'eda_summary']
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
# Include column information
|
|
247
|
+
response['columns'] = df_meta.get('columns', {})
|
|
248
|
+
|
|
249
|
+
# Generate dynamic EDA if requested
|
|
250
|
+
if include_eda:
|
|
251
|
+
include_samples = True
|
|
252
|
+
include_column_stats = True
|
|
253
|
+
if eda_summary := self._generate_eda_summary(df_name):
|
|
254
|
+
# Override with dynamic EDA if available
|
|
255
|
+
response['eda_summary'] = eda_summary
|
|
256
|
+
|
|
257
|
+
# Include sample rows if requested
|
|
258
|
+
if include_samples:
|
|
259
|
+
if sample_data := df_meta.get('sample_data', []):
|
|
260
|
+
response['sample_rows'] = sample_data
|
|
261
|
+
|
|
262
|
+
# Include detailed column statistics if requested
|
|
263
|
+
if include_column_stats:
|
|
264
|
+
if column_stats := self._generate_column_statistics(df_name):
|
|
265
|
+
response['column_statistics'] = column_stats
|
|
266
|
+
|
|
267
|
+
return response
|
|
268
|
+
|
|
269
|
+
def _describe_column(
|
|
270
|
+
self,
|
|
271
|
+
df_name: str,
|
|
272
|
+
column: str,
|
|
273
|
+
df_meta: Dict[str, Any]
|
|
274
|
+
) -> Dict[str, Any]:
|
|
275
|
+
"""
|
|
276
|
+
Describe a specific column with detailed information.
|
|
277
|
+
|
|
278
|
+
Args:
|
|
279
|
+
df_name: DataFrame name
|
|
280
|
+
column: Column name
|
|
281
|
+
df_meta: DataFrame metadata
|
|
282
|
+
|
|
283
|
+
Returns:
|
|
284
|
+
Column description dictionary
|
|
285
|
+
"""
|
|
286
|
+
column_meta = df_meta.get('columns', {}).get(column)
|
|
287
|
+
|
|
288
|
+
if not column_meta:
|
|
289
|
+
available_columns = list(df_meta.get('columns', {}).keys())
|
|
290
|
+
raise ValueError(
|
|
291
|
+
f"Column '{column}' not found in DataFrame '{df_name}'. "
|
|
292
|
+
f"Available columns: {available_columns}"
|
|
293
|
+
)
|
|
294
|
+
|
|
295
|
+
response = {
|
|
296
|
+
"dataframe": df_name,
|
|
297
|
+
"standardized_name": self.alias_map.get(df_name),
|
|
298
|
+
"column": column,
|
|
299
|
+
"metadata": column_meta
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
# Add column-specific statistics if DataFrame is available
|
|
303
|
+
df = self.dataframes.get(df_name)
|
|
304
|
+
if df is not None and column in df.columns:
|
|
305
|
+
response['statistics'] = self._compute_column_stats(df[column])
|
|
306
|
+
|
|
307
|
+
return response
|
|
308
|
+
|
|
309
|
+
def _generate_eda_summary(self, df_name: str) -> Optional[Dict[str, Any]]:
|
|
310
|
+
"""
|
|
311
|
+
Generate comprehensive exploratory data analysis summary for a DataFrame.
|
|
312
|
+
|
|
313
|
+
This method generates EDA statistics dynamically from the actual DataFrame
|
|
314
|
+
if available, or falls back to pre-computed metadata.
|
|
315
|
+
|
|
316
|
+
Args:
|
|
317
|
+
df_name: DataFrame identifier
|
|
318
|
+
|
|
319
|
+
Returns:
|
|
320
|
+
Dictionary containing EDA summary or None if unavailable
|
|
321
|
+
"""
|
|
322
|
+
df = self.dataframes.get(df_name)
|
|
323
|
+
|
|
324
|
+
if df is None:
|
|
325
|
+
# Fallback to pre-computed EDA if available
|
|
326
|
+
df_meta = self.metadata.get(df_name, {})
|
|
327
|
+
if 'eda_summary' in df_meta:
|
|
328
|
+
return {"summary_text": df_meta['eda_summary']}
|
|
329
|
+
return None
|
|
330
|
+
|
|
331
|
+
# Generate fresh EDA from DataFrame
|
|
332
|
+
numeric_cols = df.select_dtypes(include=[np.number]).columns
|
|
333
|
+
categorical_cols = df.select_dtypes(include=['object', 'category']).columns
|
|
334
|
+
datetime_cols = df.select_dtypes(include=['datetime64']).columns
|
|
335
|
+
|
|
336
|
+
# Missing data analysis
|
|
337
|
+
missing = df.isnull().sum()
|
|
338
|
+
total_missing = int(missing.sum())
|
|
339
|
+
missing_percentage = float(missing.sum() / df.size * 100) if df.size > 0 else 0.0
|
|
340
|
+
|
|
341
|
+
# Memory usage
|
|
342
|
+
memory_mb = float(df.memory_usage(deep=True).sum() / 1024 / 1024)
|
|
343
|
+
|
|
344
|
+
# Columns with missing values
|
|
345
|
+
columns_with_missing = [
|
|
346
|
+
{
|
|
347
|
+
"column": col,
|
|
348
|
+
"missing_count": int(missing[col]),
|
|
349
|
+
"missing_percentage": float(missing[col] / len(df) * 100) if len(df) > 0 else 0.0
|
|
350
|
+
}
|
|
351
|
+
for col in df.columns
|
|
352
|
+
if missing[col] > 0
|
|
353
|
+
]
|
|
354
|
+
|
|
355
|
+
return {
|
|
356
|
+
"basic_info": {
|
|
357
|
+
"total_rows": len(df),
|
|
358
|
+
"total_columns": len(df.columns),
|
|
359
|
+
"numeric_columns": len(numeric_cols),
|
|
360
|
+
"categorical_columns": len(categorical_cols),
|
|
361
|
+
"datetime_columns": len(datetime_cols),
|
|
362
|
+
"memory_usage_mb": round(memory_mb, 2),
|
|
363
|
+
},
|
|
364
|
+
"missing_data": {
|
|
365
|
+
"total_missing": total_missing,
|
|
366
|
+
"missing_percentage": round(missing_percentage, 2),
|
|
367
|
+
"columns_with_missing": columns_with_missing
|
|
368
|
+
},
|
|
369
|
+
"data_quality": {
|
|
370
|
+
"duplicate_rows": int(df.duplicated().sum()),
|
|
371
|
+
"completeness_percentage": round((1 - missing_percentage / 100) * 100, 2)
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
def _generate_column_statistics(self, df_name: str) -> Optional[Dict[str, Any]]:
|
|
376
|
+
"""
|
|
377
|
+
Generate detailed statistics for all columns in a DataFrame.
|
|
378
|
+
|
|
379
|
+
Args:
|
|
380
|
+
df_name: DataFrame identifier
|
|
381
|
+
|
|
382
|
+
Returns:
|
|
383
|
+
Dictionary with column statistics or None
|
|
384
|
+
"""
|
|
385
|
+
df = self.dataframes.get(df_name)
|
|
386
|
+
if df is None:
|
|
387
|
+
return None
|
|
388
|
+
|
|
389
|
+
numeric_cols = df.select_dtypes(include=[np.number]).columns
|
|
390
|
+
categorical_cols = df.select_dtypes(include=['object', 'category']).columns
|
|
391
|
+
|
|
392
|
+
stats = {
|
|
393
|
+
"numeric_columns": {},
|
|
394
|
+
"categorical_columns": {}
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
# Numeric column statistics
|
|
398
|
+
for col in numeric_cols:
|
|
399
|
+
stats["numeric_columns"][col] = self._compute_column_stats(df[col])
|
|
400
|
+
|
|
401
|
+
# Categorical column statistics
|
|
402
|
+
for col in categorical_cols:
|
|
403
|
+
value_counts = df[col].value_counts()
|
|
404
|
+
stats["categorical_columns"][col] = {
|
|
405
|
+
"unique_values": int(df[col].nunique()),
|
|
406
|
+
"most_common": value_counts.head(10).to_dict(),
|
|
407
|
+
"null_count": int(df[col].isnull().sum())
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
return stats
|
|
411
|
+
|
|
412
|
+
def _compute_column_stats(self, series: pd.Series) -> Dict[str, Any]:
|
|
413
|
+
"""
|
|
414
|
+
Compute statistics for a single column/series.
|
|
415
|
+
|
|
416
|
+
Args:
|
|
417
|
+
series: pandas Series to analyze
|
|
418
|
+
|
|
419
|
+
Returns:
|
|
420
|
+
Dictionary of column statistics
|
|
421
|
+
"""
|
|
422
|
+
stats = {
|
|
423
|
+
"dtype": str(series.dtype),
|
|
424
|
+
"null_count": int(series.isnull().sum()),
|
|
425
|
+
"null_percentage": round(float(series.isnull().sum() / len(series) * 100), 2) if len(series) > 0 else 0.0
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
if pd.api.types.is_numeric_dtype(series):
|
|
429
|
+
# Numeric statistics
|
|
430
|
+
stats |= {
|
|
431
|
+
"mean": None if series.empty else float(series.mean()),
|
|
432
|
+
"median": None if series.empty else float(series.median()),
|
|
433
|
+
"std": None if series.empty else float(series.std()),
|
|
434
|
+
"min": None if series.empty else float(series.min()),
|
|
435
|
+
"max": None if series.empty else float(series.max()),
|
|
436
|
+
"q25": None if series.empty else float(series.quantile(0.25)),
|
|
437
|
+
"q75": None if series.empty else float(series.quantile(0.75)),
|
|
438
|
+
}
|
|
439
|
+
else:
|
|
440
|
+
# Categorical/string statistics
|
|
441
|
+
stats |= {
|
|
442
|
+
"unique_values": int(series.nunique()),
|
|
443
|
+
"most_common": None if series.mode().empty else str(series.mode().iloc[0]),
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
return stats
|
|
447
|
+
|
|
448
|
+
def _resolve_dataframe_name(self, identifier: str) -> str:
|
|
449
|
+
"""
|
|
450
|
+
Resolve either a standardized key (df1) or original name to metadata key.
|
|
451
|
+
|
|
452
|
+
Args:
|
|
453
|
+
identifier: DataFrame name or alias
|
|
454
|
+
|
|
455
|
+
Returns:
|
|
456
|
+
Resolved DataFrame name
|
|
457
|
+
"""
|
|
458
|
+
# Direct match
|
|
459
|
+
if identifier in self.metadata:
|
|
460
|
+
return identifier
|
|
461
|
+
|
|
462
|
+
# Alias match (df1 -> actual_name)
|
|
463
|
+
for name, alias in self.alias_map.items():
|
|
464
|
+
if alias == identifier:
|
|
465
|
+
return name
|
|
466
|
+
|
|
467
|
+
# Case-insensitive match
|
|
468
|
+
identifier_lower = identifier.lower()
|
|
469
|
+
return next(
|
|
470
|
+
(
|
|
471
|
+
name
|
|
472
|
+
for name in self.metadata.keys()
|
|
473
|
+
if name.lower() == identifier_lower
|
|
474
|
+
),
|
|
475
|
+
identifier,
|
|
476
|
+
)
|