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.
Files changed (535) hide show
  1. agentui/.prettierrc +15 -0
  2. agentui/QUICKSTART.md +272 -0
  3. agentui/README.md +59 -0
  4. agentui/env.example +16 -0
  5. agentui/jsconfig.json +14 -0
  6. agentui/package-lock.json +4242 -0
  7. agentui/package.json +34 -0
  8. agentui/scripts/postinstall/apply-patches.mjs +260 -0
  9. agentui/src/app.css +61 -0
  10. agentui/src/app.d.ts +13 -0
  11. agentui/src/app.html +12 -0
  12. agentui/src/components/LoadingSpinner.svelte +64 -0
  13. agentui/src/components/ThemeSwitcher.svelte +159 -0
  14. agentui/src/components/index.js +4 -0
  15. agentui/src/lib/api/bots.ts +60 -0
  16. agentui/src/lib/api/chat.ts +22 -0
  17. agentui/src/lib/api/http.ts +25 -0
  18. agentui/src/lib/components/BotCard.svelte +33 -0
  19. agentui/src/lib/components/ChatBubble.svelte +63 -0
  20. agentui/src/lib/components/Toast.svelte +21 -0
  21. agentui/src/lib/config.ts +20 -0
  22. agentui/src/lib/stores/auth.svelte.ts +73 -0
  23. agentui/src/lib/stores/theme.svelte.js +64 -0
  24. agentui/src/lib/stores/toast.svelte.ts +31 -0
  25. agentui/src/lib/utils/conversation.ts +39 -0
  26. agentui/src/routes/+layout.svelte +20 -0
  27. agentui/src/routes/+page.svelte +232 -0
  28. agentui/src/routes/login/+page.svelte +200 -0
  29. agentui/src/routes/talk/[agentId]/+page.svelte +297 -0
  30. agentui/src/routes/talk/[agentId]/+page.ts +7 -0
  31. agentui/static/README.md +1 -0
  32. agentui/svelte.config.js +11 -0
  33. agentui/tailwind.config.ts +53 -0
  34. agentui/tsconfig.json +3 -0
  35. agentui/vite.config.ts +10 -0
  36. ai_parrot-0.17.2.dist-info/METADATA +472 -0
  37. ai_parrot-0.17.2.dist-info/RECORD +535 -0
  38. ai_parrot-0.17.2.dist-info/WHEEL +6 -0
  39. ai_parrot-0.17.2.dist-info/entry_points.txt +2 -0
  40. ai_parrot-0.17.2.dist-info/licenses/LICENSE +21 -0
  41. ai_parrot-0.17.2.dist-info/top_level.txt +6 -0
  42. crew-builder/.prettierrc +15 -0
  43. crew-builder/QUICKSTART.md +259 -0
  44. crew-builder/README.md +113 -0
  45. crew-builder/env.example +17 -0
  46. crew-builder/jsconfig.json +14 -0
  47. crew-builder/package-lock.json +4182 -0
  48. crew-builder/package.json +37 -0
  49. crew-builder/scripts/postinstall/apply-patches.mjs +260 -0
  50. crew-builder/src/app.css +62 -0
  51. crew-builder/src/app.d.ts +13 -0
  52. crew-builder/src/app.html +12 -0
  53. crew-builder/src/components/LoadingSpinner.svelte +64 -0
  54. crew-builder/src/components/ThemeSwitcher.svelte +149 -0
  55. crew-builder/src/components/index.js +9 -0
  56. crew-builder/src/lib/api/bots.ts +60 -0
  57. crew-builder/src/lib/api/chat.ts +80 -0
  58. crew-builder/src/lib/api/client.ts +56 -0
  59. crew-builder/src/lib/api/crew/crew.ts +136 -0
  60. crew-builder/src/lib/api/index.ts +5 -0
  61. crew-builder/src/lib/api/o365/auth.ts +65 -0
  62. crew-builder/src/lib/auth/auth.ts +54 -0
  63. crew-builder/src/lib/components/AgentNode.svelte +43 -0
  64. crew-builder/src/lib/components/BotCard.svelte +33 -0
  65. crew-builder/src/lib/components/ChatBubble.svelte +67 -0
  66. crew-builder/src/lib/components/ConfigPanel.svelte +278 -0
  67. crew-builder/src/lib/components/JsonTreeNode.svelte +76 -0
  68. crew-builder/src/lib/components/JsonViewer.svelte +24 -0
  69. crew-builder/src/lib/components/MarkdownEditor.svelte +48 -0
  70. crew-builder/src/lib/components/ThemeToggle.svelte +36 -0
  71. crew-builder/src/lib/components/Toast.svelte +67 -0
  72. crew-builder/src/lib/components/Toolbar.svelte +157 -0
  73. crew-builder/src/lib/components/index.ts +10 -0
  74. crew-builder/src/lib/config.ts +8 -0
  75. crew-builder/src/lib/stores/auth.svelte.ts +228 -0
  76. crew-builder/src/lib/stores/crewStore.ts +369 -0
  77. crew-builder/src/lib/stores/theme.svelte.js +145 -0
  78. crew-builder/src/lib/stores/toast.svelte.ts +69 -0
  79. crew-builder/src/lib/utils/conversation.ts +39 -0
  80. crew-builder/src/lib/utils/markdown.ts +122 -0
  81. crew-builder/src/lib/utils/talkHistory.ts +47 -0
  82. crew-builder/src/routes/+layout.svelte +20 -0
  83. crew-builder/src/routes/+page.svelte +539 -0
  84. crew-builder/src/routes/agents/+page.svelte +247 -0
  85. crew-builder/src/routes/agents/[agentId]/+page.svelte +288 -0
  86. crew-builder/src/routes/agents/[agentId]/+page.ts +7 -0
  87. crew-builder/src/routes/builder/+page.svelte +204 -0
  88. crew-builder/src/routes/crew/ask/+page.svelte +1052 -0
  89. crew-builder/src/routes/crew/ask/+page.ts +1 -0
  90. crew-builder/src/routes/integrations/o365/+page.svelte +304 -0
  91. crew-builder/src/routes/login/+page.svelte +197 -0
  92. crew-builder/src/routes/talk/[agentId]/+page.svelte +487 -0
  93. crew-builder/src/routes/talk/[agentId]/+page.ts +7 -0
  94. crew-builder/static/README.md +1 -0
  95. crew-builder/svelte.config.js +11 -0
  96. crew-builder/tailwind.config.ts +53 -0
  97. crew-builder/tsconfig.json +3 -0
  98. crew-builder/vite.config.ts +10 -0
  99. mcp_servers/calculator_server.py +309 -0
  100. parrot/__init__.py +27 -0
  101. parrot/__pycache__/__init__.cpython-310.pyc +0 -0
  102. parrot/__pycache__/version.cpython-310.pyc +0 -0
  103. parrot/_version.py +34 -0
  104. parrot/a2a/__init__.py +48 -0
  105. parrot/a2a/client.py +658 -0
  106. parrot/a2a/discovery.py +89 -0
  107. parrot/a2a/mixin.py +257 -0
  108. parrot/a2a/models.py +376 -0
  109. parrot/a2a/server.py +770 -0
  110. parrot/agents/__init__.py +29 -0
  111. parrot/bots/__init__.py +12 -0
  112. parrot/bots/a2a_agent.py +19 -0
  113. parrot/bots/abstract.py +3139 -0
  114. parrot/bots/agent.py +1129 -0
  115. parrot/bots/basic.py +9 -0
  116. parrot/bots/chatbot.py +669 -0
  117. parrot/bots/data.py +1618 -0
  118. parrot/bots/database/__init__.py +5 -0
  119. parrot/bots/database/abstract.py +3071 -0
  120. parrot/bots/database/cache.py +286 -0
  121. parrot/bots/database/models.py +468 -0
  122. parrot/bots/database/prompts.py +154 -0
  123. parrot/bots/database/retries.py +98 -0
  124. parrot/bots/database/router.py +269 -0
  125. parrot/bots/database/sql.py +41 -0
  126. parrot/bots/db/__init__.py +6 -0
  127. parrot/bots/db/abstract.py +556 -0
  128. parrot/bots/db/bigquery.py +602 -0
  129. parrot/bots/db/cache.py +85 -0
  130. parrot/bots/db/documentdb.py +668 -0
  131. parrot/bots/db/elastic.py +1014 -0
  132. parrot/bots/db/influx.py +898 -0
  133. parrot/bots/db/mock.py +96 -0
  134. parrot/bots/db/multi.py +783 -0
  135. parrot/bots/db/prompts.py +185 -0
  136. parrot/bots/db/sql.py +1255 -0
  137. parrot/bots/db/tools.py +212 -0
  138. parrot/bots/document.py +680 -0
  139. parrot/bots/hrbot.py +15 -0
  140. parrot/bots/kb.py +170 -0
  141. parrot/bots/mcp.py +36 -0
  142. parrot/bots/orchestration/README.md +463 -0
  143. parrot/bots/orchestration/__init__.py +1 -0
  144. parrot/bots/orchestration/agent.py +155 -0
  145. parrot/bots/orchestration/crew.py +3330 -0
  146. parrot/bots/orchestration/fsm.py +1179 -0
  147. parrot/bots/orchestration/hr.py +434 -0
  148. parrot/bots/orchestration/storage/__init__.py +4 -0
  149. parrot/bots/orchestration/storage/memory.py +100 -0
  150. parrot/bots/orchestration/storage/mixin.py +119 -0
  151. parrot/bots/orchestration/verify.py +202 -0
  152. parrot/bots/product.py +204 -0
  153. parrot/bots/prompts/__init__.py +96 -0
  154. parrot/bots/prompts/agents.py +155 -0
  155. parrot/bots/prompts/data.py +216 -0
  156. parrot/bots/prompts/output_generation.py +8 -0
  157. parrot/bots/scraper/__init__.py +3 -0
  158. parrot/bots/scraper/models.py +122 -0
  159. parrot/bots/scraper/scraper.py +1173 -0
  160. parrot/bots/scraper/templates.py +115 -0
  161. parrot/bots/stores/__init__.py +5 -0
  162. parrot/bots/stores/local.py +172 -0
  163. parrot/bots/webdev.py +81 -0
  164. parrot/cli.py +17 -0
  165. parrot/clients/__init__.py +16 -0
  166. parrot/clients/base.py +1491 -0
  167. parrot/clients/claude.py +1191 -0
  168. parrot/clients/factory.py +129 -0
  169. parrot/clients/google.py +4567 -0
  170. parrot/clients/gpt.py +1975 -0
  171. parrot/clients/grok.py +432 -0
  172. parrot/clients/groq.py +986 -0
  173. parrot/clients/hf.py +582 -0
  174. parrot/clients/models.py +18 -0
  175. parrot/conf.py +395 -0
  176. parrot/embeddings/__init__.py +9 -0
  177. parrot/embeddings/base.py +157 -0
  178. parrot/embeddings/google.py +98 -0
  179. parrot/embeddings/huggingface.py +74 -0
  180. parrot/embeddings/openai.py +84 -0
  181. parrot/embeddings/processor.py +88 -0
  182. parrot/exceptions.c +13868 -0
  183. parrot/exceptions.cpython-310-x86_64-linux-gnu.so +0 -0
  184. parrot/exceptions.pxd +22 -0
  185. parrot/exceptions.pxi +15 -0
  186. parrot/exceptions.pyx +44 -0
  187. parrot/generators/__init__.py +29 -0
  188. parrot/generators/base.py +200 -0
  189. parrot/generators/html.py +293 -0
  190. parrot/generators/react.py +205 -0
  191. parrot/generators/streamlit.py +203 -0
  192. parrot/generators/template.py +105 -0
  193. parrot/handlers/__init__.py +4 -0
  194. parrot/handlers/agent.py +861 -0
  195. parrot/handlers/agents/__init__.py +1 -0
  196. parrot/handlers/agents/abstract.py +900 -0
  197. parrot/handlers/bots.py +338 -0
  198. parrot/handlers/chat.py +915 -0
  199. parrot/handlers/creation.sql +192 -0
  200. parrot/handlers/crew/ARCHITECTURE.md +362 -0
  201. parrot/handlers/crew/README_BOTMANAGER_PERSISTENCE.md +303 -0
  202. parrot/handlers/crew/README_REDIS_PERSISTENCE.md +366 -0
  203. parrot/handlers/crew/__init__.py +0 -0
  204. parrot/handlers/crew/handler.py +801 -0
  205. parrot/handlers/crew/models.py +229 -0
  206. parrot/handlers/crew/redis_persistence.py +523 -0
  207. parrot/handlers/jobs/__init__.py +10 -0
  208. parrot/handlers/jobs/job.py +384 -0
  209. parrot/handlers/jobs/mixin.py +627 -0
  210. parrot/handlers/jobs/models.py +115 -0
  211. parrot/handlers/jobs/worker.py +31 -0
  212. parrot/handlers/models.py +596 -0
  213. parrot/handlers/o365_auth.py +105 -0
  214. parrot/handlers/stream.py +337 -0
  215. parrot/interfaces/__init__.py +6 -0
  216. parrot/interfaces/aws.py +143 -0
  217. parrot/interfaces/credentials.py +113 -0
  218. parrot/interfaces/database.py +27 -0
  219. parrot/interfaces/google.py +1123 -0
  220. parrot/interfaces/hierarchy.py +1227 -0
  221. parrot/interfaces/http.py +651 -0
  222. parrot/interfaces/images/__init__.py +0 -0
  223. parrot/interfaces/images/plugins/__init__.py +24 -0
  224. parrot/interfaces/images/plugins/abstract.py +58 -0
  225. parrot/interfaces/images/plugins/analisys.py +148 -0
  226. parrot/interfaces/images/plugins/classify.py +150 -0
  227. parrot/interfaces/images/plugins/classifybase.py +182 -0
  228. parrot/interfaces/images/plugins/detect.py +150 -0
  229. parrot/interfaces/images/plugins/exif.py +1103 -0
  230. parrot/interfaces/images/plugins/hash.py +52 -0
  231. parrot/interfaces/images/plugins/vision.py +104 -0
  232. parrot/interfaces/images/plugins/yolo.py +66 -0
  233. parrot/interfaces/images/plugins/zerodetect.py +197 -0
  234. parrot/interfaces/o365.py +978 -0
  235. parrot/interfaces/onedrive.py +822 -0
  236. parrot/interfaces/sharepoint.py +1435 -0
  237. parrot/interfaces/soap.py +257 -0
  238. parrot/loaders/__init__.py +8 -0
  239. parrot/loaders/abstract.py +1131 -0
  240. parrot/loaders/audio.py +199 -0
  241. parrot/loaders/basepdf.py +53 -0
  242. parrot/loaders/basevideo.py +1568 -0
  243. parrot/loaders/csv.py +409 -0
  244. parrot/loaders/docx.py +116 -0
  245. parrot/loaders/epubloader.py +316 -0
  246. parrot/loaders/excel.py +199 -0
  247. parrot/loaders/factory.py +55 -0
  248. parrot/loaders/files/__init__.py +0 -0
  249. parrot/loaders/files/abstract.py +39 -0
  250. parrot/loaders/files/html.py +26 -0
  251. parrot/loaders/files/text.py +63 -0
  252. parrot/loaders/html.py +152 -0
  253. parrot/loaders/markdown.py +442 -0
  254. parrot/loaders/pdf.py +373 -0
  255. parrot/loaders/pdfmark.py +320 -0
  256. parrot/loaders/pdftables.py +506 -0
  257. parrot/loaders/ppt.py +476 -0
  258. parrot/loaders/qa.py +63 -0
  259. parrot/loaders/splitters/__init__.py +10 -0
  260. parrot/loaders/splitters/base.py +138 -0
  261. parrot/loaders/splitters/md.py +228 -0
  262. parrot/loaders/splitters/token.py +143 -0
  263. parrot/loaders/txt.py +26 -0
  264. parrot/loaders/video.py +89 -0
  265. parrot/loaders/videolocal.py +218 -0
  266. parrot/loaders/videounderstanding.py +377 -0
  267. parrot/loaders/vimeo.py +167 -0
  268. parrot/loaders/web.py +599 -0
  269. parrot/loaders/youtube.py +504 -0
  270. parrot/manager/__init__.py +5 -0
  271. parrot/manager/manager.py +1030 -0
  272. parrot/mcp/__init__.py +28 -0
  273. parrot/mcp/adapter.py +105 -0
  274. parrot/mcp/cli.py +174 -0
  275. parrot/mcp/client.py +119 -0
  276. parrot/mcp/config.py +75 -0
  277. parrot/mcp/integration.py +842 -0
  278. parrot/mcp/oauth.py +933 -0
  279. parrot/mcp/server.py +225 -0
  280. parrot/mcp/transports/__init__.py +3 -0
  281. parrot/mcp/transports/base.py +279 -0
  282. parrot/mcp/transports/grpc_session.py +163 -0
  283. parrot/mcp/transports/http.py +312 -0
  284. parrot/mcp/transports/mcp.proto +108 -0
  285. parrot/mcp/transports/quic.py +1082 -0
  286. parrot/mcp/transports/sse.py +330 -0
  287. parrot/mcp/transports/stdio.py +309 -0
  288. parrot/mcp/transports/unix.py +395 -0
  289. parrot/mcp/transports/websocket.py +547 -0
  290. parrot/memory/__init__.py +16 -0
  291. parrot/memory/abstract.py +209 -0
  292. parrot/memory/agent.py +32 -0
  293. parrot/memory/cache.py +175 -0
  294. parrot/memory/core.py +555 -0
  295. parrot/memory/file.py +153 -0
  296. parrot/memory/mem.py +131 -0
  297. parrot/memory/redis.py +613 -0
  298. parrot/models/__init__.py +46 -0
  299. parrot/models/basic.py +118 -0
  300. parrot/models/compliance.py +208 -0
  301. parrot/models/crew.py +395 -0
  302. parrot/models/detections.py +654 -0
  303. parrot/models/generation.py +85 -0
  304. parrot/models/google.py +223 -0
  305. parrot/models/groq.py +23 -0
  306. parrot/models/openai.py +30 -0
  307. parrot/models/outputs.py +285 -0
  308. parrot/models/responses.py +938 -0
  309. parrot/notifications/__init__.py +743 -0
  310. parrot/openapi/__init__.py +3 -0
  311. parrot/openapi/components.yaml +641 -0
  312. parrot/openapi/config.py +322 -0
  313. parrot/outputs/__init__.py +32 -0
  314. parrot/outputs/formats/__init__.py +108 -0
  315. parrot/outputs/formats/altair.py +359 -0
  316. parrot/outputs/formats/application.py +122 -0
  317. parrot/outputs/formats/base.py +351 -0
  318. parrot/outputs/formats/bokeh.py +356 -0
  319. parrot/outputs/formats/card.py +424 -0
  320. parrot/outputs/formats/chart.py +436 -0
  321. parrot/outputs/formats/d3.py +255 -0
  322. parrot/outputs/formats/echarts.py +310 -0
  323. parrot/outputs/formats/generators/__init__.py +0 -0
  324. parrot/outputs/formats/generators/abstract.py +61 -0
  325. parrot/outputs/formats/generators/panel.py +145 -0
  326. parrot/outputs/formats/generators/streamlit.py +86 -0
  327. parrot/outputs/formats/generators/terminal.py +63 -0
  328. parrot/outputs/formats/holoviews.py +310 -0
  329. parrot/outputs/formats/html.py +147 -0
  330. parrot/outputs/formats/jinja2.py +46 -0
  331. parrot/outputs/formats/json.py +87 -0
  332. parrot/outputs/formats/map.py +933 -0
  333. parrot/outputs/formats/markdown.py +172 -0
  334. parrot/outputs/formats/matplotlib.py +237 -0
  335. parrot/outputs/formats/mixins/__init__.py +0 -0
  336. parrot/outputs/formats/mixins/emaps.py +855 -0
  337. parrot/outputs/formats/plotly.py +341 -0
  338. parrot/outputs/formats/seaborn.py +310 -0
  339. parrot/outputs/formats/table.py +397 -0
  340. parrot/outputs/formats/template_report.py +138 -0
  341. parrot/outputs/formats/yaml.py +125 -0
  342. parrot/outputs/formatter.py +152 -0
  343. parrot/outputs/templates/__init__.py +95 -0
  344. parrot/pipelines/__init__.py +0 -0
  345. parrot/pipelines/abstract.py +210 -0
  346. parrot/pipelines/detector.py +124 -0
  347. parrot/pipelines/models.py +90 -0
  348. parrot/pipelines/planogram.py +3002 -0
  349. parrot/pipelines/table.sql +97 -0
  350. parrot/plugins/__init__.py +106 -0
  351. parrot/plugins/importer.py +80 -0
  352. parrot/py.typed +0 -0
  353. parrot/registry/__init__.py +18 -0
  354. parrot/registry/registry.py +594 -0
  355. parrot/scheduler/__init__.py +1189 -0
  356. parrot/scheduler/models.py +60 -0
  357. parrot/security/__init__.py +16 -0
  358. parrot/security/prompt_injection.py +268 -0
  359. parrot/security/security_events.sql +25 -0
  360. parrot/services/__init__.py +1 -0
  361. parrot/services/mcp/__init__.py +8 -0
  362. parrot/services/mcp/config.py +13 -0
  363. parrot/services/mcp/server.py +295 -0
  364. parrot/services/o365_remote_auth.py +235 -0
  365. parrot/stores/__init__.py +7 -0
  366. parrot/stores/abstract.py +352 -0
  367. parrot/stores/arango.py +1090 -0
  368. parrot/stores/bigquery.py +1377 -0
  369. parrot/stores/cache.py +106 -0
  370. parrot/stores/empty.py +10 -0
  371. parrot/stores/faiss_store.py +1157 -0
  372. parrot/stores/kb/__init__.py +9 -0
  373. parrot/stores/kb/abstract.py +68 -0
  374. parrot/stores/kb/cache.py +165 -0
  375. parrot/stores/kb/doc.py +325 -0
  376. parrot/stores/kb/hierarchy.py +346 -0
  377. parrot/stores/kb/local.py +457 -0
  378. parrot/stores/kb/prompt.py +28 -0
  379. parrot/stores/kb/redis.py +659 -0
  380. parrot/stores/kb/store.py +115 -0
  381. parrot/stores/kb/user.py +374 -0
  382. parrot/stores/models.py +59 -0
  383. parrot/stores/pgvector.py +3 -0
  384. parrot/stores/postgres.py +2853 -0
  385. parrot/stores/utils/__init__.py +0 -0
  386. parrot/stores/utils/chunking.py +197 -0
  387. parrot/telemetry/__init__.py +3 -0
  388. parrot/telemetry/mixin.py +111 -0
  389. parrot/template/__init__.py +3 -0
  390. parrot/template/engine.py +259 -0
  391. parrot/tools/__init__.py +23 -0
  392. parrot/tools/abstract.py +644 -0
  393. parrot/tools/agent.py +363 -0
  394. parrot/tools/arangodbsearch.py +537 -0
  395. parrot/tools/arxiv_tool.py +188 -0
  396. parrot/tools/calculator/__init__.py +3 -0
  397. parrot/tools/calculator/operations/__init__.py +38 -0
  398. parrot/tools/calculator/operations/calculus.py +80 -0
  399. parrot/tools/calculator/operations/statistics.py +76 -0
  400. parrot/tools/calculator/tool.py +150 -0
  401. parrot/tools/cloudwatch.py +988 -0
  402. parrot/tools/codeinterpreter/__init__.py +127 -0
  403. parrot/tools/codeinterpreter/executor.py +371 -0
  404. parrot/tools/codeinterpreter/internals.py +473 -0
  405. parrot/tools/codeinterpreter/models.py +643 -0
  406. parrot/tools/codeinterpreter/prompts.py +224 -0
  407. parrot/tools/codeinterpreter/tool.py +664 -0
  408. parrot/tools/company_info/__init__.py +6 -0
  409. parrot/tools/company_info/tool.py +1138 -0
  410. parrot/tools/correlationanalysis.py +437 -0
  411. parrot/tools/database/abstract.py +286 -0
  412. parrot/tools/database/bq.py +115 -0
  413. parrot/tools/database/cache.py +284 -0
  414. parrot/tools/database/models.py +95 -0
  415. parrot/tools/database/pg.py +343 -0
  416. parrot/tools/databasequery.py +1159 -0
  417. parrot/tools/db.py +1800 -0
  418. parrot/tools/ddgo.py +370 -0
  419. parrot/tools/decorators.py +271 -0
  420. parrot/tools/dftohtml.py +282 -0
  421. parrot/tools/document.py +549 -0
  422. parrot/tools/ecs.py +819 -0
  423. parrot/tools/edareport.py +368 -0
  424. parrot/tools/elasticsearch.py +1049 -0
  425. parrot/tools/employees.py +462 -0
  426. parrot/tools/epson/__init__.py +96 -0
  427. parrot/tools/excel.py +683 -0
  428. parrot/tools/file/__init__.py +13 -0
  429. parrot/tools/file/abstract.py +76 -0
  430. parrot/tools/file/gcs.py +378 -0
  431. parrot/tools/file/local.py +284 -0
  432. parrot/tools/file/s3.py +511 -0
  433. parrot/tools/file/tmp.py +309 -0
  434. parrot/tools/file/tool.py +501 -0
  435. parrot/tools/file_reader.py +129 -0
  436. parrot/tools/flowtask/__init__.py +19 -0
  437. parrot/tools/flowtask/tool.py +761 -0
  438. parrot/tools/gittoolkit.py +508 -0
  439. parrot/tools/google/__init__.py +18 -0
  440. parrot/tools/google/base.py +169 -0
  441. parrot/tools/google/tools.py +1251 -0
  442. parrot/tools/googlelocation.py +5 -0
  443. parrot/tools/googleroutes.py +5 -0
  444. parrot/tools/googlesearch.py +5 -0
  445. parrot/tools/googlesitesearch.py +5 -0
  446. parrot/tools/googlevoice.py +2 -0
  447. parrot/tools/gvoice.py +695 -0
  448. parrot/tools/ibisworld/README.md +225 -0
  449. parrot/tools/ibisworld/__init__.py +11 -0
  450. parrot/tools/ibisworld/tool.py +366 -0
  451. parrot/tools/jiratoolkit.py +1718 -0
  452. parrot/tools/manager.py +1098 -0
  453. parrot/tools/math.py +152 -0
  454. parrot/tools/metadata.py +476 -0
  455. parrot/tools/msteams.py +1621 -0
  456. parrot/tools/msword.py +635 -0
  457. parrot/tools/multidb.py +580 -0
  458. parrot/tools/multistoresearch.py +369 -0
  459. parrot/tools/networkninja.py +167 -0
  460. parrot/tools/nextstop/__init__.py +4 -0
  461. parrot/tools/nextstop/base.py +286 -0
  462. parrot/tools/nextstop/employee.py +733 -0
  463. parrot/tools/nextstop/store.py +462 -0
  464. parrot/tools/notification.py +435 -0
  465. parrot/tools/o365/__init__.py +42 -0
  466. parrot/tools/o365/base.py +295 -0
  467. parrot/tools/o365/bundle.py +522 -0
  468. parrot/tools/o365/events.py +554 -0
  469. parrot/tools/o365/mail.py +992 -0
  470. parrot/tools/o365/onedrive.py +497 -0
  471. parrot/tools/o365/sharepoint.py +641 -0
  472. parrot/tools/openapi_toolkit.py +904 -0
  473. parrot/tools/openweather.py +527 -0
  474. parrot/tools/pdfprint.py +1001 -0
  475. parrot/tools/powerbi.py +518 -0
  476. parrot/tools/powerpoint.py +1113 -0
  477. parrot/tools/pricestool.py +146 -0
  478. parrot/tools/products/__init__.py +246 -0
  479. parrot/tools/prophet_tool.py +171 -0
  480. parrot/tools/pythonpandas.py +630 -0
  481. parrot/tools/pythonrepl.py +910 -0
  482. parrot/tools/qsource.py +436 -0
  483. parrot/tools/querytoolkit.py +395 -0
  484. parrot/tools/quickeda.py +827 -0
  485. parrot/tools/resttool.py +553 -0
  486. parrot/tools/retail/__init__.py +0 -0
  487. parrot/tools/retail/bby.py +528 -0
  488. parrot/tools/sandboxtool.py +703 -0
  489. parrot/tools/sassie/__init__.py +352 -0
  490. parrot/tools/scraping/__init__.py +7 -0
  491. parrot/tools/scraping/docs/select.md +466 -0
  492. parrot/tools/scraping/documentation.md +1278 -0
  493. parrot/tools/scraping/driver.py +436 -0
  494. parrot/tools/scraping/models.py +576 -0
  495. parrot/tools/scraping/options.py +85 -0
  496. parrot/tools/scraping/orchestrator.py +517 -0
  497. parrot/tools/scraping/readme.md +740 -0
  498. parrot/tools/scraping/tool.py +3115 -0
  499. parrot/tools/seasonaldetection.py +642 -0
  500. parrot/tools/shell_tool/__init__.py +5 -0
  501. parrot/tools/shell_tool/actions.py +408 -0
  502. parrot/tools/shell_tool/engine.py +155 -0
  503. parrot/tools/shell_tool/models.py +322 -0
  504. parrot/tools/shell_tool/tool.py +442 -0
  505. parrot/tools/site_search.py +214 -0
  506. parrot/tools/textfile.py +418 -0
  507. parrot/tools/think.py +378 -0
  508. parrot/tools/toolkit.py +298 -0
  509. parrot/tools/webapp_tool.py +187 -0
  510. parrot/tools/whatif.py +1279 -0
  511. parrot/tools/workday/MULTI_WSDL_EXAMPLE.md +249 -0
  512. parrot/tools/workday/__init__.py +6 -0
  513. parrot/tools/workday/models.py +1389 -0
  514. parrot/tools/workday/tool.py +1293 -0
  515. parrot/tools/yfinance_tool.py +306 -0
  516. parrot/tools/zipcode.py +217 -0
  517. parrot/utils/__init__.py +2 -0
  518. parrot/utils/helpers.py +73 -0
  519. parrot/utils/parsers/__init__.py +5 -0
  520. parrot/utils/parsers/toml.c +12078 -0
  521. parrot/utils/parsers/toml.cpython-310-x86_64-linux-gnu.so +0 -0
  522. parrot/utils/parsers/toml.pyx +21 -0
  523. parrot/utils/toml.py +11 -0
  524. parrot/utils/types.cpp +20936 -0
  525. parrot/utils/types.cpython-310-x86_64-linux-gnu.so +0 -0
  526. parrot/utils/types.pyx +213 -0
  527. parrot/utils/uv.py +11 -0
  528. parrot/version.py +10 -0
  529. parrot/yaml-rs/Cargo.lock +350 -0
  530. parrot/yaml-rs/Cargo.toml +19 -0
  531. parrot/yaml-rs/pyproject.toml +19 -0
  532. parrot/yaml-rs/python/yaml_rs/__init__.py +81 -0
  533. parrot/yaml-rs/src/lib.rs +222 -0
  534. requirements/docker-compose.yml +24 -0
  535. requirements/requirements-dev.txt +21 -0
