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/bots/document.py
ADDED
|
@@ -0,0 +1,680 @@
|
|
|
1
|
+
"""
|
|
2
|
+
DocumentAgent - Specialized agent for document processing without Langchain.
|
|
3
|
+
|
|
4
|
+
Migrated from NotebookAgent to use native Parrot architecture:
|
|
5
|
+
- Extends BasicAgent from parrot.bots.agent
|
|
6
|
+
- Uses AbstractTool-based tools (WordToMarkdownTool, GoogleVoiceTool, ExcelTool)
|
|
7
|
+
- Native conversation() and invoke() methods
|
|
8
|
+
- Async-first architecture
|
|
9
|
+
- Integrated with ToolManager
|
|
10
|
+
"""
|
|
11
|
+
import os
|
|
12
|
+
import re
|
|
13
|
+
import json
|
|
14
|
+
from pathlib import Path
|
|
15
|
+
from datetime import datetime, timezone
|
|
16
|
+
from typing import List, Optional, Dict, Any, Union
|
|
17
|
+
from navconfig import BASE_DIR
|
|
18
|
+
from navconfig.logging import logging
|
|
19
|
+
|
|
20
|
+
from parrot.conf import BASE_STATIC_URL
|
|
21
|
+
from parrot.bots.agent import BasicAgent
|
|
22
|
+
from parrot.tools.abstract import AbstractTool
|
|
23
|
+
from parrot.tools.excel import ExcelTool
|
|
24
|
+
from parrot.tools.msword import WordToMarkdownTool, MSWordTool
|
|
25
|
+
from parrot.tools.gvoice import GoogleVoiceTool
|
|
26
|
+
from parrot.models.responses import AIMessage, AgentResponse
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
# Define format instructions
|
|
30
|
+
FORMAT_INSTRUCTIONS = """
|
|
31
|
+
FORMAT INSTRUCTIONS:
|
|
32
|
+
When responding to user queries, follow these formatting guidelines:
|
|
33
|
+
1. Use markdown for structured responses
|
|
34
|
+
2. Use bullet points for lists
|
|
35
|
+
3. Use headers for sections (# for main headers, ## for subheaders)
|
|
36
|
+
4. Include code blocks with triple backticks when showing code
|
|
37
|
+
5. Format tables using markdown table syntax
|
|
38
|
+
6. For document analysis, highlight key findings and insights
|
|
39
|
+
7. When generating summaries, organize by main themes or sections
|
|
40
|
+
"""
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
# System prompt for document processing
|
|
44
|
+
DOCUMENT_AGENT_SYSTEM_PROMPT = """You are {name}, a document assistant specialized in analysis,
|
|
45
|
+
summarization, and extraction of key information from text documents.
|
|
46
|
+
|
|
47
|
+
Current date: {today_date}
|
|
48
|
+
|
|
49
|
+
## Your Capabilities
|
|
50
|
+
|
|
51
|
+
You have access to the following tools:
|
|
52
|
+
{tools_list}
|
|
53
|
+
|
|
54
|
+
## Document Analysis Guidelines
|
|
55
|
+
|
|
56
|
+
When analyzing documents, follow these comprehensive guidelines:
|
|
57
|
+
|
|
58
|
+
1. **Document Conversion and Processing**
|
|
59
|
+
- Use word_to_markdown_tool to convert Word documents to Markdown format
|
|
60
|
+
- Use excel_tool to work with Excel spreadsheets
|
|
61
|
+
- Process the resulting markdown to identify structure, sections, and key elements
|
|
62
|
+
- Preserve document formatting and structure when relevant to understanding
|
|
63
|
+
|
|
64
|
+
2. **Content Analysis**
|
|
65
|
+
- Identify key themes, topics, and main arguments in the document
|
|
66
|
+
- Extract important facts, figures, quotes, and statistics
|
|
67
|
+
- Recognize patterns in the content and logical structure
|
|
68
|
+
- Analyze tone, style, and language used in the document
|
|
69
|
+
|
|
70
|
+
3. **Summarization Techniques**
|
|
71
|
+
- Create executive summaries capturing the essential points
|
|
72
|
+
- Develop section-by-section summaries for longer documents
|
|
73
|
+
- Use bullet points for key takeaways
|
|
74
|
+
- Preserve the author's original intent and meaning
|
|
75
|
+
- Highlight the most important insights and conclusions
|
|
76
|
+
|
|
77
|
+
4. **Audio Narration**
|
|
78
|
+
- When requested, generate clear, well-structured audio summaries
|
|
79
|
+
- Format text for natural-sounding speech using google_tts_service tool
|
|
80
|
+
- Structure narration with clear introduction, body, and conclusion
|
|
81
|
+
- Use transitions between major points and sections
|
|
82
|
+
- Emphasize key information through pacing and structure
|
|
83
|
+
|
|
84
|
+
5. **Special Document Elements**
|
|
85
|
+
- Properly handle tables, charts, and figures by describing their content
|
|
86
|
+
- Extract and process lists, bullet points, and numbered items
|
|
87
|
+
- Identify and analyze headers, footers, and metadata
|
|
88
|
+
- Process citations, references, and bibliographic information
|
|
89
|
+
|
|
90
|
+
6. **Output Formatting**
|
|
91
|
+
- Use markdown formatting for structured responses
|
|
92
|
+
- Organize information hierarchically with headers and subheaders
|
|
93
|
+
- Present extracted information in tables when appropriate
|
|
94
|
+
- Use code blocks for technical content or examples
|
|
95
|
+
- Highlight key quotes or important excerpts
|
|
96
|
+
|
|
97
|
+
{format_instructions}
|
|
98
|
+
|
|
99
|
+
Always begin by understanding what the user wants to do with their document.
|
|
100
|
+
Ask for clarification if needed. Be helpful, professional, and thorough in your document analysis.
|
|
101
|
+
"""
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
class DocumentAgent(BasicAgent):
|
|
105
|
+
"""
|
|
106
|
+
A specialized agent for document processing - converting Word docs to Markdown,
|
|
107
|
+
analyzing content, processing Excel files, and generating narrated summaries.
|
|
108
|
+
|
|
109
|
+
This agent extends BasicAgent and integrates document-specific tools without
|
|
110
|
+
relying on Langchain dependencies.
|
|
111
|
+
"""
|
|
112
|
+
|
|
113
|
+
def __init__(
|
|
114
|
+
self,
|
|
115
|
+
name: str = 'Document Assistant',
|
|
116
|
+
llm: Optional[str] = None,
|
|
117
|
+
tools: List[AbstractTool] = None,
|
|
118
|
+
system_prompt: str = None,
|
|
119
|
+
document_url: Optional[str] = None,
|
|
120
|
+
**kwargs
|
|
121
|
+
):
|
|
122
|
+
"""
|
|
123
|
+
Initialize the DocumentAgent.
|
|
124
|
+
|
|
125
|
+
Args:
|
|
126
|
+
name: Agent name
|
|
127
|
+
llm: LLM client to use (e.g., 'google', 'openai', 'anthropic')
|
|
128
|
+
tools: List of tools to use (will add document tools automatically)
|
|
129
|
+
system_prompt: Custom system prompt (uses default if None)
|
|
130
|
+
document_url: Optional URL to a document to process
|
|
131
|
+
**kwargs: Additional arguments for BasicAgent
|
|
132
|
+
"""
|
|
133
|
+
self._document_url = document_url
|
|
134
|
+
self._document_content = None
|
|
135
|
+
self._document_metadata = {}
|
|
136
|
+
|
|
137
|
+
# Format instructions
|
|
138
|
+
self._format_instructions: str = kwargs.pop('format_instructions', FORMAT_INSTRUCTIONS)
|
|
139
|
+
|
|
140
|
+
# Set up directories for outputs
|
|
141
|
+
self._static_path = BASE_DIR.joinpath('static', self.agent_id)
|
|
142
|
+
self.agent_audio_dir = self._static_path.joinpath('audio', 'agents')
|
|
143
|
+
self.agent_docs_dir = self._static_path.joinpath('docs', 'agents')
|
|
144
|
+
|
|
145
|
+
# Ensure directories exist
|
|
146
|
+
os.makedirs(str(self.agent_audio_dir), exist_ok=True)
|
|
147
|
+
os.makedirs(str(self.agent_docs_dir), exist_ok=True)
|
|
148
|
+
|
|
149
|
+
# Initialize logger
|
|
150
|
+
self.logger = logging.getLogger(f'Parrot.DocumentAgent.{name}')
|
|
151
|
+
|
|
152
|
+
# Initialize tools list if None
|
|
153
|
+
if tools is None:
|
|
154
|
+
tools = []
|
|
155
|
+
|
|
156
|
+
# Add document-specific tools
|
|
157
|
+
self._init_document_tools(tools)
|
|
158
|
+
|
|
159
|
+
# Create system prompt
|
|
160
|
+
if system_prompt is None:
|
|
161
|
+
system_prompt = self._create_system_prompt()
|
|
162
|
+
|
|
163
|
+
# Initialize parent BasicAgent
|
|
164
|
+
super().__init__(
|
|
165
|
+
name=name,
|
|
166
|
+
llm=llm,
|
|
167
|
+
system_prompt=system_prompt,
|
|
168
|
+
tools=tools,
|
|
169
|
+
**kwargs
|
|
170
|
+
)
|
|
171
|
+
|
|
172
|
+
self.description = (
|
|
173
|
+
"A specialized agent for document processing, analysis, and summarization. "
|
|
174
|
+
"Can convert Word documents to Markdown, process Excel files, and generate audio summaries."
|
|
175
|
+
)
|
|
176
|
+
|
|
177
|
+
def _init_document_tools(self, tools: List[AbstractTool]) -> None:
|
|
178
|
+
"""Initialize document-specific tools if not already present."""
|
|
179
|
+
# Check existing tools
|
|
180
|
+
tool_names = {tool.name for tool in tools}
|
|
181
|
+
|
|
182
|
+
# Add MSWordTool if not present
|
|
183
|
+
if "ms_word_tool" not in tool_names:
|
|
184
|
+
try:
|
|
185
|
+
msword_tool = MSWordTool(
|
|
186
|
+
output_dir=str(self.agent_docs_dir)
|
|
187
|
+
)
|
|
188
|
+
tools.append(msword_tool)
|
|
189
|
+
self.logger.info("Added MSWordTool")
|
|
190
|
+
except Exception as e:
|
|
191
|
+
self.logger.warning(f"Could not add MSWordTool: {e}")
|
|
192
|
+
|
|
193
|
+
# Add WordToMarkdownTool if not present
|
|
194
|
+
if "word_to_markdown_tool" not in tool_names:
|
|
195
|
+
try:
|
|
196
|
+
word_tool = WordToMarkdownTool()
|
|
197
|
+
tools.append(word_tool)
|
|
198
|
+
self.logger.info("Added WordToMarkdownTool")
|
|
199
|
+
except Exception as e:
|
|
200
|
+
self.logger.warning(f"Could not add WordToMarkdownTool: {e}")
|
|
201
|
+
|
|
202
|
+
# Add GoogleVoiceTool (TTS) if not present
|
|
203
|
+
if "google_tts_service" not in tool_names:
|
|
204
|
+
try:
|
|
205
|
+
voice_tool = GoogleVoiceTool(
|
|
206
|
+
output_dir=str(self.agent_audio_dir)
|
|
207
|
+
)
|
|
208
|
+
tools.append(voice_tool)
|
|
209
|
+
self.logger.info(f"Added GoogleVoiceTool with name: {voice_tool.name}")
|
|
210
|
+
except Exception as e:
|
|
211
|
+
self.logger.warning(f"Could not add GoogleVoiceTool: {e}")
|
|
212
|
+
|
|
213
|
+
# Add ExcelTool if available and not present
|
|
214
|
+
if "excel_tool" not in tool_names:
|
|
215
|
+
try:
|
|
216
|
+
excel_tool = ExcelTool(
|
|
217
|
+
output_dir=str(self.agent_docs_dir)
|
|
218
|
+
)
|
|
219
|
+
tools.append(excel_tool)
|
|
220
|
+
self.logger.info("Added ExcelTool")
|
|
221
|
+
except ImportError:
|
|
222
|
+
self.logger.debug("ExcelTool not available")
|
|
223
|
+
except Exception as e:
|
|
224
|
+
self.logger.warning(f"Could not add ExcelTool: {e}")
|
|
225
|
+
|
|
226
|
+
def _create_system_prompt(self) -> str:
|
|
227
|
+
"""Create the system prompt for the document agent."""
|
|
228
|
+
now = datetime.now(timezone.utc).strftime("%Y-%m-%d")
|
|
229
|
+
|
|
230
|
+
# Build tools list
|
|
231
|
+
tools_list = ""
|
|
232
|
+
for tool in self.tools:
|
|
233
|
+
tools_list += f"- **{tool.name}**: {tool.description}\n"
|
|
234
|
+
|
|
235
|
+
# Format the prompt
|
|
236
|
+
system_prompt = DOCUMENT_AGENT_SYSTEM_PROMPT.format(
|
|
237
|
+
name=self.name,
|
|
238
|
+
today_date=now,
|
|
239
|
+
tools_list=tools_list,
|
|
240
|
+
format_instructions=self._format_instructions
|
|
241
|
+
)
|
|
242
|
+
|
|
243
|
+
return system_prompt
|
|
244
|
+
|
|
245
|
+
async def configure(self, app=None) -> None:
|
|
246
|
+
"""
|
|
247
|
+
Configure the DocumentAgent with necessary setup.
|
|
248
|
+
|
|
249
|
+
Args:
|
|
250
|
+
app: Optional aiohttp application for web integrations
|
|
251
|
+
"""
|
|
252
|
+
await super().configure(app)
|
|
253
|
+
self.logger.info(f"DocumentAgent '{self.name}' configured with {len(self.tools)} tools")
|
|
254
|
+
|
|
255
|
+
async def load_document(self, url: str) -> Dict[str, Any]:
|
|
256
|
+
"""
|
|
257
|
+
Load a document from a URL using WordToMarkdownTool.
|
|
258
|
+
|
|
259
|
+
Args:
|
|
260
|
+
url: URL of the Word document to load
|
|
261
|
+
|
|
262
|
+
Returns:
|
|
263
|
+
Dictionary with document content and metadata
|
|
264
|
+
"""
|
|
265
|
+
if not url:
|
|
266
|
+
return {"error": "No document URL provided", "success": False}
|
|
267
|
+
|
|
268
|
+
# Find the Word tool
|
|
269
|
+
word_tool = self.get_tool("word_to_markdown_tool")
|
|
270
|
+
|
|
271
|
+
if not word_tool:
|
|
272
|
+
return {"error": "WordToMarkdownTool not available", "success": False}
|
|
273
|
+
|
|
274
|
+
try:
|
|
275
|
+
# Use the tool to load and convert the document
|
|
276
|
+
result = await word_tool._arun(url)
|
|
277
|
+
|
|
278
|
+
if isinstance(result, str):
|
|
279
|
+
try:
|
|
280
|
+
result = json.loads(result)
|
|
281
|
+
except:
|
|
282
|
+
result = {"markdown": result}
|
|
283
|
+
|
|
284
|
+
if not result.get("success", False):
|
|
285
|
+
return {
|
|
286
|
+
"error": result.get("error", "Unknown error loading document"),
|
|
287
|
+
"success": False
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
self._document_content = result.get("markdown", "")
|
|
291
|
+
self._document_metadata = {
|
|
292
|
+
"source_url": url,
|
|
293
|
+
"loaded_at": datetime.now().isoformat(),
|
|
294
|
+
"format": "markdown"
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
self.logger.info(
|
|
298
|
+
f"Document loaded successfully: {len(self._document_content)} characters"
|
|
299
|
+
)
|
|
300
|
+
|
|
301
|
+
return {
|
|
302
|
+
"content": self._document_content,
|
|
303
|
+
"metadata": self._document_metadata,
|
|
304
|
+
"success": True
|
|
305
|
+
}
|
|
306
|
+
except Exception as e:
|
|
307
|
+
self.logger.error(f"Error loading document: {e}")
|
|
308
|
+
return {"error": f"Error loading document: {str(e)}", "success": False}
|
|
309
|
+
|
|
310
|
+
async def generate_summary(self, max_length: int = 500) -> Dict[str, Any]:
|
|
311
|
+
"""
|
|
312
|
+
Generate a summary of the loaded document using the LLM.
|
|
313
|
+
|
|
314
|
+
Args:
|
|
315
|
+
max_length: Maximum length hint for summary (not strict)
|
|
316
|
+
|
|
317
|
+
Returns:
|
|
318
|
+
Dictionary with summary text and success status
|
|
319
|
+
"""
|
|
320
|
+
if not self._document_content:
|
|
321
|
+
self.logger.error("No document content available to summarize")
|
|
322
|
+
return {"error": "No document content available to summarize", "success": False}
|
|
323
|
+
|
|
324
|
+
content_length = len(self._document_content)
|
|
325
|
+
self.logger.info(f"Generating summary for document with {content_length} characters")
|
|
326
|
+
|
|
327
|
+
try:
|
|
328
|
+
# Create summarization prompt
|
|
329
|
+
prompt = f"""
|
|
330
|
+
Please analyze this document and create a comprehensive summary.
|
|
331
|
+
|
|
332
|
+
{self._document_content[:15000]} # Limit to ~15k chars to avoid token issues
|
|
333
|
+
|
|
334
|
+
Your summary should:
|
|
335
|
+
1. Capture the main points and themes
|
|
336
|
+
2. Be well-structured with headers for major sections
|
|
337
|
+
3. Use bullet points for key details when appropriate
|
|
338
|
+
4. Be suitable for audio narration (clear and flowing)
|
|
339
|
+
5. Highlight the most important insights and conclusions
|
|
340
|
+
|
|
341
|
+
Focus on providing value and clarity in your summary.
|
|
342
|
+
"""
|
|
343
|
+
|
|
344
|
+
# Use the agent's conversation method for context-aware summarization
|
|
345
|
+
response = await self.invoke(
|
|
346
|
+
question=prompt,
|
|
347
|
+
user_id="document_processor",
|
|
348
|
+
session_id=f"doc_summary_{datetime.now().timestamp()}",
|
|
349
|
+
use_conversation_history=False # Stateless for summary
|
|
350
|
+
)
|
|
351
|
+
|
|
352
|
+
if isinstance(response, AIMessage):
|
|
353
|
+
summary_text = response.content
|
|
354
|
+
elif isinstance(response, AgentResponse):
|
|
355
|
+
summary_text = response.output
|
|
356
|
+
else:
|
|
357
|
+
summary_text = str(response)
|
|
358
|
+
|
|
359
|
+
if not summary_text or len(summary_text.strip()) < 10:
|
|
360
|
+
self.logger.warning("Generated summary is too short or empty")
|
|
361
|
+
return {"error": "Failed to generate summary", "success": False}
|
|
362
|
+
|
|
363
|
+
self.logger.info(f"Summary generated successfully: {len(summary_text)} characters")
|
|
364
|
+
|
|
365
|
+
return {
|
|
366
|
+
"summary": summary_text,
|
|
367
|
+
"success": True
|
|
368
|
+
}
|
|
369
|
+
except Exception as e:
|
|
370
|
+
self.logger.error(f"Error generating summary: {e}", exc_info=True)
|
|
371
|
+
return {"error": f"Error generating summary: {str(e)}", "success": False}
|
|
372
|
+
|
|
373
|
+
async def _preprocess_text_for_speech(self, text: str) -> str:
|
|
374
|
+
"""
|
|
375
|
+
Preprocess text to make it suitable for speech synthesis.
|
|
376
|
+
Removes Markdown formatting while preserving natural flow.
|
|
377
|
+
|
|
378
|
+
Args:
|
|
379
|
+
text: Text in Markdown format
|
|
380
|
+
|
|
381
|
+
Returns:
|
|
382
|
+
Clean text optimized for speech synthesis
|
|
383
|
+
"""
|
|
384
|
+
# Remove bold/italic marks without adding explanatory text
|
|
385
|
+
text = re.sub(r'\*\*(.*?)\*\*', r'\1', text) # Remove **bold**
|
|
386
|
+
text = re.sub(r'\*(.*?)\*', r'\1', text) # Remove *italic*
|
|
387
|
+
text = re.sub(r'__(.*?)__', r'\1', text) # Remove __bold__
|
|
388
|
+
text = re.sub(r'_(.*?)_', r'\1', text) # Remove _italic_
|
|
389
|
+
|
|
390
|
+
# Improve lists for natural speech
|
|
391
|
+
text = re.sub(r'^\s*[\*\-\+]\s+', '', text, flags=re.MULTILINE) # Unordered lists
|
|
392
|
+
text = re.sub(r'^\s*(\d+)\.\s+', '', text, flags=re.MULTILINE) # Numbered lists
|
|
393
|
+
|
|
394
|
+
# Convert headers maintaining original text
|
|
395
|
+
text = re.sub(r'^#{1,6}\s+(.*)', r'\1', text, flags=re.MULTILINE)
|
|
396
|
+
|
|
397
|
+
# Clean other Markdown elements
|
|
398
|
+
text = re.sub(r'\[(.*?)\]\(.*?\)', r'\1', text) # Links: keep only text
|
|
399
|
+
text = re.sub(r'`(.*?)`', r'\1', text) # Remove `code`
|
|
400
|
+
text = re.sub(r'~~(.*?)~~', r'\1', text) # Remove ~~strikethrough~~
|
|
401
|
+
|
|
402
|
+
# Remove code blocks
|
|
403
|
+
text = re.sub(r'```.*?```', '', text, flags=re.DOTALL)
|
|
404
|
+
|
|
405
|
+
# Remove special characters
|
|
406
|
+
text = re.sub(r'[|]', ' ', text) # Remove pipes (common in tables)
|
|
407
|
+
|
|
408
|
+
# Handle colons and bullets for better flow
|
|
409
|
+
text = re.sub(r':\s*\n', '. ', text) # Convert ":" followed by newline to period
|
|
410
|
+
|
|
411
|
+
# Add natural pauses after paragraphs
|
|
412
|
+
text = re.sub(r'\n{2,}', '. ', text)
|
|
413
|
+
|
|
414
|
+
# Normalize spaces and punctuation
|
|
415
|
+
text = re.sub(r'\s{2,}', ' ', text) # Limit consecutive spaces
|
|
416
|
+
text = re.sub(r'\.{2,}', '.', text) # Convert multiple periods to one
|
|
417
|
+
text = re.sub(r'\.\s*\.', '.', text) # Remove double periods
|
|
418
|
+
|
|
419
|
+
# Ensure space after punctuation
|
|
420
|
+
text = re.sub(r'([.!?])\s+([A-Z])', r'\1 \2', text)
|
|
421
|
+
|
|
422
|
+
self.logger.debug(f"Preprocessed text for speech: {len(text)} characters")
|
|
423
|
+
|
|
424
|
+
return text.strip()
|
|
425
|
+
|
|
426
|
+
async def generate_audio(
|
|
427
|
+
self,
|
|
428
|
+
text: str,
|
|
429
|
+
voice_gender: str = "FEMALE",
|
|
430
|
+
language_code: str = "en-US"
|
|
431
|
+
) -> Dict[str, Any]:
|
|
432
|
+
"""
|
|
433
|
+
Generate audio narration from text using GoogleVoiceTool.
|
|
434
|
+
|
|
435
|
+
Args:
|
|
436
|
+
text: Text to convert to audio
|
|
437
|
+
voice_gender: Gender of the voice (MALE or FEMALE)
|
|
438
|
+
language_code: BCP-47 language code (e.g., 'en-US', 'es-ES')
|
|
439
|
+
|
|
440
|
+
Returns:
|
|
441
|
+
Dictionary with audio file information
|
|
442
|
+
"""
|
|
443
|
+
try:
|
|
444
|
+
# Find the voice tool
|
|
445
|
+
voice_tool = self.get_tool("google_tts_service")
|
|
446
|
+
|
|
447
|
+
if not voice_tool:
|
|
448
|
+
self.logger.error("Google TTS tool not found")
|
|
449
|
+
available_tools = [t.name for t in self.tools]
|
|
450
|
+
self.logger.info(f"Available tools: {', '.join(available_tools)}")
|
|
451
|
+
return {"error": "Google TTS tool not available", "success": False}
|
|
452
|
+
|
|
453
|
+
# Preprocess text for speech
|
|
454
|
+
self.logger.info("Preprocessing text for speech synthesis...")
|
|
455
|
+
processed_text = await self._preprocess_text_for_speech(text)
|
|
456
|
+
|
|
457
|
+
self.logger.info(f"Generating audio using {voice_tool.name}...")
|
|
458
|
+
|
|
459
|
+
# Call the tool with proper parameters
|
|
460
|
+
result = await voice_tool._arun(
|
|
461
|
+
text=processed_text,
|
|
462
|
+
voice_gender=voice_gender,
|
|
463
|
+
language_code=language_code,
|
|
464
|
+
file_prefix="document_summary"
|
|
465
|
+
)
|
|
466
|
+
|
|
467
|
+
# Process result
|
|
468
|
+
if isinstance(result, str):
|
|
469
|
+
try:
|
|
470
|
+
result = json.loads(result)
|
|
471
|
+
except:
|
|
472
|
+
result = {"message": result}
|
|
473
|
+
|
|
474
|
+
self.logger.info(f"Voice tool result: {result}")
|
|
475
|
+
|
|
476
|
+
# Verify file exists and construct URL
|
|
477
|
+
if "file_path" in result and os.path.exists(result["file_path"]):
|
|
478
|
+
file_path = result["file_path"]
|
|
479
|
+
# Construct URL for web access
|
|
480
|
+
url = str(file_path).replace(str(self._static_path), BASE_STATIC_URL)
|
|
481
|
+
result["url"] = url
|
|
482
|
+
result["filename"] = os.path.basename(file_path)
|
|
483
|
+
result["success"] = True
|
|
484
|
+
self.logger.info(f"Audio generated successfully at: {file_path}")
|
|
485
|
+
self.logger.info(f"Audio URL: {url}")
|
|
486
|
+
else:
|
|
487
|
+
self.logger.warning("Audio file path not found in result or file doesn't exist")
|
|
488
|
+
if "file_path" in result:
|
|
489
|
+
self.logger.debug(f"Expected path: {result['file_path']}")
|
|
490
|
+
result["success"] = False
|
|
491
|
+
|
|
492
|
+
return result
|
|
493
|
+
except Exception as e:
|
|
494
|
+
self.logger.error(f"Error generating audio: {e}", exc_info=True)
|
|
495
|
+
return {"error": f"Error generating audio: {str(e)}", "success": False}
|
|
496
|
+
|
|
497
|
+
async def process_document_workflow(
|
|
498
|
+
self,
|
|
499
|
+
document_url: str,
|
|
500
|
+
generate_audio_summary: bool = True
|
|
501
|
+
) -> Dict[str, Any]:
|
|
502
|
+
"""
|
|
503
|
+
Run a complete document processing workflow:
|
|
504
|
+
1. Load and convert document
|
|
505
|
+
2. Generate a summary
|
|
506
|
+
3. Optionally create an audio narration
|
|
507
|
+
|
|
508
|
+
Args:
|
|
509
|
+
document_url: URL to the Word document
|
|
510
|
+
generate_audio_summary: Whether to generate audio narration
|
|
511
|
+
|
|
512
|
+
Returns:
|
|
513
|
+
Dictionary with document content, summary, and optional audio information
|
|
514
|
+
"""
|
|
515
|
+
self.logger.info(f"Starting document workflow for: {document_url}")
|
|
516
|
+
|
|
517
|
+
# Step 1: Load the document
|
|
518
|
+
document_result = await self.load_document(document_url)
|
|
519
|
+
|
|
520
|
+
if not document_result.get("success"):
|
|
521
|
+
return document_result
|
|
522
|
+
|
|
523
|
+
# Step 2: Generate summary
|
|
524
|
+
try:
|
|
525
|
+
summary_result = await self.generate_summary()
|
|
526
|
+
except Exception as e:
|
|
527
|
+
self.logger.error(f"Error generating summary: {e}")
|
|
528
|
+
summary_result = {"error": str(e), "summary": "", "success": False}
|
|
529
|
+
|
|
530
|
+
# Combine results
|
|
531
|
+
workflow_result = {
|
|
532
|
+
"document": {
|
|
533
|
+
"content_preview": (
|
|
534
|
+
self._document_content[:500] + "..."
|
|
535
|
+
if len(self._document_content) > 500
|
|
536
|
+
else self._document_content
|
|
537
|
+
),
|
|
538
|
+
"full_content_length": len(self._document_content),
|
|
539
|
+
"metadata": self._document_metadata
|
|
540
|
+
},
|
|
541
|
+
"summary": summary_result.get("summary", ""),
|
|
542
|
+
"success": summary_result.get("success", False)
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
# Step 3: Generate audio if requested and summary succeeded
|
|
546
|
+
if generate_audio_summary and summary_result.get("success"):
|
|
547
|
+
try:
|
|
548
|
+
audio_result = await self.generate_audio(summary_result["summary"])
|
|
549
|
+
workflow_result["audio"] = audio_result
|
|
550
|
+
except Exception as e:
|
|
551
|
+
self.logger.error(f"Error generating audio: {e}")
|
|
552
|
+
workflow_result["audio"] = {"error": str(e), "success": False}
|
|
553
|
+
|
|
554
|
+
return workflow_result
|
|
555
|
+
|
|
556
|
+
def extract_filenames(self, response: Union[AIMessage, AgentResponse]) -> Dict[str, Dict[str, Any]]:
|
|
557
|
+
"""
|
|
558
|
+
Extract filenames from agent response.
|
|
559
|
+
|
|
560
|
+
Args:
|
|
561
|
+
response: Agent response object
|
|
562
|
+
|
|
563
|
+
Returns:
|
|
564
|
+
Dictionary mapping filenames to their metadata
|
|
565
|
+
"""
|
|
566
|
+
if isinstance(response, AIMessage):
|
|
567
|
+
output = response.content
|
|
568
|
+
elif isinstance(response, AgentResponse):
|
|
569
|
+
output = response.output
|
|
570
|
+
else:
|
|
571
|
+
output = str(response)
|
|
572
|
+
|
|
573
|
+
# Split the content by lines
|
|
574
|
+
output_lines = output.splitlines()
|
|
575
|
+
filenames = {}
|
|
576
|
+
|
|
577
|
+
for line in output_lines:
|
|
578
|
+
if 'filename:' in line.lower():
|
|
579
|
+
filename = line.split('filename:')[1].strip()
|
|
580
|
+
if filename:
|
|
581
|
+
try:
|
|
582
|
+
filename_path = Path(filename).resolve()
|
|
583
|
+
if filename_path.is_file():
|
|
584
|
+
content_type = self._mimetype_from_ext(filename_path.suffix)
|
|
585
|
+
url = str(filename_path).replace(str(self._static_path), BASE_STATIC_URL)
|
|
586
|
+
filenames[filename_path.name] = {
|
|
587
|
+
'content_type': content_type,
|
|
588
|
+
'file_path': str(filename_path),
|
|
589
|
+
'filename': filename_path.name,
|
|
590
|
+
'url': url
|
|
591
|
+
}
|
|
592
|
+
except (AttributeError, OSError):
|
|
593
|
+
pass
|
|
594
|
+
|
|
595
|
+
return filenames
|
|
596
|
+
|
|
597
|
+
def _mimetype_from_ext(self, ext: str) -> str:
|
|
598
|
+
"""Get the MIME type from file extension."""
|
|
599
|
+
mime_types = {
|
|
600
|
+
'.csv': 'text/csv',
|
|
601
|
+
'.xlsx': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
|
|
602
|
+
'.xls': 'application/vnd.ms-excel',
|
|
603
|
+
'.json': 'application/json',
|
|
604
|
+
'.txt': 'text/plain',
|
|
605
|
+
'.html': 'text/html',
|
|
606
|
+
'.htm': 'text/html',
|
|
607
|
+
'.pdf': 'application/pdf',
|
|
608
|
+
'.png': 'image/png',
|
|
609
|
+
'.jpg': 'image/jpeg',
|
|
610
|
+
'.jpeg': 'image/jpeg',
|
|
611
|
+
'.gif': 'image/gif',
|
|
612
|
+
'.svg': 'image/svg+xml',
|
|
613
|
+
'.md': 'text/markdown',
|
|
614
|
+
'.ogg': 'audio/ogg',
|
|
615
|
+
'.wav': 'audio/wav',
|
|
616
|
+
'.mp3': 'audio/mpeg',
|
|
617
|
+
'.mp4': 'video/mp4',
|
|
618
|
+
'.docx': 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
|
|
619
|
+
}
|
|
620
|
+
return mime_types.get(ext.lower(), 'application/octet-stream')
|
|
621
|
+
|
|
622
|
+
async def analyze_document(
|
|
623
|
+
self,
|
|
624
|
+
document_url: str,
|
|
625
|
+
analysis_type: str = "comprehensive"
|
|
626
|
+
) -> Dict[str, Any]:
|
|
627
|
+
"""
|
|
628
|
+
Analyze a document with specific analysis type.
|
|
629
|
+
|
|
630
|
+
Args:
|
|
631
|
+
document_url: URL to the document
|
|
632
|
+
analysis_type: Type of analysis ('comprehensive', 'summary', 'key_points', 'themes')
|
|
633
|
+
|
|
634
|
+
Returns:
|
|
635
|
+
Analysis results
|
|
636
|
+
"""
|
|
637
|
+
# Load document if not already loaded
|
|
638
|
+
if not self._document_content or self._document_metadata.get("source_url") != document_url:
|
|
639
|
+
load_result = await self.load_document(document_url)
|
|
640
|
+
if not load_result.get("success"):
|
|
641
|
+
return load_result
|
|
642
|
+
|
|
643
|
+
# Create analysis prompt based on type
|
|
644
|
+
analysis_prompts = {
|
|
645
|
+
"comprehensive": "Provide a comprehensive analysis of this document, including themes, key arguments, evidence, and conclusions.",
|
|
646
|
+
"summary": "Provide a concise summary of the main points in this document.",
|
|
647
|
+
"key_points": "Extract and list the key points, facts, and takeaways from this document.",
|
|
648
|
+
"themes": "Identify and analyze the main themes and topics discussed in this document."
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
prompt = f"""{analysis_prompts.get(analysis_type, analysis_prompts['comprehensive'])}
|
|
652
|
+
|
|
653
|
+
Document Content:
|
|
654
|
+
{self._document_content[:10000]}
|
|
655
|
+
"""
|
|
656
|
+
|
|
657
|
+
try:
|
|
658
|
+
response = await self.invoke(
|
|
659
|
+
question=prompt,
|
|
660
|
+
user_id="document_analyzer",
|
|
661
|
+
session_id=f"analysis_{datetime.now().timestamp()}",
|
|
662
|
+
use_conversation_history=False
|
|
663
|
+
)
|
|
664
|
+
|
|
665
|
+
if isinstance(response, AIMessage):
|
|
666
|
+
analysis = response.content
|
|
667
|
+
elif isinstance(response, AgentResponse):
|
|
668
|
+
analysis = response.output
|
|
669
|
+
else:
|
|
670
|
+
analysis = str(response)
|
|
671
|
+
|
|
672
|
+
return {
|
|
673
|
+
"analysis_type": analysis_type,
|
|
674
|
+
"analysis": analysis,
|
|
675
|
+
"document_metadata": self._document_metadata,
|
|
676
|
+
"success": True
|
|
677
|
+
}
|
|
678
|
+
except Exception as e:
|
|
679
|
+
self.logger.error(f"Error analyzing document: {e}", exc_info=True)
|
|
680
|
+
return {"error": f"Error analyzing document: {str(e)}", "success": False}
|
parrot/bots/hrbot.py
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
from .chatbot import Chatbot
|
|
2
|
+
|
|
3
|
+
class HRAgent(Chatbot):
|
|
4
|
+
"""Represents an Human Resources agent in Navigator.
|
|
5
|
+
|
|
6
|
+
Each agent has a name, a role, a goal, a backstory,
|
|
7
|
+
and an optional language model (llm).
|
|
8
|
+
"""
|
|
9
|
+
name: str = 'TROCers'
|
|
10
|
+
company: str = 'T-ROC Global'
|
|
11
|
+
company_website: str = 'https://www.trocglobal.com'
|
|
12
|
+
contact_information = 'communications@trocglobal.com'
|
|
13
|
+
contact_form = 'https://www.surveymonkey.com/r/TROC_Suggestion_Box'
|
|
14
|
+
role: str = 'Human Resources Assistant'
|
|
15
|
+
goal = 'Bring useful information to employees'
|