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/basic.py
ADDED
parrot/bots/chatbot.py
ADDED
|
@@ -0,0 +1,669 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Foundational base of every Chatbot and Agent in ai-parrot.
|
|
3
|
+
"""
|
|
4
|
+
from typing import Any, Union, Dict, List, Optional, ClassVar
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
import uuid
|
|
7
|
+
from string import Template
|
|
8
|
+
import importlib
|
|
9
|
+
import asyncio
|
|
10
|
+
from contextlib import asynccontextmanager
|
|
11
|
+
# Navconfig
|
|
12
|
+
from datamodel.exceptions import ValidationError # pylint: disable=E0611
|
|
13
|
+
from navconfig import BASE_DIR
|
|
14
|
+
from navconfig.exceptions import ConfigError # pylint: disable=E0611
|
|
15
|
+
from asyncdb.exceptions import NoDataFound
|
|
16
|
+
from asyncdb import AsyncPool
|
|
17
|
+
from ..conf import (
|
|
18
|
+
default_dsn,
|
|
19
|
+
EMBEDDING_DEFAULT_MODEL,
|
|
20
|
+
KB_DEFAULT_MODEL
|
|
21
|
+
)
|
|
22
|
+
from ..handlers.models import BotModel
|
|
23
|
+
from .abstract import AbstractBot
|
|
24
|
+
from ..tools import (
|
|
25
|
+
AbstractTool,
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
class Chatbot(AbstractBot):
|
|
29
|
+
"""Represents an Bot (Chatbot, Agent) in Navigator.
|
|
30
|
+
|
|
31
|
+
This class is the base for all chatbots and agents in the ai-parrot framework.
|
|
32
|
+
|
|
33
|
+
This class can be used in two ways:
|
|
34
|
+
1. Manual creation: bot = Chatbot(name="MyBot", tools=[...])
|
|
35
|
+
2. Database loading: bot = Chatbot(name="MyBot", from_database=True)
|
|
36
|
+
"""
|
|
37
|
+
company_information: dict = {}
|
|
38
|
+
# Shared database pool for BotModel operations
|
|
39
|
+
_db_pool: ClassVar[Optional[AsyncPool]] = None
|
|
40
|
+
_db_pool_lock: ClassVar[asyncio.Lock] = asyncio.Lock()
|
|
41
|
+
|
|
42
|
+
def __init__(
|
|
43
|
+
self,
|
|
44
|
+
name: str = 'Nav',
|
|
45
|
+
system_prompt: str = None,
|
|
46
|
+
human_prompt: str = None,
|
|
47
|
+
from_database: bool = True,
|
|
48
|
+
tools: List[Union[str, AbstractTool]] = None,
|
|
49
|
+
**kwargs
|
|
50
|
+
):
|
|
51
|
+
"""
|
|
52
|
+
Initialize the Chatbot with manual creation or database loading support.
|
|
53
|
+
|
|
54
|
+
Args:
|
|
55
|
+
name: Bot name
|
|
56
|
+
system_prompt: Custom system prompt
|
|
57
|
+
human_prompt: Custom human prompt
|
|
58
|
+
from_database: Whether to load configuration from database
|
|
59
|
+
tools: List of tools for manual creation
|
|
60
|
+
**kwargs: Additional configuration
|
|
61
|
+
"""
|
|
62
|
+
# Other Configuration
|
|
63
|
+
self.confidence_threshold: float = kwargs.get('threshold', 0.5)
|
|
64
|
+
self._from_database: bool = from_database
|
|
65
|
+
self._max_tools: int = kwargs.get('max_tools', 10)
|
|
66
|
+
# Text Documents
|
|
67
|
+
self.documents_dir: Path = kwargs.get(
|
|
68
|
+
'documents_dir',
|
|
69
|
+
None
|
|
70
|
+
)
|
|
71
|
+
# Company Information:
|
|
72
|
+
self.company_information = kwargs.get(
|
|
73
|
+
'company_information',
|
|
74
|
+
self.company_information
|
|
75
|
+
)
|
|
76
|
+
# Tool configuration
|
|
77
|
+
self.available_tool_instances: Dict[str, Any] = {}
|
|
78
|
+
super().__init__(
|
|
79
|
+
name=name,
|
|
80
|
+
system_prompt=system_prompt,
|
|
81
|
+
human_prompt=human_prompt,
|
|
82
|
+
tools= tools,
|
|
83
|
+
**kwargs
|
|
84
|
+
)
|
|
85
|
+
if isinstance(self.documents_dir, str):
|
|
86
|
+
self.documents_dir = Path(self.documents_dir)
|
|
87
|
+
if not self.documents_dir:
|
|
88
|
+
self.documents_dir = BASE_DIR.joinpath('documents')
|
|
89
|
+
if not self.documents_dir.exists():
|
|
90
|
+
self.documents_dir.mkdir(
|
|
91
|
+
parents=True,
|
|
92
|
+
exist_ok=True
|
|
93
|
+
)
|
|
94
|
+
|
|
95
|
+
# ------------------------------------------------------------------
|
|
96
|
+
# Database helpers
|
|
97
|
+
# ------------------------------------------------------------------
|
|
98
|
+
@classmethod
|
|
99
|
+
async def _get_db_pool(cls) -> AsyncPool:
|
|
100
|
+
"""Return a shared async database pool for bot metadata."""
|
|
101
|
+
if not default_dsn:
|
|
102
|
+
raise ConfigError(
|
|
103
|
+
"Database DSN is not configured; cannot load bots from database"
|
|
104
|
+
)
|
|
105
|
+
|
|
106
|
+
pool = cls._db_pool
|
|
107
|
+
if pool is not None and pool.is_connected() and not pool.event_loop_is_closed():
|
|
108
|
+
return pool
|
|
109
|
+
|
|
110
|
+
async with cls._db_pool_lock:
|
|
111
|
+
pool = cls._db_pool
|
|
112
|
+
if pool is not None and pool.is_connected() and not pool.event_loop_is_closed():
|
|
113
|
+
return pool
|
|
114
|
+
|
|
115
|
+
pool = AsyncPool('pg', dsn=default_dsn)
|
|
116
|
+
await pool.connect() # pylint: disable=E1101 # noqa
|
|
117
|
+
cls._db_pool = pool
|
|
118
|
+
return pool
|
|
119
|
+
|
|
120
|
+
@classmethod
|
|
121
|
+
@asynccontextmanager
|
|
122
|
+
async def _botmodel_connection(cls):
|
|
123
|
+
"""Context manager that yields a pooled connection for BotModel operations."""
|
|
124
|
+
pool = await cls._get_db_pool()
|
|
125
|
+
connection = None
|
|
126
|
+
try:
|
|
127
|
+
connection = await pool.acquire()
|
|
128
|
+
yield connection
|
|
129
|
+
finally:
|
|
130
|
+
if connection is not None:
|
|
131
|
+
await pool.release(connection)
|
|
132
|
+
|
|
133
|
+
def __repr__(self):
|
|
134
|
+
return f"<{self.__class__.__name__}:{self.name}>"
|
|
135
|
+
|
|
136
|
+
async def configure(self, app=None) -> None:
|
|
137
|
+
"""Load configuration for this Chatbot."""
|
|
138
|
+
if self._from_database:
|
|
139
|
+
bot = None
|
|
140
|
+
try:
|
|
141
|
+
bot = await self.bot_exists(name=self.name, uuid=self.chatbot_id)
|
|
142
|
+
except Exception as exc: # pragma: no cover - defensive logging
|
|
143
|
+
self.logger.error(
|
|
144
|
+
(
|
|
145
|
+
f"Failed to load bot '{self.name}' metadata from database: {exc}. "
|
|
146
|
+
"Falling back to manual configuration."
|
|
147
|
+
),
|
|
148
|
+
exc_info=True,
|
|
149
|
+
)
|
|
150
|
+
if bot:
|
|
151
|
+
self.logger.notice(
|
|
152
|
+
f"Loading Bot {self.name} from Database: {bot.chatbot_id}"
|
|
153
|
+
)
|
|
154
|
+
# Bot exists on Database, Configure from the Database
|
|
155
|
+
await self.from_database(bot)
|
|
156
|
+
else:
|
|
157
|
+
self.logger.warning(
|
|
158
|
+
f"Bot {self.name} not found or database unavailable, falling back to manual configuration"
|
|
159
|
+
)
|
|
160
|
+
self._from_database = False
|
|
161
|
+
await self.from_manual_config()
|
|
162
|
+
else:
|
|
163
|
+
# Manual configuration
|
|
164
|
+
await self.from_manual_config()
|
|
165
|
+
# Call parent configuration
|
|
166
|
+
await super().configure(app)
|
|
167
|
+
|
|
168
|
+
def _from_bot(self, bot, key, config, default) -> Any:
|
|
169
|
+
value = getattr(bot, key, None)
|
|
170
|
+
file_value = config.get(key, default)
|
|
171
|
+
return value or file_value
|
|
172
|
+
|
|
173
|
+
def _from_db(self, botobj, key, default: str = None) -> Any:
|
|
174
|
+
value = getattr(botobj, key, default)
|
|
175
|
+
return value or default
|
|
176
|
+
|
|
177
|
+
def import_kb_class(self, kb_path: str):
|
|
178
|
+
try:
|
|
179
|
+
# Split the path to get module and class name
|
|
180
|
+
module_path, class_name = kb_path.rsplit('.', 1)
|
|
181
|
+
module = importlib.import_module(module_path)
|
|
182
|
+
return getattr(module, class_name)
|
|
183
|
+
except (ValueError, ImportError, AttributeError) as e:
|
|
184
|
+
self.logger.error(
|
|
185
|
+
f"Failed to import KB class from {kb_path}: {e}"
|
|
186
|
+
)
|
|
187
|
+
return None
|
|
188
|
+
|
|
189
|
+
async def from_manual_config(self) -> None:
|
|
190
|
+
"""
|
|
191
|
+
Configure the bot manually without database dependency.
|
|
192
|
+
"""
|
|
193
|
+
self.logger.info(f"Configuring bot {self.name} manually")
|
|
194
|
+
|
|
195
|
+
# Set up basic configuration with defaults
|
|
196
|
+
self.pre_instructions: list = getattr(self, 'pre_instructions', [])
|
|
197
|
+
self.description = getattr(self, 'description', f"AI Assistant: {self.name}")
|
|
198
|
+
self.role = getattr(self, 'role', 'AI Assistant')
|
|
199
|
+
self.goal = getattr(self, 'goal', 'Help users accomplish their tasks effectively')
|
|
200
|
+
self.rationale = getattr(self, 'rationale', 'Provide accurate and helpful information to users.')
|
|
201
|
+
self.backstory = getattr(self, 'backstory', 'I am an AI assistant created to help users with various tasks.')
|
|
202
|
+
self.capabilities = getattr(self, 'capabilities', 'I can engage in conversation, answer questions, and use tools when needed.')
|
|
203
|
+
|
|
204
|
+
# LLM Configuration with defaults
|
|
205
|
+
self._llm = getattr(self, '_llm', 'google')
|
|
206
|
+
self._llm_model = getattr(self, '_llm_model', None)
|
|
207
|
+
self._llm_temp = getattr(self, '_llm_temp', 0.1)
|
|
208
|
+
self._max_tokens = getattr(self, '_max_tokens', 8192)
|
|
209
|
+
self._top_k = getattr(self, '_top_k', 41)
|
|
210
|
+
self._top_p = getattr(self, '_top_p', 0.9)
|
|
211
|
+
self._llm_config = getattr(self, '_llm_config', {})
|
|
212
|
+
|
|
213
|
+
# Tool and agent configuration
|
|
214
|
+
self.auto_tool_detection = getattr(self, 'auto_tool_detection', True)
|
|
215
|
+
self.tool_threshold = getattr(self, 'tool_threshold', 0.7)
|
|
216
|
+
self.operation_mode = getattr(self, 'operation_mode', 'adaptive')
|
|
217
|
+
# Embedding Model Configuration
|
|
218
|
+
self.embedding_model: dict = getattr(self, 'embedding_model', {
|
|
219
|
+
'model_name': EMBEDDING_DEFAULT_MODEL,
|
|
220
|
+
'model_type': 'huggingface'
|
|
221
|
+
})
|
|
222
|
+
|
|
223
|
+
# Vector store configuration
|
|
224
|
+
self._use_vector = getattr(self, '_use_vector', False)
|
|
225
|
+
self._vector_store = getattr(self, '_vector_store', {})
|
|
226
|
+
self._metric_type = getattr(self, '_metric_type', 'COSINE')
|
|
227
|
+
|
|
228
|
+
# Memory and conversation configuration
|
|
229
|
+
self.memory_type = getattr(self, 'memory_type', 'memory')
|
|
230
|
+
self.memory_config = getattr(self, 'memory_config', {})
|
|
231
|
+
self.max_context_turns = getattr(self, 'max_context_turns', 5)
|
|
232
|
+
self.use_conversation_history = getattr(self, 'use_conversation_history', True)
|
|
233
|
+
|
|
234
|
+
# Context and retrieval settings
|
|
235
|
+
self.context_search_limit = getattr(self, 'context_search_limit', 10)
|
|
236
|
+
self.context_score_threshold = getattr(self, 'context_score_threshold', 0.7)
|
|
237
|
+
|
|
238
|
+
# Security and permissions
|
|
239
|
+
_default = self.default_permissions()
|
|
240
|
+
_permissions = getattr(self, '_permissions', {})
|
|
241
|
+
self._permissions = {**_default, **_permissions}
|
|
242
|
+
|
|
243
|
+
# Other settings
|
|
244
|
+
self.language = getattr(self, 'language', 'en')
|
|
245
|
+
self.disclaimer = getattr(self, 'disclaimer', None)
|
|
246
|
+
|
|
247
|
+
self.logger.info(
|
|
248
|
+
f"Manual configuration complete: "
|
|
249
|
+
f"tools_enabled={self.enable_tools}, "
|
|
250
|
+
f"operation_mode={self.operation_mode}, "
|
|
251
|
+
f"use_vector={self._use_vector}, "
|
|
252
|
+
f"tools_count={self.tool_manager.tool_count()}"
|
|
253
|
+
)
|
|
254
|
+
|
|
255
|
+
async def bot_exists(
|
|
256
|
+
self,
|
|
257
|
+
name: str = None,
|
|
258
|
+
uuid: uuid.UUID = None
|
|
259
|
+
) -> Union[BotModel, bool]:
|
|
260
|
+
"""Check if the Chatbot exists in the Database."""
|
|
261
|
+
try:
|
|
262
|
+
async with self._botmodel_connection() as conn: # pylint: disable=E1101
|
|
263
|
+
BotModel.Meta.connection = conn
|
|
264
|
+
try:
|
|
265
|
+
if self.chatbot_id:
|
|
266
|
+
try:
|
|
267
|
+
bot = await BotModel.get(chatbot_id=uuid, enabled=True)
|
|
268
|
+
except Exception:
|
|
269
|
+
bot = await BotModel.get(name=name, enabled=True)
|
|
270
|
+
else:
|
|
271
|
+
bot = await BotModel.get(name=self.name, enabled=True)
|
|
272
|
+
if bot:
|
|
273
|
+
return bot
|
|
274
|
+
except NoDataFound:
|
|
275
|
+
return False
|
|
276
|
+
except Exception as exc: # pragma: no cover - unexpected database error
|
|
277
|
+
self.logger.error(
|
|
278
|
+
f"Error retrieving bot from database: {exc}",
|
|
279
|
+
exc_info=True,
|
|
280
|
+
)
|
|
281
|
+
except Exception as exc: # pragma: no cover - database unavailable
|
|
282
|
+
self.logger.error(
|
|
283
|
+
f"Database error while checking bot existence: {exc}",
|
|
284
|
+
exc_info=True,
|
|
285
|
+
)
|
|
286
|
+
return False
|
|
287
|
+
|
|
288
|
+
async def from_database(
|
|
289
|
+
self,
|
|
290
|
+
bot: Union[BotModel, None] = None
|
|
291
|
+
) -> None:
|
|
292
|
+
"""
|
|
293
|
+
Load the Chatbot/Agent Configuration from the Database.
|
|
294
|
+
If the bot is not found, it will raise a ConfigError.
|
|
295
|
+
"""
|
|
296
|
+
if not bot:
|
|
297
|
+
async with self._botmodel_connection() as conn: # pylint: disable=E1101
|
|
298
|
+
# import model
|
|
299
|
+
BotModel.Meta.connection = conn
|
|
300
|
+
try:
|
|
301
|
+
if self.chatbot_id:
|
|
302
|
+
try:
|
|
303
|
+
bot = await BotModel.get(chatbot_id=self.chatbot_id)
|
|
304
|
+
except Exception:
|
|
305
|
+
bot = await BotModel.get(name=self.name)
|
|
306
|
+
else:
|
|
307
|
+
bot = await BotModel.get(name=self.name)
|
|
308
|
+
except ValidationError as ex:
|
|
309
|
+
# Handle ValidationError
|
|
310
|
+
self.logger.error(f"Validation error: {ex}")
|
|
311
|
+
raise ConfigError(
|
|
312
|
+
f"Chatbot {self.name} with errors: {ex.payload()}."
|
|
313
|
+
)
|
|
314
|
+
except NoDataFound:
|
|
315
|
+
# Fallback to File configuration:
|
|
316
|
+
raise ConfigError(
|
|
317
|
+
f"Chatbot {self.name} not found in the database."
|
|
318
|
+
)
|
|
319
|
+
|
|
320
|
+
# Start Bot configuration from Database:
|
|
321
|
+
self.pre_instructions: list = self._from_db(
|
|
322
|
+
bot, 'pre_instructions', default=[]
|
|
323
|
+
)
|
|
324
|
+
self.name = self._from_db(bot, 'name', default=self.name)
|
|
325
|
+
self.chatbot_id = str(self._from_db(bot, 'chatbot_id', default=self.chatbot_id))
|
|
326
|
+
self.description = self._from_db(bot, 'description', default=self.description)
|
|
327
|
+
|
|
328
|
+
# Bot personality and behavior
|
|
329
|
+
self.role = self._from_db(bot, 'role', default=self.role)
|
|
330
|
+
self.goal = self._from_db(bot, 'goal', default=self.goal)
|
|
331
|
+
self.rationale = self._from_db(bot, 'rationale', default=self.rationale)
|
|
332
|
+
self.backstory = self._from_db(bot, 'backstory', default=self.backstory)
|
|
333
|
+
self.capabilities = self._from_db(bot, 'capabilities', default='')
|
|
334
|
+
|
|
335
|
+
# Prompt configuration
|
|
336
|
+
if bot.system_prompt_template:
|
|
337
|
+
self.system_prompt_template = bot.system_prompt_template
|
|
338
|
+
if bot.human_prompt_template:
|
|
339
|
+
self.human_prompt_template = bot.human_prompt_template
|
|
340
|
+
|
|
341
|
+
# LLM Configuration
|
|
342
|
+
self._llm = self._from_db(bot, 'llm', default='google')
|
|
343
|
+
self._llm_model = self._from_db(bot, 'model', default='gemini-2.5-flash')
|
|
344
|
+
self._llm_temp = self._from_db(bot, 'temperature', default=0.1)
|
|
345
|
+
self._max_tokens = self._from_db(bot, 'max_tokens', default=1024)
|
|
346
|
+
self._top_k = self._from_db(bot, 'top_k', default=41)
|
|
347
|
+
self._top_p = self._from_db(bot, 'top_p', default=0.9)
|
|
348
|
+
self._llm_config = self._from_db(bot, 'model_config', default={})
|
|
349
|
+
|
|
350
|
+
# Tool and agent configuration
|
|
351
|
+
self.enable_tools = self._from_db(bot, 'tools_enabled', default=True)
|
|
352
|
+
self.auto_tool_detection = self._from_db(bot, 'auto_tool_detection', default=True)
|
|
353
|
+
self.tool_threshold = self._from_db(bot, 'tool_threshold', default=0.7)
|
|
354
|
+
self.operation_mode = self._from_db(bot, 'operation_mode', default='adaptive')
|
|
355
|
+
|
|
356
|
+
# Load tools from database
|
|
357
|
+
tool_names = self._from_db(bot, 'tools', default=[])
|
|
358
|
+
if tool_names and self.enable_tools:
|
|
359
|
+
self.tool_manager.register_tools(tool_names)
|
|
360
|
+
|
|
361
|
+
# Embedding Model Configuration
|
|
362
|
+
self.embedding_model: dict = self._from_db(
|
|
363
|
+
bot, 'embedding_model', default={
|
|
364
|
+
'model_name': EMBEDDING_DEFAULT_MODEL,
|
|
365
|
+
'model_type': 'huggingface'
|
|
366
|
+
}
|
|
367
|
+
)
|
|
368
|
+
|
|
369
|
+
# Vector store configuration
|
|
370
|
+
self._use_vector = self._from_db(bot, 'use_vector', default=False)
|
|
371
|
+
self._vector_store = self._from_db(bot, 'vector_store_config', default={})
|
|
372
|
+
self._metric_type = self._vector_store.get('metric_type', self._metric_type)
|
|
373
|
+
|
|
374
|
+
# Memory and conversation configuration
|
|
375
|
+
self.memory_type = self._from_db(bot, 'memory_type', default='memory')
|
|
376
|
+
self.memory_config = self._from_db(bot, 'memory_config', default={})
|
|
377
|
+
self.max_context_turns = self._from_db(bot, 'max_context_turns', default=5)
|
|
378
|
+
self.use_conversation_history = self._from_db(bot, 'use_conversation_history', default=True)
|
|
379
|
+
|
|
380
|
+
# Context and retrieval settings
|
|
381
|
+
self.context_search_limit = self._from_db(bot, 'context_search_limit', default=10)
|
|
382
|
+
self.context_score_threshold = self._from_db(bot, 'context_score_threshold', default=0.7)
|
|
383
|
+
|
|
384
|
+
# Security and permissions
|
|
385
|
+
_default = self.default_permissions()
|
|
386
|
+
_permissions = self._from_db(bot, 'permissions', default={})
|
|
387
|
+
self._permissions = {**_default, **_permissions}
|
|
388
|
+
|
|
389
|
+
# Knowledge Base:
|
|
390
|
+
self.use_kb = self._from_db(bot, 'use_kb', default=False)
|
|
391
|
+
self._kb = self._from_db(bot, 'kb', default=[])
|
|
392
|
+
if self.use_kb:
|
|
393
|
+
from ..stores.kb.store import KnowledgeBaseStore
|
|
394
|
+
self.kb_store = KnowledgeBaseStore(
|
|
395
|
+
embedding_model=KB_DEFAULT_MODEL,
|
|
396
|
+
dimension=384
|
|
397
|
+
)
|
|
398
|
+
|
|
399
|
+
# Custom Knowledge Bases
|
|
400
|
+
self.custom_kbs = self._from_db(bot, 'custom_kbs', default=[])
|
|
401
|
+
if self.custom_kbs:
|
|
402
|
+
for kb_path in self.custom_kbs:
|
|
403
|
+
kb_class = self.import_kb_class(kb_path)
|
|
404
|
+
if kb_class:
|
|
405
|
+
self.register_kb(kb_class)
|
|
406
|
+
|
|
407
|
+
# Other settings
|
|
408
|
+
self.language = self._from_db(bot, 'language', default='en')
|
|
409
|
+
self.disclaimer = self._from_db(bot, 'disclaimer', default=None)
|
|
410
|
+
|
|
411
|
+
self.logger.info(
|
|
412
|
+
f"Loaded bot configuration: "
|
|
413
|
+
f"tools_enabled={self.enable_tools}, "
|
|
414
|
+
f"operation_mode={self.operation_mode}, "
|
|
415
|
+
f"use_vector={self._use_vector}, "
|
|
416
|
+
f"tools_count={self.tool_manager.tool_count()}"
|
|
417
|
+
)
|
|
418
|
+
|
|
419
|
+
def _define_prompt(self, config: dict = None, **kwargs):
|
|
420
|
+
"""
|
|
421
|
+
Enhanced prompt definition that includes tools information.
|
|
422
|
+
"""
|
|
423
|
+
# Setup the prompt variables
|
|
424
|
+
if config:
|
|
425
|
+
for key, val in config.items():
|
|
426
|
+
setattr(self, key, val)
|
|
427
|
+
|
|
428
|
+
# Build pre-context
|
|
429
|
+
pre_context = ''
|
|
430
|
+
if self.pre_instructions:
|
|
431
|
+
pre_context = "IMPORTANT PRE-INSTRUCTIONS: \n"
|
|
432
|
+
pre_context += "\n".join(f"- {a}." for a in self.pre_instructions)
|
|
433
|
+
|
|
434
|
+
# Build tools context if tools are available
|
|
435
|
+
tools_context = ''
|
|
436
|
+
# Apply template substitution
|
|
437
|
+
tmpl = Template(self.system_prompt_template)
|
|
438
|
+
final_prompt = tmpl.safe_substitute(
|
|
439
|
+
name=self.name,
|
|
440
|
+
role=self.role,
|
|
441
|
+
goal=self.goal,
|
|
442
|
+
capabilities=self.capabilities,
|
|
443
|
+
backstory=self.backstory,
|
|
444
|
+
rationale=self.rationale,
|
|
445
|
+
pre_context=pre_context,
|
|
446
|
+
tools_context=tools_context,
|
|
447
|
+
**kwargs
|
|
448
|
+
)
|
|
449
|
+
# Set the system prompt
|
|
450
|
+
self.system_prompt_template = final_prompt
|
|
451
|
+
if self._debug:
|
|
452
|
+
print(' SYSTEM PROMPT ')
|
|
453
|
+
print(final_prompt)
|
|
454
|
+
|
|
455
|
+
async def update_database_config(self, **updates) -> bool:
|
|
456
|
+
"""
|
|
457
|
+
Update bot configuration in database.
|
|
458
|
+
|
|
459
|
+
Args:
|
|
460
|
+
**updates: Configuration updates to apply
|
|
461
|
+
|
|
462
|
+
Returns:
|
|
463
|
+
bool: True if update was successful, False otherwise
|
|
464
|
+
"""
|
|
465
|
+
try:
|
|
466
|
+
async with self._botmodel_connection() as conn: # pylint: disable=E1101 # noqa
|
|
467
|
+
BotModel.Meta.connection = conn
|
|
468
|
+
bot = await BotModel.get(chatbot_id=self.chatbot_id)
|
|
469
|
+
|
|
470
|
+
# Apply updates
|
|
471
|
+
for key, value in updates.items():
|
|
472
|
+
if hasattr(bot, key):
|
|
473
|
+
setattr(bot, key, value)
|
|
474
|
+
|
|
475
|
+
# Save changes
|
|
476
|
+
await bot.update()
|
|
477
|
+
self.logger.info(f"Updated bot configuration in database: {list(updates.keys())}")
|
|
478
|
+
return True
|
|
479
|
+
|
|
480
|
+
except Exception as e:
|
|
481
|
+
self.logger.error(f"Error updating bot configuration: {e}")
|
|
482
|
+
return False
|
|
483
|
+
|
|
484
|
+
async def save_to_database(self) -> bool:
|
|
485
|
+
"""
|
|
486
|
+
Save current bot configuration to database.
|
|
487
|
+
|
|
488
|
+
Returns:
|
|
489
|
+
bool: True if save was successful, False otherwise
|
|
490
|
+
"""
|
|
491
|
+
try:
|
|
492
|
+
async with self._botmodel_connection() as conn: # pylint: disable=E1101 # noqa
|
|
493
|
+
BotModel.Meta.connection = conn
|
|
494
|
+
|
|
495
|
+
# Create or update bot model
|
|
496
|
+
bot_data = {
|
|
497
|
+
'chatbot_id': self.chatbot_id,
|
|
498
|
+
'name': self.name,
|
|
499
|
+
'description': self.description,
|
|
500
|
+
'role': self.role,
|
|
501
|
+
'goal': self.goal,
|
|
502
|
+
'backstory': self.backstory,
|
|
503
|
+
'rationale': self.rationale,
|
|
504
|
+
'capabilities': getattr(self, 'capabilities', ''),
|
|
505
|
+
'system_prompt_template': self.system_prompt_template,
|
|
506
|
+
'human_prompt_template': getattr(self, 'human_prompt_template', None),
|
|
507
|
+
'pre_instructions': self.pre_instructions,
|
|
508
|
+
'llm': self._llm,
|
|
509
|
+
'model_name': self._llm_model,
|
|
510
|
+
'temperature': self._llm_temp,
|
|
511
|
+
'max_tokens': self._max_tokens,
|
|
512
|
+
'top_k': self._top_k,
|
|
513
|
+
'top_p': self._top_p,
|
|
514
|
+
'model_config': self._llm_config,
|
|
515
|
+
'tools_enabled': getattr(self, 'enable_tools', True),
|
|
516
|
+
'auto_tool_detection': getattr(self, 'auto_tool_detection', True),
|
|
517
|
+
'tool_threshold': getattr(self, 'tool_threshold', 0.7),
|
|
518
|
+
'tools': [tool.name for tool in self.tool_manager.list_tools()] if self.tool_manager else [],
|
|
519
|
+
'operation_mode': getattr(self, 'operation_mode', 'adaptive'),
|
|
520
|
+
'use_vector': self._use_vector,
|
|
521
|
+
'vector_store_config': self._vector_store,
|
|
522
|
+
'embedding_model': self.embedding_model,
|
|
523
|
+
'context_search_limit': getattr(self, 'context_search_limit', 10),
|
|
524
|
+
'context_score_threshold': getattr(self, 'context_score_threshold', 0.7),
|
|
525
|
+
'memory_type': getattr(self, 'memory_type', 'memory'),
|
|
526
|
+
'memory_config': getattr(self, 'memory_config', {}),
|
|
527
|
+
'max_context_turns': getattr(self, 'max_context_turns', 5),
|
|
528
|
+
'use_conversation_history': getattr(self, 'use_conversation_history', True),
|
|
529
|
+
'permissions': self._permissions,
|
|
530
|
+
'language': getattr(self, 'language', 'en'),
|
|
531
|
+
'disclaimer': getattr(self, 'disclaimer', None),
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
try:
|
|
535
|
+
# Try to get existing bot
|
|
536
|
+
bot = await BotModel.get(chatbot_id=self.chatbot_id)
|
|
537
|
+
# Update existing
|
|
538
|
+
for key, value in bot_data.items():
|
|
539
|
+
setattr(bot, key, value)
|
|
540
|
+
await bot.update()
|
|
541
|
+
self.logger.info(f"Updated existing bot {self.name} in database")
|
|
542
|
+
|
|
543
|
+
except NoDataFound:
|
|
544
|
+
# Create new bot
|
|
545
|
+
bot = BotModel(**bot_data)
|
|
546
|
+
await bot.save()
|
|
547
|
+
self.logger.info(f"Created new bot {self.name} in database")
|
|
548
|
+
|
|
549
|
+
return True
|
|
550
|
+
|
|
551
|
+
except Exception as e:
|
|
552
|
+
self.logger.error(f"Error saving bot to database: {e}")
|
|
553
|
+
return False
|
|
554
|
+
|
|
555
|
+
def get_configuration_summary(self) -> Dict[str, Any]:
|
|
556
|
+
"""
|
|
557
|
+
Get a summary of the current bot configuration.
|
|
558
|
+
|
|
559
|
+
Returns:
|
|
560
|
+
Dict containing configuration summary
|
|
561
|
+
"""
|
|
562
|
+
return {
|
|
563
|
+
'name': self.name,
|
|
564
|
+
'chatbot_id': self.chatbot_id,
|
|
565
|
+
'operation_mode': getattr(self, 'operation_mode', 'adaptive'),
|
|
566
|
+
'current_mode': self.get_operation_mode(),
|
|
567
|
+
'tools_enabled': getattr(self, 'enable_tools', False),
|
|
568
|
+
'tools_count': self.tool_manager.tool_count() if self.tool_manager else 0,
|
|
569
|
+
'available_tools': self.tool_manager.list_tools() if self.tool_manager else [],
|
|
570
|
+
'use_vector_store': self._use_vector,
|
|
571
|
+
'vector_store_type': self._vector_store.get('name', 'none') if self._vector_store else 'none',
|
|
572
|
+
'llm': self._llm,
|
|
573
|
+
'model_name': self._llm_model,
|
|
574
|
+
'memory_type': getattr(self, 'memory_type', 'memory'),
|
|
575
|
+
'max_context_turns': getattr(self, 'max_context_turns', 5),
|
|
576
|
+
'auto_tool_detection': getattr(self, 'auto_tool_detection', True),
|
|
577
|
+
'tool_threshold': getattr(self, 'tool_threshold', 0.7),
|
|
578
|
+
'language': getattr(self, 'language', 'en'),
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
async def test_configuration(self) -> Dict[str, Any]:
|
|
582
|
+
"""
|
|
583
|
+
Test the current bot configuration and return status.
|
|
584
|
+
|
|
585
|
+
Returns:
|
|
586
|
+
Dict containing test results
|
|
587
|
+
"""
|
|
588
|
+
results = {
|
|
589
|
+
'status': 'success',
|
|
590
|
+
'errors': [],
|
|
591
|
+
'warnings': [],
|
|
592
|
+
'info': []
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
try:
|
|
596
|
+
# Test database connection
|
|
597
|
+
if not await self.bot_exists(name=self.name):
|
|
598
|
+
results['warnings'].append(f"Bot {self.name} not found in database")
|
|
599
|
+
else:
|
|
600
|
+
results['info'].append("Database connection: OK")
|
|
601
|
+
|
|
602
|
+
# Test LLM configuration
|
|
603
|
+
if not self._llm:
|
|
604
|
+
results['errors'].append("No LLM configured")
|
|
605
|
+
else:
|
|
606
|
+
results['info'].append(f"LLM configured: {self._llm}")
|
|
607
|
+
|
|
608
|
+
# Test tools configuration
|
|
609
|
+
if getattr(self, 'enable_tools', False):
|
|
610
|
+
if not self.tool_manager:
|
|
611
|
+
results['warnings'].append("Tools enabled but no tools loaded")
|
|
612
|
+
else:
|
|
613
|
+
results['info'].append(f"Tools loaded: {len(self.tool_manager.list_tools())}")
|
|
614
|
+
|
|
615
|
+
# Test each tool
|
|
616
|
+
for tool in self.tool_manager.list_tools():
|
|
617
|
+
try:
|
|
618
|
+
# Basic tool validation
|
|
619
|
+
if not hasattr(tool, 'name'):
|
|
620
|
+
results['errors'].append(f"Tool {tool.__class__.__name__} missing name attribute")
|
|
621
|
+
else:
|
|
622
|
+
results['info'].append(f"Tool {tool.name}: OK")
|
|
623
|
+
except Exception as e:
|
|
624
|
+
results['errors'].append(f"Tool {tool.__class__.__name__} error: {e}")
|
|
625
|
+
|
|
626
|
+
# Test vector store configuration
|
|
627
|
+
if self._use_vector:
|
|
628
|
+
if not self._vector_store:
|
|
629
|
+
results['errors'].append("Vector store enabled but not configured")
|
|
630
|
+
else:
|
|
631
|
+
results['info'].append("Vector store configured")
|
|
632
|
+
|
|
633
|
+
# Set overall status
|
|
634
|
+
if results['errors']:
|
|
635
|
+
results['status'] = 'error'
|
|
636
|
+
elif results['warnings']:
|
|
637
|
+
results['status'] = 'warning'
|
|
638
|
+
|
|
639
|
+
except Exception as e:
|
|
640
|
+
results['status'] = 'error'
|
|
641
|
+
results['errors'].append(f"Configuration test failed: {e}")
|
|
642
|
+
|
|
643
|
+
return results
|
|
644
|
+
|
|
645
|
+
async def reload_from_database(self) -> bool:
|
|
646
|
+
"""
|
|
647
|
+
Reload bot configuration from database.
|
|
648
|
+
|
|
649
|
+
Returns:
|
|
650
|
+
bool: True if reload was successful, False otherwise
|
|
651
|
+
"""
|
|
652
|
+
try:
|
|
653
|
+
if bot := await self.bot_exists(name=self.name, uuid=self.chatbot_id):
|
|
654
|
+
await self.from_database(bot)
|
|
655
|
+
self.logger.info(f"Reloaded bot {self.name} configuration from database")
|
|
656
|
+
return True
|
|
657
|
+
else:
|
|
658
|
+
self.logger.error(f"Bot {self.name} not found in database for reload")
|
|
659
|
+
return False
|
|
660
|
+
except Exception as e:
|
|
661
|
+
self.logger.error(f"Error reloading bot configuration: {e}")
|
|
662
|
+
return False
|
|
663
|
+
|
|
664
|
+
def __str__(self) -> str:
|
|
665
|
+
"""String representation of the bot."""
|
|
666
|
+
mode = self.get_operation_mode()
|
|
667
|
+
tools_info = f", {self.tool_manager.tool_count()} tools" if self.enable_tools else ", no tools"
|
|
668
|
+
vector_info = ", vector store" if self._use_vector else ""
|
|
669
|
+
return f"{self.name} ({mode} mode{tools_info}{vector_info})"
|