parrot/clients/hf.py ADDED
@@ -0,0 +1,582 @@
1
+ """
2
+ TransformersClient for ai-parrot framework.
3
+ Supports micro-LLMs from HuggingFace transformers for small tasks.
4
+ """
5
+ import asyncio
6
+ import logging
7
+ import uuid
8
+ import time
9
+ from typing import Any, AsyncIterator, Dict, List, Optional, Union
10
+ from pathlib import Path
11
+ from enum import Enum
12
+
13
+ import torch
14
+ from transformers import (
15
+ AutoModelForCausalLM,
16
+ AutoTokenizer,
17
+ GenerationConfig
18
+ )
19
+
20
+ from .base import AbstractClient, MessageResponse, StreamingRetryConfig
21
+ from ..models import (
22
+ AIMessage,
23
+ AIMessageFactory,
24
+ CompletionUsage,
25
+ StructuredOutputConfig,
26
+ OutputFormat
27
+ )
28
+ from ..memory import ConversationHistory, ConversationTurn
29
+
30
+
31
+ class TransformersModel(Enum):
32
+ """Enum for supported transformer models."""
33
+ DIALOPT_MEDIUM = "microsoft/DialoGPT-medium"
34
+ DIALOPT_SMALL = "microsoft/DialoGPT-small"
35
+ DIALOPT_LARGE = "microsoft/DialoGPT-large"
36
+ TINY_LLM = "arnir0/Tiny-LLM"
37
+ GEMMA_2B = "google/gemma-2-2b-it"
38
+ GEMMA_9B = "google/gemma-2-9b-it"
39
+ GEMMA_3_4B = "google/gemma-3-4b-it"
40
+ GEMMA_3_1B = "google/gemma-3-1b-pt"
41
+ QWEN_1_5B = "Qwen/Qwen2.5-1.5B-Instruct"
42
+ QWEN_3B = "Qwen/Qwen2.5-3B-Instruct"
43
+ QWEN_7B = "Qwen/Qwen2.5-7B-Instruct"
44
+ BCCARD_QWEN_32B = "BCCard/Qwen2.5-VL-32B-Instruct-FP8-Dynamic"
45
+ PHI_3_MINI = "microsoft/Phi-3-mini-4k-instruct"
46
+ PHI_3_SMALL = "microsoft/Phi-3-small-8k-instruct"
47
+ PHI_3_5_MINI = "microsoft/Phi-3.5-mini-instruct"
48
+ OPENAI_GPT_20B = "openai/gpt-oss-20b"
49
+ HUGGINGFACE_TB_SMOLLM2_1_7B = "HuggingFaceTB/SmolLM2-1.7B"
50
+ DEEPSEEK_R1_1B = "deepseek-ai/DeepSeek-R1-Distill-Qwen-1.5B"
51
+ DEEPSEEK_R1_7B = "deepseek-ai/DeepSeek-R1-Distill-Qwen-7B"
52
+
53
+
54
+ class TransformersClient(AbstractClient):
55
+ """
56
+ Client for interacting with HuggingFace transformers micro-LLMs.
57
+
58
+ This client is designed for small, local models that can run efficiently
59
+ on CPU or single GPU setups for quick tasks and lightweight inference.
60
+ """
61
+
62
+ client_type: str = "transformers"
63
+ client_name: str = "transformers"
64
+
65
+ def __init__(
66
+ self,
67
+ model: Union[str, TransformersModel] = TransformersModel.QWEN_3B,
68
+ device: Optional[str] = None,
69
+ torch_dtype: Optional[torch.dtype] = None,
70
+ trust_remote_code: bool = False,
71
+ use_fast_tokenizer: bool = True,
72
+ **kwargs
73
+ ):
74
+ """
75
+ Initialize the TransformersClient.
76
+
77
+ Args:
78
+ model: Model name or TransformersModel enum
79
+ device: Device to run the model on ('cpu', 'cuda', 'auto')
80
+ torch_dtype: PyTorch data type for the model
81
+ trust_remote_code: Whether to trust remote code
82
+ use_fast_tokenizer: Whether to use fast tokenizer
83
+ **kwargs: Additional arguments for AbstractClient
84
+ """
85
+ super().__init__(**kwargs)
86
+
87
+ # Model configuration
88
+ self.model_name = model.value if isinstance(model, TransformersModel) else model
89
+ self.client_name = self.model_name.split("/")[-1] # Use last part of model name as client name
90
+ self.device = device or ("cuda" if torch.cuda.is_available() else "cpu")
91
+ self.torch_dtype = torch_dtype or (torch.float16 if torch.cuda.is_available() else torch.float32)
92
+ self.trust_remote_code = trust_remote_code
93
+ self.use_fast_tokenizer = use_fast_tokenizer
94
+
95
+ # Model and tokenizer (will be loaded lazily)
96
+ self.model = None
97
+ self.tokenizer = None
98
+
99
+ # Generation configuration
100
+ self.generation_config = GenerationConfig(
101
+ max_new_tokens=512,
102
+ temperature=0.7,
103
+ top_p=0.9,
104
+ top_k=50,
105
+ do_sample=True,
106
+ pad_token_id=None, # Will be set after tokenizer is loaded
107
+ eos_token_id=None, # Will be set after tokenizer is loaded
108
+ )
109
+
110
+ self.logger = logging.getLogger(
111
+ f"parrot.TransformersClient.{self.model_name}"
112
+ )
113
+
114
+ async def get_client(self) -> Any:
115
+ """Initialize the client context and load the model."""
116
+ await self._load_model()
117
+ return self.model
118
+
119
+ async def close(self):
120
+ """Clean up resources."""
121
+ await self.clear_model()
122
+ await super().close()
123
+
124
+ async def _load_model(self):
125
+ """Load the model and tokenizer asynchronously."""
126
+ if self.model is not None and self.tokenizer is not None:
127
+ return
128
+
129
+ self.logger.info(f"Loading model: {self.model_name}")
130
+
131
+ # Load tokenizer
132
+ self.tokenizer = AutoTokenizer.from_pretrained(
133
+ self.model_name,
134
+ use_fast=self.use_fast_tokenizer,
135
+ trust_remote_code=self.trust_remote_code,
136
+ padding_side='left' # Important for batch generation
137
+ )
138
+
139
+ # Set pad token if not available
140
+ if self.tokenizer.pad_token is None:
141
+ self.tokenizer.pad_token = self.tokenizer.eos_token
142
+
143
+ # Load model
144
+ self.model = AutoModelForCausalLM.from_pretrained(
145
+ self.model_name,
146
+ torch_dtype=self.torch_dtype,
147
+ device_map=self.device if self.device != "cpu" else None,
148
+ trust_remote_code=self.trust_remote_code,
149
+ )
150
+
151
+ if self.device == "cpu":
152
+ self.model = self.model.to(self.device)
153
+
154
+ # Update generation config with tokenizer info
155
+ self.generation_config.pad_token_id = self.tokenizer.pad_token_id
156
+ self.generation_config.eos_token_id = self.tokenizer.eos_token_id
157
+
158
+ self.logger.info(f"Model loaded successfully on {self.device}")
159
+
160
+ def _prepare_prompt(
161
+ self,
162
+ prompt: str,
163
+ system_prompt: Optional[str] = None,
164
+ conversation_history: Optional[List[Dict[str, str]]] = None
165
+ ) -> str:
166
+ """
167
+ Prepare the prompt based on the model type.
168
+
169
+ Args:
170
+ prompt: User prompt
171
+ system_prompt: System prompt
172
+ conversation_history: Previous conversation turns
173
+
174
+ Returns:
175
+ Formatted prompt string
176
+ """
177
+ # Handle different model formats
178
+ if "gemma" in self.model_name.lower():
179
+ return self._format_gemma_prompt(prompt, system_prompt, conversation_history)
180
+ elif "qwen" in self.model_name.lower():
181
+ return self._format_qwen_prompt(prompt, system_prompt, conversation_history)
182
+ elif "phi" in self.model_name.lower():
183
+ return self._format_phi_prompt(prompt, system_prompt, conversation_history)
184
+ elif "dialogpt" in self.model_name.lower():
185
+ return self._format_dialogpt_prompt(prompt, conversation_history)
186
+ else:
187
+ # Default simple format
188
+ return self._format_simple_prompt(prompt, system_prompt, conversation_history)
189
+
190
+ def _format_gemma_prompt(
191
+ self,
192
+ prompt: str,
193
+ system_prompt: Optional[str] = None,
194
+ conversation_history: Optional[List[Dict[str, str]]] = None
195
+ ) -> str:
196
+ """Format prompt for Gemma models."""
197
+ messages = []
198
+
199
+ if system_prompt:
200
+ messages.append({"role": "system", "content": system_prompt})
201
+
202
+ if conversation_history:
203
+ messages.extend(conversation_history)
204
+
205
+ messages.append({"role": "user", "content": prompt})
206
+
207
+ # Use tokenizer's chat template if available
208
+ if hasattr(self.tokenizer, 'apply_chat_template'):
209
+ return self.tokenizer.apply_chat_template(
210
+ messages,
211
+ tokenize=False,
212
+ add_generation_prompt=True
213
+ )
214
+ else:
215
+ # Fallback format
216
+ formatted = ""
217
+ for msg in messages:
218
+ formatted += f"<{msg['role']}>\n{msg['content']}\n</{msg['role']}>\n"
219
+ return formatted
220
+
221
+ def _format_qwen_prompt(
222
+ self,
223
+ prompt: str,
224
+ system_prompt: Optional[str] = None,
225
+ conversation_history: Optional[List[Dict[str, str]]] = None
226
+ ) -> str:
227
+ """Format prompt for Qwen models."""
228
+ messages = []
229
+
230
+ if system_prompt:
231
+ messages.append({"role": "system", "content": system_prompt})
232
+ else:
233
+ messages.append({
234
+ "role": "system",
235
+ "content": "You are Qwen, created by Alibaba Cloud. You are a helpful assistant."
236
+ })
237
+
238
+ if conversation_history:
239
+ messages.extend(conversation_history)
240
+
241
+ messages.append({"role": "user", "content": prompt})
242
+
243
+ if hasattr(self.tokenizer, 'apply_chat_template'):
244
+ return self.tokenizer.apply_chat_template(
245
+ messages,
246
+ tokenize=False,
247
+ add_generation_prompt=True
248
+ )
249
+ else:
250
+ # Fallback format
251
+ formatted = ""
252
+ for msg in messages:
253
+ formatted += f"<|im_start|>{msg['role']}\n{msg['content']}<|im_end|>\n"
254
+ formatted += "<|im_start|>assistant\n"
255
+ return formatted
256
+
257
+ def _format_phi_prompt(
258
+ self,
259
+ prompt: str,
260
+ system_prompt: Optional[str] = None,
261
+ conversation_history: Optional[List[Dict[str, str]]] = None
262
+ ) -> str:
263
+ """Format prompt for Phi models."""
264
+ messages = []
265
+
266
+ if system_prompt:
267
+ messages.append({"role": "system", "content": system_prompt})
268
+
269
+ if conversation_history:
270
+ messages.extend(conversation_history)
271
+
272
+ messages.append({"role": "user", "content": prompt})
273
+
274
+ if hasattr(self.tokenizer, 'apply_chat_template'):
275
+ return self.tokenizer.apply_chat_template(
276
+ messages,
277
+ tokenize=False,
278
+ add_generation_prompt=True
279
+ )
280
+ else:
281
+ # Phi-3 format
282
+ formatted = ""
283
+ for msg in messages:
284
+ formatted += f"<|{msg['role']}|>\n{msg['content']}<|end|>\n"
285
+ formatted += "<|assistant|>\n"
286
+ return formatted
287
+
288
+ def _format_dialogpt_prompt(
289
+ self,
290
+ prompt: str,
291
+ conversation_history: Optional[List[Dict[str, str]]] = None
292
+ ) -> str:
293
+ """Format prompt for DialoGPT models."""
294
+ # DialoGPT is conversational, so we concatenate with EOS tokens
295
+ conversation = ""
296
+
297
+ if conversation_history:
298
+ for turn in conversation_history:
299
+ if turn["role"] == "user":
300
+ conversation += turn["content"] + self.tokenizer.eos_token
301
+ elif turn["role"] == "assistant":
302
+ conversation += turn["content"] + self.tokenizer.eos_token
303
+
304
+ conversation += prompt + self.tokenizer.eos_token
305
+ return conversation
306
+
307
+ def _format_simple_prompt(
308
+ self,
309
+ prompt: str,
310
+ system_prompt: Optional[str] = None,
311
+ conversation_history: Optional[List[Dict[str, str]]] = None
312
+ ) -> str:
313
+ """Simple fallback prompt format."""
314
+ formatted = ""
315
+
316
+ if system_prompt:
317
+ formatted += f"System: {system_prompt}\n\n"
318
+
319
+ if conversation_history:
320
+ for turn in conversation_history:
321
+ formatted += f"{turn['role'].title()}: {turn['content']}\n"
322
+
323
+ formatted += f"User: {prompt}\nAssistant:"
324
+ return formatted
325
+
326
+ def _get_conversation_history(
327
+ self,
328
+ user_id: Optional[str],
329
+ session_id: Optional[str]
330
+ ) -> List[Dict[str, str]]:
331
+ """Get conversation history from memory."""
332
+ if not self.conversation_memory or not user_id or not session_id:
333
+ return []
334
+
335
+ try:
336
+ # This would be implemented based on your memory system
337
+ # For now, return empty list
338
+ return []
339
+ except Exception as e:
340
+ self.logger.warning(f"Could not retrieve conversation history: {e}")
341
+ return []
342
+
343
+ async def ask(
344
+ self,
345
+ prompt: str,
346
+ max_tokens: int = 512,
347
+ temperature: float = 0.7,
348
+ files: Optional[List[Union[str, Path]]] = None,
349
+ system_prompt: Optional[str] = None,
350
+ user_id: Optional[str] = None,
351
+ session_id: Optional[str] = None,
352
+ tools: Optional[List[Dict[str, Any]]] = None,
353
+ structured_output: Optional[Union[type, StructuredOutputConfig]] = None,
354
+ **kwargs
355
+ ) -> AIMessage:
356
+ """
357
+ Send a prompt to the transformer model and return the response.
358
+
359
+ Args:
360
+ prompt: The input prompt
361
+ model: Model name (ignored, uses initialized model)
362
+ max_tokens: Maximum tokens to generate
363
+ temperature: Sampling temperature
364
+ files: File attachments (not supported by transformers)
365
+ system_prompt: System prompt
366
+ user_id: User ID for conversation memory
367
+ session_id: Session ID for conversation memory
368
+ tools: Tool definitions (not supported)
369
+ structured_output: Structured output configuration
370
+ **kwargs: Additional generation parameters
371
+
372
+ Returns:
373
+ AIMessage response
374
+ """
375
+ if not self.model or not self.tokenizer:
376
+ await self._load_model()
377
+
378
+ turn_id = str(uuid.uuid4())
379
+ original_prompt = prompt
380
+
381
+ messages, conversation_session, system_prompt = await self._prepare_conversation_context(
382
+ prompt, files, user_id, session_id, system_prompt
383
+ )
384
+
385
+ if files:
386
+ self.logger.warning(
387
+ "File attachments not supported by TransformersClient"
388
+ )
389
+
390
+ if tools:
391
+ self.logger.warning(
392
+ "Tool calling not supported by TransformersClient"
393
+ )
394
+ all_tool_calls = []
395
+
396
+ # Get conversation history
397
+ conversation_history = self._get_conversation_history(user_id, session_id)
398
+
399
+ # Prepare the prompt
400
+ formatted_prompt = self._prepare_prompt(prompt, system_prompt, conversation_history)
401
+
402
+ # Update generation config
403
+ gen_config = GenerationConfig(
404
+ max_new_tokens=max_tokens,
405
+ temperature=temperature,
406
+ top_p=kwargs.get('top_p', 0.9),
407
+ top_k=kwargs.get('top_k', 50),
408
+ do_sample=temperature > 0,
409
+ pad_token_id=self.tokenizer.pad_token_id,
410
+ eos_token_id=self.tokenizer.eos_token_id,
411
+ repetition_penalty=kwargs.get('repetition_penalty', 1.1),
412
+ )
413
+
414
+ # Tokenize input
415
+ inputs = self.tokenizer.encode(formatted_prompt, return_tensors="pt")
416
+ if self.device != "cpu":
417
+ inputs = inputs.to(self.device)
418
+
419
+ # Generate response
420
+ start_time = time.time()
421
+
422
+ with torch.no_grad():
423
+ outputs = self.model.generate(
424
+ inputs,
425
+ generation_config=gen_config,
426
+ **kwargs
427
+ )
428
+
429
+ generation_time = time.time() - start_time
430
+
431
+ # Decode response
432
+ input_length = inputs.shape[1]
433
+ generated_ids = outputs[0][input_length:]
434
+ response_text = self.tokenizer.decode(generated_ids, skip_special_tokens=True)
435
+
436
+ # Clean up response
437
+ response_text = response_text.strip()
438
+
439
+ # Create usage statistics
440
+ usage = CompletionUsage(
441
+ prompt_tokens=input_length,
442
+ completion_tokens=len(generated_ids),
443
+ total_tokens=input_length + len(generated_ids)
444
+ )
445
+
446
+ # Create AIMessage response
447
+ ai_message = AIMessageFactory.create_message(
448
+ response=response_text,
449
+ input_text=original_prompt,
450
+ user_id=user_id,
451
+ session_id=session_id,
452
+ turn_id=turn_id,
453
+ model=self.model_name,
454
+ text_response=response_text,
455
+ usage=usage,
456
+ response_time=generation_time,
457
+ )
458
+
459
+ # Store conversation turn if memory is available
460
+ # Update conversation memory
461
+ tools_used = [tc.name for tc in all_tool_calls]
462
+ await self._update_conversation_memory(
463
+ user_id,
464
+ session_id,
465
+ conversation_session,
466
+ messages,
467
+ system_prompt,
468
+ turn_id,
469
+ original_prompt,
470
+ response_text,
471
+ tools_used
472
+ )
473
+
474
+ # Handle structured output if requested
475
+ if structured_output:
476
+ try:
477
+ structured_result = await self._handle_structured_output(
478
+ {"content": [{"type": "text", "text": response_text}]},
479
+ structured_output
480
+ )
481
+ ai_message.structured_output = structured_result
482
+ except Exception as e:
483
+ self.logger.warning(f"Failed to parse structured output: {e}")
484
+
485
+ return ai_message
486
+
487
+ async def ask_stream(
488
+ self,
489
+ prompt: str,
490
+ model: Optional[str] = None,
491
+ max_tokens: int = 512,
492
+ temperature: float = 0.7,
493
+ files: Optional[List[Union[str, Path]]] = None,
494
+ system_prompt: Optional[str] = None,
495
+ user_id: Optional[str] = None,
496
+ session_id: Optional[str] = None,
497
+ tools: Optional[List[Dict[str, Any]]] = None,
498
+ **kwargs
499
+ ) -> AsyncIterator[str]:
500
+ """
501
+ Stream the model's response.
502
+
503
+ Note: True streaming is not easily available with transformers,
504
+ so this implementation yields the complete response.
505
+ """
506
+ response = await self.ask(
507
+ prompt=prompt,
508
+ model=model,
509
+ max_tokens=max_tokens,
510
+ temperature=temperature,
511
+ files=files,
512
+ system_prompt=system_prompt,
513
+ user_id=user_id,
514
+ session_id=session_id,
515
+ tools=tools,
516
+ **kwargs
517
+ )
518
+
519
+ # Simulate streaming by yielding chunks
520
+ text = response.content
521
+ chunk_size = 10 # Characters per chunk
522
+
523
+ for i in range(0, len(text), chunk_size):
524
+ chunk = text[i:i + chunk_size]
525
+ yield chunk
526
+ await asyncio.sleep(0.01) # Small delay to simulate streaming
527
+
528
+ async def batch_ask(self, requests: List[Dict[str, Any]]) -> List[AIMessage]:
529
+ """
530
+ Process multiple requests in batch.
531
+
532
+ Note: This processes requests sequentially to avoid memory issues
533
+ with multiple models loaded simultaneously.
534
+ """
535
+ results = []
536
+ for request in requests:
537
+ try:
538
+ result = await self.ask(**request)
539
+ results.append(result)
540
+ except Exception as e:
541
+ self.logger.error(f"Error in batch request: {e}")
542
+ # Create error response
543
+ error_message = AIMessageFactory.create_message(
544
+ response=result,
545
+ input_text=request.get('prompt', ''),
546
+ user_id=request.get('user_id'),
547
+ session_id=request.get('session_id'),
548
+ turn_id=str(uuid.uuid4()),
549
+ model=self.model_name,
550
+ usage=CompletionUsage(prompt_tokens=0, completion_tokens=0, total_tokens=0)
551
+ )
552
+ results.append(error_message)
553
+
554
+ return results
555
+
556
+ def get_model_info(self) -> Dict[str, Any]:
557
+ """Get information about the loaded model."""
558
+ if not self.model:
559
+ return {"status": "not_loaded"}
560
+
561
+ return {
562
+ "model_name": self.model_name,
563
+ "device": self.device,
564
+ "torch_dtype": str(self.torch_dtype),
565
+ "status": "loaded",
566
+ "vocab_size": self.tokenizer.vocab_size if self.tokenizer else None,
567
+ "max_position_embeddings": getattr(self.model.config, 'max_position_embeddings', None),
568
+ }
569
+
570
+ async def clear_model(self):
571
+ """Clear the model from memory."""
572
+ if self.model:
573
+ del self.model
574
+ self.model = None
575
+ if self.tokenizer:
576
+ del self.tokenizer
577
+ self.tokenizer = None
578
+ if torch.cuda.is_available():
579
+ torch.cuda.empty_cache()
580
+ self.logger.info(
581
+ "Model cleared from memory"
582
+ )
@@ -0,0 +1,18 @@
1
+ from __future__ import annotations
2
+ from typing import Any, Dict, Optional, Type
3
+ from dataclasses import dataclass, field
4
+ from .base import AbstractClient
5
+
6
+
7
+ @dataclass
8
+ class LLMConfig:
9
+ """Resolved LLM configuration."""
10
+ provider: Optional[str] = None
11
+ model: Optional[str] = None
12
+ temperature: float = 0.1
13
+ top_k: int = 41
14
+ top_p: float = 0.9
15
+ max_tokens: Optional[int] = None
16
+ client_class: Optional[Type[AbstractClient]] = None
17
+ client_instance: Optional[AbstractClient] = None
18
+ extra: Dict[str, Any] = field(default_factory=dict)