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
|
@@ -0,0 +1,437 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Correlation Analysis Tool - Analyze correlations between a key column and other columns.
|
|
3
|
+
"""
|
|
4
|
+
from typing import Any, Dict, Optional, List
|
|
5
|
+
from enum import Enum
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
from datetime import datetime
|
|
8
|
+
import base64
|
|
9
|
+
import io
|
|
10
|
+
import matplotlib
|
|
11
|
+
import matplotlib.pyplot as plt
|
|
12
|
+
import seaborn as sns
|
|
13
|
+
import pandas as pd
|
|
14
|
+
import numpy as np
|
|
15
|
+
from pydantic import BaseModel, Field
|
|
16
|
+
from .abstract import AbstractTool
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
matplotlib.use('Agg') # Use non-interactive backend
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class CorrelationMethod(str, Enum):
|
|
23
|
+
"""Available correlation methods."""
|
|
24
|
+
PEARSON = "pearson"
|
|
25
|
+
SPEARMAN = "spearman"
|
|
26
|
+
KENDALL = "kendall"
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class OutputFormat(str, Enum):
|
|
30
|
+
"""Available output formats."""
|
|
31
|
+
JSON = "json"
|
|
32
|
+
DATAFRAME = "dataframe"
|
|
33
|
+
HEATMAP = "heatmap"
|
|
34
|
+
ALL = "all"
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
class CorrelationAnalysisArgs(BaseModel):
|
|
38
|
+
"""Arguments schema for Correlation Analysis."""
|
|
39
|
+
|
|
40
|
+
dataframe: Any = Field(
|
|
41
|
+
description="Pandas DataFrame to analyze"
|
|
42
|
+
)
|
|
43
|
+
key_column: str = Field(
|
|
44
|
+
description="Column name to use as the key for correlation comparison"
|
|
45
|
+
)
|
|
46
|
+
comparison_columns: Optional[List[str]] = Field(
|
|
47
|
+
default=None,
|
|
48
|
+
description="List of column names to compare with key column. If None, uses all numeric columns except key column"
|
|
49
|
+
)
|
|
50
|
+
correlation_method: CorrelationMethod = Field(
|
|
51
|
+
default=CorrelationMethod.PEARSON,
|
|
52
|
+
description="Correlation method to use: pearson, spearman, or kendall"
|
|
53
|
+
)
|
|
54
|
+
output_format: OutputFormat = Field(
|
|
55
|
+
default=OutputFormat.ALL,
|
|
56
|
+
description="Output format: json, dataframe, heatmap, or all"
|
|
57
|
+
)
|
|
58
|
+
min_correlation_threshold: float = Field(
|
|
59
|
+
default=0.0,
|
|
60
|
+
description="Minimum absolute correlation value to include in results"
|
|
61
|
+
)
|
|
62
|
+
sort_by_correlation: bool = Field(
|
|
63
|
+
default=True,
|
|
64
|
+
description="Sort results by absolute correlation value (descending)"
|
|
65
|
+
)
|
|
66
|
+
exclude_self_correlation: bool = Field(
|
|
67
|
+
default=True,
|
|
68
|
+
description="Exclude the key column from correlation with itself"
|
|
69
|
+
)
|
|
70
|
+
filename: Optional[str] = Field(
|
|
71
|
+
default=None,
|
|
72
|
+
description="Optional filename to save the heatmap (without extension)"
|
|
73
|
+
)
|
|
74
|
+
heatmap_style: str = Field(
|
|
75
|
+
default="coolwarm",
|
|
76
|
+
description="Color map for heatmap: coolwarm, viridis, plasma, etc."
|
|
77
|
+
)
|
|
78
|
+
figure_size: tuple = Field(
|
|
79
|
+
default=(10, 8),
|
|
80
|
+
description="Figure size for heatmap (width, height)"
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
class CorrelationAnalysisTool(AbstractTool):
|
|
85
|
+
"""
|
|
86
|
+
Tool for analyzing correlations between a key column and other columns in a DataFrame.
|
|
87
|
+
|
|
88
|
+
This tool helps identify relationships between a target variable and potential
|
|
89
|
+
predictor variables, useful for business analytics, feature selection, and
|
|
90
|
+
exploratory data analysis.
|
|
91
|
+
"""
|
|
92
|
+
|
|
93
|
+
name: str = "correlation_analysis"
|
|
94
|
+
description: str = "Analyze correlations between a key column and other columns in a DataFrame"
|
|
95
|
+
args_schema = CorrelationAnalysisArgs
|
|
96
|
+
return_direct: bool = False
|
|
97
|
+
|
|
98
|
+
def _default_output_dir(self) -> Optional[Path]:
|
|
99
|
+
"""Default output directory for correlation analysis results."""
|
|
100
|
+
return self.static_dir / "correlation_analysis" if self.static_dir else None
|
|
101
|
+
|
|
102
|
+
def _calculate_correlations(
|
|
103
|
+
self,
|
|
104
|
+
df: pd.DataFrame,
|
|
105
|
+
key_column: str,
|
|
106
|
+
comparison_columns: List[str],
|
|
107
|
+
method: str
|
|
108
|
+
) -> pd.Series:
|
|
109
|
+
"""
|
|
110
|
+
Calculate correlations between key column and comparison columns.
|
|
111
|
+
|
|
112
|
+
Args:
|
|
113
|
+
df: DataFrame to analyze
|
|
114
|
+
key_column: Key column name
|
|
115
|
+
comparison_columns: List of columns to compare with
|
|
116
|
+
method: Correlation method
|
|
117
|
+
|
|
118
|
+
Returns:
|
|
119
|
+
Series with correlation values
|
|
120
|
+
"""
|
|
121
|
+
correlations = {}
|
|
122
|
+
key_data = df[key_column]
|
|
123
|
+
|
|
124
|
+
for col in comparison_columns:
|
|
125
|
+
try:
|
|
126
|
+
# Skip if column doesn't exist
|
|
127
|
+
if col not in df.columns:
|
|
128
|
+
self.logger.warning(f"Column '{col}' not found in DataFrame")
|
|
129
|
+
continue
|
|
130
|
+
|
|
131
|
+
# Skip non-numeric columns for pearson correlation
|
|
132
|
+
if method == 'pearson' and not pd.api.types.is_numeric_dtype(df[col]):
|
|
133
|
+
self.logger.info(f"Skipping non-numeric column '{col}' for Pearson correlation")
|
|
134
|
+
continue
|
|
135
|
+
|
|
136
|
+
# Calculate correlation
|
|
137
|
+
corr_value = key_data.corr(df[col], method=method)
|
|
138
|
+
|
|
139
|
+
# Handle NaN correlations
|
|
140
|
+
if pd.isna(corr_value):
|
|
141
|
+
self.logger.warning(f"Correlation between '{key_column}' and '{col}' is NaN")
|
|
142
|
+
correlations[col] = 0.0
|
|
143
|
+
else:
|
|
144
|
+
correlations[col] = corr_value
|
|
145
|
+
|
|
146
|
+
except Exception as e:
|
|
147
|
+
self.logger.error(f"Error calculating correlation for column '{col}': {e}")
|
|
148
|
+
correlations[col] = 0.0
|
|
149
|
+
|
|
150
|
+
return pd.Series(correlations)
|
|
151
|
+
|
|
152
|
+
def _create_correlation_heatmap(
|
|
153
|
+
self,
|
|
154
|
+
correlations: pd.Series,
|
|
155
|
+
key_column: str,
|
|
156
|
+
style: str = "coolwarm",
|
|
157
|
+
figure_size: tuple = (10, 8)
|
|
158
|
+
) -> str:
|
|
159
|
+
"""
|
|
160
|
+
Create a correlation heatmap.
|
|
161
|
+
|
|
162
|
+
Args:
|
|
163
|
+
correlations: Series with correlation values
|
|
164
|
+
key_column: Name of the key column
|
|
165
|
+
style: Color map style
|
|
166
|
+
figure_size: Figure size tuple
|
|
167
|
+
|
|
168
|
+
Returns:
|
|
169
|
+
Base64 encoded image string
|
|
170
|
+
"""
|
|
171
|
+
try:
|
|
172
|
+
# Create figure
|
|
173
|
+
fig, ax = plt.subplots(figsize=figure_size)
|
|
174
|
+
|
|
175
|
+
# Prepare data for heatmap
|
|
176
|
+
# Create a matrix with key column vs other columns
|
|
177
|
+
corr_matrix = correlations.to_frame(name=key_column).T
|
|
178
|
+
|
|
179
|
+
# Create heatmap
|
|
180
|
+
sns.heatmap(
|
|
181
|
+
corr_matrix,
|
|
182
|
+
annot=True,
|
|
183
|
+
cmap=style,
|
|
184
|
+
center=0,
|
|
185
|
+
fmt='.3f',
|
|
186
|
+
cbar_kws={'label': 'Correlation Coefficient'},
|
|
187
|
+
ax=ax
|
|
188
|
+
)
|
|
189
|
+
|
|
190
|
+
ax.set_title(f'Correlation Analysis: {key_column} vs Other Variables',
|
|
191
|
+
fontsize=14, fontweight='bold', pad=20)
|
|
192
|
+
ax.set_xlabel('Variables', fontsize=12)
|
|
193
|
+
ax.set_ylabel('Key Variable', fontsize=12)
|
|
194
|
+
|
|
195
|
+
# Rotate x-axis labels for better readability
|
|
196
|
+
plt.xticks(rotation=45, ha='right')
|
|
197
|
+
plt.tight_layout()
|
|
198
|
+
|
|
199
|
+
# Convert to base64
|
|
200
|
+
buf = io.BytesIO()
|
|
201
|
+
fig.savefig(buf, format='png', dpi=150, bbox_inches='tight', facecolor='white')
|
|
202
|
+
buf.seek(0)
|
|
203
|
+
img_base64 = base64.b64encode(buf.read()).decode('utf-8')
|
|
204
|
+
buf.close()
|
|
205
|
+
plt.close(fig)
|
|
206
|
+
|
|
207
|
+
return img_base64
|
|
208
|
+
|
|
209
|
+
except Exception as e:
|
|
210
|
+
self.logger.error(f"Error creating heatmap: {e}")
|
|
211
|
+
return ""
|
|
212
|
+
|
|
213
|
+
def _create_bar_chart(
|
|
214
|
+
self,
|
|
215
|
+
correlations: pd.Series,
|
|
216
|
+
key_column: str,
|
|
217
|
+
figure_size: tuple = (12, 6)
|
|
218
|
+
) -> str:
|
|
219
|
+
"""
|
|
220
|
+
Create a bar chart of correlations.
|
|
221
|
+
|
|
222
|
+
Args:
|
|
223
|
+
correlations: Series with correlation values
|
|
224
|
+
key_column: Name of the key column
|
|
225
|
+
figure_size: Figure size tuple
|
|
226
|
+
|
|
227
|
+
Returns:
|
|
228
|
+
Base64 encoded image string
|
|
229
|
+
"""
|
|
230
|
+
try:
|
|
231
|
+
# Sort by absolute correlation value
|
|
232
|
+
sorted_corr = correlations.reindex(
|
|
233
|
+
correlations.abs().sort_values(ascending=True).index
|
|
234
|
+
)
|
|
235
|
+
|
|
236
|
+
# Create figure
|
|
237
|
+
fig, ax = plt.subplots(figsize=figure_size)
|
|
238
|
+
|
|
239
|
+
# Create bar chart
|
|
240
|
+
colors = ['red' if x < 0 else 'blue' for x in sorted_corr.values]
|
|
241
|
+
bars = ax.barh(range(len(sorted_corr)), sorted_corr.values, color=colors, alpha=0.7)
|
|
242
|
+
|
|
243
|
+
# Customize chart
|
|
244
|
+
ax.set_yticks(range(len(sorted_corr)))
|
|
245
|
+
ax.set_yticklabels(sorted_corr.index)
|
|
246
|
+
ax.set_xlabel('Correlation Coefficient')
|
|
247
|
+
ax.set_title(f'Correlation Analysis: {key_column} vs Other Variables',
|
|
248
|
+
fontsize=14, fontweight='bold')
|
|
249
|
+
ax.axvline(x=0, color='black', linestyle='-', alpha=0.3)
|
|
250
|
+
ax.grid(True, alpha=0.3)
|
|
251
|
+
|
|
252
|
+
# Add value labels on bars
|
|
253
|
+
for i, (bar, value) in enumerate(zip(bars, sorted_corr.values)):
|
|
254
|
+
ax.text(value + (0.01 if value >= 0 else -0.01), i, f'{value:.3f}',
|
|
255
|
+
ha='left' if value >= 0 else 'right', va='center')
|
|
256
|
+
|
|
257
|
+
plt.tight_layout()
|
|
258
|
+
|
|
259
|
+
# Convert to base64
|
|
260
|
+
buf = io.BytesIO()
|
|
261
|
+
fig.savefig(buf, format='png', dpi=150, bbox_inches='tight', facecolor='white')
|
|
262
|
+
buf.seek(0)
|
|
263
|
+
img_base64 = base64.b64encode(buf.read()).decode('utf-8')
|
|
264
|
+
buf.close()
|
|
265
|
+
plt.close(fig)
|
|
266
|
+
|
|
267
|
+
return img_base64
|
|
268
|
+
|
|
269
|
+
except Exception as e:
|
|
270
|
+
self.logger.error(f"Error creating bar chart: {e}")
|
|
271
|
+
return ""
|
|
272
|
+
|
|
273
|
+
async def _execute(
|
|
274
|
+
self,
|
|
275
|
+
dataframe: pd.DataFrame,
|
|
276
|
+
key_column: str,
|
|
277
|
+
comparison_columns: Optional[List[str]] = None,
|
|
278
|
+
correlation_method: CorrelationMethod = CorrelationMethod.PEARSON,
|
|
279
|
+
output_format: OutputFormat = OutputFormat.ALL,
|
|
280
|
+
min_correlation_threshold: float = 0.0,
|
|
281
|
+
sort_by_correlation: bool = True,
|
|
282
|
+
exclude_self_correlation: bool = True,
|
|
283
|
+
filename: Optional[str] = None,
|
|
284
|
+
heatmap_style: str = "coolwarm",
|
|
285
|
+
figure_size: tuple = (10, 8),
|
|
286
|
+
**kwargs
|
|
287
|
+
) -> Dict[str, Any]:
|
|
288
|
+
"""
|
|
289
|
+
Execute correlation analysis.
|
|
290
|
+
|
|
291
|
+
Returns:
|
|
292
|
+
Dictionary containing correlation results in requested formats
|
|
293
|
+
"""
|
|
294
|
+
|
|
295
|
+
# Validate input
|
|
296
|
+
if not isinstance(dataframe, pd.DataFrame):
|
|
297
|
+
raise ValueError("Input must be a pandas DataFrame")
|
|
298
|
+
|
|
299
|
+
if dataframe.empty:
|
|
300
|
+
raise ValueError("DataFrame is empty")
|
|
301
|
+
|
|
302
|
+
if key_column not in dataframe.columns:
|
|
303
|
+
raise ValueError(f"Key column '{key_column}' not found in DataFrame")
|
|
304
|
+
|
|
305
|
+
# Check if key column is numeric for pearson correlation
|
|
306
|
+
if correlation_method == CorrelationMethod.PEARSON and not pd.api.types.is_numeric_dtype(dataframe[key_column]):
|
|
307
|
+
raise ValueError(f"Key column '{key_column}' must be numeric for Pearson correlation")
|
|
308
|
+
|
|
309
|
+
self.logger.info(f"Starting correlation analysis for key column: {key_column}")
|
|
310
|
+
|
|
311
|
+
# Determine comparison columns
|
|
312
|
+
if comparison_columns is None:
|
|
313
|
+
# Use all numeric columns except the key column
|
|
314
|
+
numeric_columns = dataframe.select_dtypes(include=[np.number]).columns.tolist()
|
|
315
|
+
comparison_columns = [col for col in numeric_columns if col != key_column]
|
|
316
|
+
self.logger.info(f"Using all numeric columns except key: {len(comparison_columns)} columns")
|
|
317
|
+
else:
|
|
318
|
+
# Validate provided columns
|
|
319
|
+
missing_columns = [col for col in comparison_columns if col not in dataframe.columns]
|
|
320
|
+
if missing_columns:
|
|
321
|
+
raise ValueError(f"Columns not found in DataFrame: {missing_columns}")
|
|
322
|
+
|
|
323
|
+
# Exclude self-correlation if requested
|
|
324
|
+
if exclude_self_correlation and key_column in comparison_columns:
|
|
325
|
+
comparison_columns = [col for col in comparison_columns if col != key_column]
|
|
326
|
+
|
|
327
|
+
if not comparison_columns:
|
|
328
|
+
raise ValueError("No valid comparison columns found")
|
|
329
|
+
|
|
330
|
+
# Calculate correlations
|
|
331
|
+
correlations = self._calculate_correlations(
|
|
332
|
+
dataframe, key_column, comparison_columns, correlation_method.value
|
|
333
|
+
)
|
|
334
|
+
|
|
335
|
+
# Apply minimum threshold filter
|
|
336
|
+
if min_correlation_threshold > 0:
|
|
337
|
+
correlations = correlations[correlations.abs() >= min_correlation_threshold]
|
|
338
|
+
self.logger.info(f"Filtered to {len(correlations)} correlations above threshold {min_correlation_threshold}")
|
|
339
|
+
|
|
340
|
+
# Sort by correlation if requested
|
|
341
|
+
if sort_by_correlation:
|
|
342
|
+
correlations = correlations.reindex(correlations.abs().sort_values(ascending=False).index)
|
|
343
|
+
|
|
344
|
+
# Generate timestamp
|
|
345
|
+
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
|
|
346
|
+
|
|
347
|
+
# Prepare base result
|
|
348
|
+
result = {
|
|
349
|
+
"key_column": key_column,
|
|
350
|
+
"correlation_method": correlation_method.value,
|
|
351
|
+
"comparison_columns_count": len(comparison_columns),
|
|
352
|
+
"valid_correlations_count": len(correlations),
|
|
353
|
+
"timestamp": timestamp,
|
|
354
|
+
"analysis_summary": {
|
|
355
|
+
"highest_positive_correlation": {
|
|
356
|
+
"column": correlations.idxmax() if len(correlations) > 0 else None,
|
|
357
|
+
"value": correlations.max() if len(correlations) > 0 else None
|
|
358
|
+
},
|
|
359
|
+
"highest_negative_correlation": {
|
|
360
|
+
"column": correlations.idxmin() if len(correlations) > 0 else None,
|
|
361
|
+
"value": correlations.min() if len(correlations) > 0 else None
|
|
362
|
+
},
|
|
363
|
+
"mean_absolute_correlation": correlations.abs().mean() if len(correlations) > 0 else 0,
|
|
364
|
+
"strong_correlations_count": len(correlations[correlations.abs() >= 0.7]) if len(correlations) > 0 else 0
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
# Generate outputs based on requested format
|
|
369
|
+
if output_format in [OutputFormat.JSON, OutputFormat.ALL]:
|
|
370
|
+
result["json_output"] = {
|
|
371
|
+
"correlations": correlations.to_dict(),
|
|
372
|
+
"sorted_correlations": [
|
|
373
|
+
{"column": col, "correlation": float(corr)}
|
|
374
|
+
for col, corr in correlations.items()
|
|
375
|
+
]
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
if output_format in [OutputFormat.DATAFRAME, OutputFormat.ALL]:
|
|
379
|
+
correlation_df = pd.DataFrame({
|
|
380
|
+
'column': correlations.index,
|
|
381
|
+
'correlation': correlations.values,
|
|
382
|
+
'abs_correlation': correlations.abs().values
|
|
383
|
+
}).reset_index(drop=True)
|
|
384
|
+
|
|
385
|
+
result["dataframe_output"] = {
|
|
386
|
+
"correlation_dataframe": correlation_df.to_dict('records'),
|
|
387
|
+
"dataframe_shape": correlation_df.shape,
|
|
388
|
+
"dataframe_html": correlation_df.to_html(classes='correlation-table', table_id='correlation-results')
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
if output_format in [OutputFormat.HEATMAP, OutputFormat.ALL]:
|
|
392
|
+
# Create heatmap
|
|
393
|
+
heatmap_b64 = self._create_correlation_heatmap(
|
|
394
|
+
correlations, key_column, heatmap_style, figure_size
|
|
395
|
+
)
|
|
396
|
+
|
|
397
|
+
# Create bar chart
|
|
398
|
+
bar_chart_b64 = self._create_bar_chart(correlations, key_column, figure_size)
|
|
399
|
+
|
|
400
|
+
result["heatmap_output"] = {
|
|
401
|
+
"heatmap_image": heatmap_b64,
|
|
402
|
+
"bar_chart_image": bar_chart_b64,
|
|
403
|
+
"heatmap_style": heatmap_style,
|
|
404
|
+
"figure_size": figure_size
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
# Save heatmap to file if filename provided
|
|
408
|
+
if filename and heatmap_b64:
|
|
409
|
+
try:
|
|
410
|
+
if not filename.endswith('.png'):
|
|
411
|
+
filename = f"{filename}_{timestamp}.png"
|
|
412
|
+
|
|
413
|
+
# Ensure output directory exists
|
|
414
|
+
if self.output_dir:
|
|
415
|
+
self.output_dir.mkdir(parents=True, exist_ok=True)
|
|
416
|
+
file_path = self.output_dir / filename
|
|
417
|
+
else:
|
|
418
|
+
file_path = Path(filename)
|
|
419
|
+
|
|
420
|
+
# Decode and save image
|
|
421
|
+
img_data = base64.b64decode(heatmap_b64)
|
|
422
|
+
with open(file_path, 'wb') as f:
|
|
423
|
+
f.write(img_data)
|
|
424
|
+
|
|
425
|
+
self.logger.info(f"Heatmap saved to: {file_path}")
|
|
426
|
+
|
|
427
|
+
result["heatmap_output"].update({
|
|
428
|
+
"file_path": str(file_path),
|
|
429
|
+
"file_url": self.to_static_url(file_path),
|
|
430
|
+
"file_size": file_path.stat().st_size
|
|
431
|
+
})
|
|
432
|
+
|
|
433
|
+
except Exception as e:
|
|
434
|
+
self.logger.error(f"Failed to save heatmap: {e}")
|
|
435
|
+
result["heatmap_output"]["save_error"] = str(e)
|
|
436
|
+
|
|
437
|
+
return result
|