ws-bom-robot-app 0.0.78__tar.gz → 0.0.80__tar.gz

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 (82) hide show
  1. {ws_bom_robot_app-0.0.78/ws_bom_robot_app.egg-info → ws_bom_robot_app-0.0.80}/PKG-INFO +74 -49
  2. {ws_bom_robot_app-0.0.78 → ws_bom_robot_app-0.0.80}/README.md +73 -48
  3. {ws_bom_robot_app-0.0.78 → ws_bom_robot_app-0.0.80}/setup.py +1 -1
  4. {ws_bom_robot_app-0.0.78 → ws_bom_robot_app-0.0.80}/ws_bom_robot_app/config.py +3 -1
  5. {ws_bom_robot_app-0.0.78 → ws_bom_robot_app-0.0.80}/ws_bom_robot_app/cron_manager.py +8 -7
  6. {ws_bom_robot_app-0.0.78 → ws_bom_robot_app-0.0.80}/ws_bom_robot_app/llm/main.py +12 -3
  7. {ws_bom_robot_app-0.0.78 → ws_bom_robot_app-0.0.80}/ws_bom_robot_app/llm/models/api.py +33 -0
  8. {ws_bom_robot_app-0.0.78 → ws_bom_robot_app-0.0.80}/ws_bom_robot_app/llm/nebuly_handler.py +14 -10
  9. {ws_bom_robot_app-0.0.78 → ws_bom_robot_app-0.0.80}/ws_bom_robot_app/llm/providers/llm_manager.py +94 -26
  10. ws_bom_robot_app-0.0.80/ws_bom_robot_app/llm/utils/cleanup.py +74 -0
  11. ws_bom_robot_app-0.0.80/ws_bom_robot_app/llm/utils/download.py +185 -0
  12. {ws_bom_robot_app-0.0.78 → ws_bom_robot_app-0.0.80}/ws_bom_robot_app/main.py +4 -1
  13. {ws_bom_robot_app-0.0.78 → ws_bom_robot_app-0.0.80/ws_bom_robot_app.egg-info}/PKG-INFO +74 -49
  14. {ws_bom_robot_app-0.0.78 → ws_bom_robot_app-0.0.80}/ws_bom_robot_app.egg-info/SOURCES.txt +1 -1
  15. ws_bom_robot_app-0.0.78/ws_bom_robot_app/llm/utils/download.py +0 -79
  16. ws_bom_robot_app-0.0.78/ws_bom_robot_app/llm/utils/kb.py +0 -34
  17. {ws_bom_robot_app-0.0.78 → ws_bom_robot_app-0.0.80}/MANIFEST.in +0 -0
  18. {ws_bom_robot_app-0.0.78 → ws_bom_robot_app-0.0.80}/pyproject.toml +0 -0
  19. {ws_bom_robot_app-0.0.78 → ws_bom_robot_app-0.0.80}/requirements.txt +0 -0
  20. {ws_bom_robot_app-0.0.78 → ws_bom_robot_app-0.0.80}/setup.cfg +0 -0
  21. {ws_bom_robot_app-0.0.78 → ws_bom_robot_app-0.0.80}/ws_bom_robot_app/__init__.py +0 -0
  22. {ws_bom_robot_app-0.0.78 → ws_bom_robot_app-0.0.80}/ws_bom_robot_app/auth.py +0 -0
  23. {ws_bom_robot_app-0.0.78 → ws_bom_robot_app-0.0.80}/ws_bom_robot_app/llm/__init__.py +0 -0
  24. {ws_bom_robot_app-0.0.78 → ws_bom_robot_app-0.0.80}/ws_bom_robot_app/llm/agent_context.py +0 -0
  25. {ws_bom_robot_app-0.0.78 → ws_bom_robot_app-0.0.80}/ws_bom_robot_app/llm/agent_description.py +0 -0
  26. {ws_bom_robot_app-0.0.78 → ws_bom_robot_app-0.0.80}/ws_bom_robot_app/llm/agent_handler.py +0 -0
  27. {ws_bom_robot_app-0.0.78 → ws_bom_robot_app-0.0.80}/ws_bom_robot_app/llm/agent_lcel.py +0 -0
  28. {ws_bom_robot_app-0.0.78 → ws_bom_robot_app-0.0.80}/ws_bom_robot_app/llm/api.py +0 -0
  29. {ws_bom_robot_app-0.0.78 → ws_bom_robot_app-0.0.80}/ws_bom_robot_app/llm/defaut_prompt.py +0 -0
  30. {ws_bom_robot_app-0.0.78 → ws_bom_robot_app-0.0.80}/ws_bom_robot_app/llm/feedbacks/__init__.py +0 -0
  31. {ws_bom_robot_app-0.0.78 → ws_bom_robot_app-0.0.80}/ws_bom_robot_app/llm/feedbacks/feedback_manager.py +0 -0
  32. {ws_bom_robot_app-0.0.78 → ws_bom_robot_app-0.0.80}/ws_bom_robot_app/llm/models/__init__.py +0 -0
  33. {ws_bom_robot_app-0.0.78 → ws_bom_robot_app-0.0.80}/ws_bom_robot_app/llm/models/base.py +0 -0
  34. {ws_bom_robot_app-0.0.78 → ws_bom_robot_app-0.0.80}/ws_bom_robot_app/llm/models/feedback.py +0 -0
  35. {ws_bom_robot_app-0.0.78 → ws_bom_robot_app-0.0.80}/ws_bom_robot_app/llm/models/kb.py +0 -0
  36. {ws_bom_robot_app-0.0.78 → ws_bom_robot_app-0.0.80}/ws_bom_robot_app/llm/providers/__init__.py +0 -0
  37. {ws_bom_robot_app-0.0.78 → ws_bom_robot_app-0.0.80}/ws_bom_robot_app/llm/tools/__init__.py +0 -0
  38. {ws_bom_robot_app-0.0.78 → ws_bom_robot_app-0.0.80}/ws_bom_robot_app/llm/tools/models/__init__.py +0 -0
  39. {ws_bom_robot_app-0.0.78 → ws_bom_robot_app-0.0.80}/ws_bom_robot_app/llm/tools/models/main.py +0 -0
  40. {ws_bom_robot_app-0.0.78 → ws_bom_robot_app-0.0.80}/ws_bom_robot_app/llm/tools/tool_builder.py +0 -0
  41. {ws_bom_robot_app-0.0.78 → ws_bom_robot_app-0.0.80}/ws_bom_robot_app/llm/tools/tool_manager.py +0 -0
  42. {ws_bom_robot_app-0.0.78 → ws_bom_robot_app-0.0.80}/ws_bom_robot_app/llm/tools/utils.py +0 -0
  43. {ws_bom_robot_app-0.0.78 → ws_bom_robot_app-0.0.80}/ws_bom_robot_app/llm/utils/__init__.py +0 -0
  44. {ws_bom_robot_app-0.0.78 → ws_bom_robot_app-0.0.80}/ws_bom_robot_app/llm/utils/agent.py +0 -0
  45. {ws_bom_robot_app-0.0.78 → ws_bom_robot_app-0.0.80}/ws_bom_robot_app/llm/utils/chunker.py +0 -0
  46. {ws_bom_robot_app-0.0.78 → ws_bom_robot_app-0.0.80}/ws_bom_robot_app/llm/utils/cms.py +0 -0
  47. {ws_bom_robot_app-0.0.78 → ws_bom_robot_app-0.0.80}/ws_bom_robot_app/llm/utils/print.py +0 -0
  48. {ws_bom_robot_app-0.0.78 → ws_bom_robot_app-0.0.80}/ws_bom_robot_app/llm/utils/secrets.py +0 -0
  49. {ws_bom_robot_app-0.0.78 → ws_bom_robot_app-0.0.80}/ws_bom_robot_app/llm/utils/webhooks.py +0 -0
  50. {ws_bom_robot_app-0.0.78 → ws_bom_robot_app-0.0.80}/ws_bom_robot_app/llm/vector_store/__init__.py +0 -0
  51. {ws_bom_robot_app-0.0.78 → ws_bom_robot_app-0.0.80}/ws_bom_robot_app/llm/vector_store/db/__init__.py +0 -0
  52. {ws_bom_robot_app-0.0.78 → ws_bom_robot_app-0.0.80}/ws_bom_robot_app/llm/vector_store/db/base.py +0 -0
  53. {ws_bom_robot_app-0.0.78 → ws_bom_robot_app-0.0.80}/ws_bom_robot_app/llm/vector_store/db/chroma.py +0 -0
  54. {ws_bom_robot_app-0.0.78 → ws_bom_robot_app-0.0.80}/ws_bom_robot_app/llm/vector_store/db/faiss.py +0 -0
  55. {ws_bom_robot_app-0.0.78 → ws_bom_robot_app-0.0.80}/ws_bom_robot_app/llm/vector_store/db/manager.py +0 -0
  56. {ws_bom_robot_app-0.0.78 → ws_bom_robot_app-0.0.80}/ws_bom_robot_app/llm/vector_store/db/qdrant.py +0 -0
  57. {ws_bom_robot_app-0.0.78 → ws_bom_robot_app-0.0.80}/ws_bom_robot_app/llm/vector_store/generator.py +0 -0
  58. {ws_bom_robot_app-0.0.78 → ws_bom_robot_app-0.0.80}/ws_bom_robot_app/llm/vector_store/integration/__init__.py +0 -0
  59. {ws_bom_robot_app-0.0.78 → ws_bom_robot_app-0.0.80}/ws_bom_robot_app/llm/vector_store/integration/azure.py +0 -0
  60. {ws_bom_robot_app-0.0.78 → ws_bom_robot_app-0.0.80}/ws_bom_robot_app/llm/vector_store/integration/base.py +0 -0
  61. {ws_bom_robot_app-0.0.78 → ws_bom_robot_app-0.0.80}/ws_bom_robot_app/llm/vector_store/integration/confluence.py +0 -0
  62. {ws_bom_robot_app-0.0.78 → ws_bom_robot_app-0.0.80}/ws_bom_robot_app/llm/vector_store/integration/dropbox.py +0 -0
  63. {ws_bom_robot_app-0.0.78 → ws_bom_robot_app-0.0.80}/ws_bom_robot_app/llm/vector_store/integration/gcs.py +0 -0
  64. {ws_bom_robot_app-0.0.78 → ws_bom_robot_app-0.0.80}/ws_bom_robot_app/llm/vector_store/integration/github.py +0 -0
  65. {ws_bom_robot_app-0.0.78 → ws_bom_robot_app-0.0.80}/ws_bom_robot_app/llm/vector_store/integration/googledrive.py +0 -0
  66. {ws_bom_robot_app-0.0.78 → ws_bom_robot_app-0.0.80}/ws_bom_robot_app/llm/vector_store/integration/jira.py +0 -0
  67. {ws_bom_robot_app-0.0.78 → ws_bom_robot_app-0.0.80}/ws_bom_robot_app/llm/vector_store/integration/manager.py +0 -0
  68. {ws_bom_robot_app-0.0.78 → ws_bom_robot_app-0.0.80}/ws_bom_robot_app/llm/vector_store/integration/s3.py +0 -0
  69. {ws_bom_robot_app-0.0.78 → ws_bom_robot_app-0.0.80}/ws_bom_robot_app/llm/vector_store/integration/sftp.py +0 -0
  70. {ws_bom_robot_app-0.0.78 → ws_bom_robot_app-0.0.80}/ws_bom_robot_app/llm/vector_store/integration/sharepoint.py +0 -0
  71. {ws_bom_robot_app-0.0.78 → ws_bom_robot_app-0.0.80}/ws_bom_robot_app/llm/vector_store/integration/sitemap.py +0 -0
  72. {ws_bom_robot_app-0.0.78 → ws_bom_robot_app-0.0.80}/ws_bom_robot_app/llm/vector_store/integration/slack.py +0 -0
  73. {ws_bom_robot_app-0.0.78 → ws_bom_robot_app-0.0.80}/ws_bom_robot_app/llm/vector_store/integration/thron.py +0 -0
  74. {ws_bom_robot_app-0.0.78 → ws_bom_robot_app-0.0.80}/ws_bom_robot_app/llm/vector_store/loader/__init__.py +0 -0
  75. {ws_bom_robot_app-0.0.78 → ws_bom_robot_app-0.0.80}/ws_bom_robot_app/llm/vector_store/loader/base.py +0 -0
  76. {ws_bom_robot_app-0.0.78 → ws_bom_robot_app-0.0.80}/ws_bom_robot_app/llm/vector_store/loader/docling.py +0 -0
  77. {ws_bom_robot_app-0.0.78 → ws_bom_robot_app-0.0.80}/ws_bom_robot_app/llm/vector_store/loader/json_loader.py +0 -0
  78. {ws_bom_robot_app-0.0.78 → ws_bom_robot_app-0.0.80}/ws_bom_robot_app/task_manager.py +0 -0
  79. {ws_bom_robot_app-0.0.78 → ws_bom_robot_app-0.0.80}/ws_bom_robot_app/util.py +0 -0
  80. {ws_bom_robot_app-0.0.78 → ws_bom_robot_app-0.0.80}/ws_bom_robot_app.egg-info/dependency_links.txt +0 -0
  81. {ws_bom_robot_app-0.0.78 → ws_bom_robot_app-0.0.80}/ws_bom_robot_app.egg-info/requires.txt +0 -0
  82. {ws_bom_robot_app-0.0.78 → ws_bom_robot_app-0.0.80}/ws_bom_robot_app.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ws_bom_robot_app
3
- Version: 0.0.78
3
+ Version: 0.0.80
4
4
  Summary: A FastAPI application serving ws bom/robot/llm platform ai.
5
5
  Home-page: https://github.com/websolutespa/bom
6
6
  Author: Websolute Spa
@@ -83,18 +83,30 @@ from ws_bom_robot_app import main
83
83
  app = main.app
84
84
  ```
85
85
 
86
- FIll `.env` with the following code:
87
-
88
- ```env
89
- #robot_env=local/development/production
90
- robot_env=local
91
- robot_user='[user]'
92
- robot_password='[pwd]'
93
- robot_data_folder='./.data'
94
- robot_cms_auth='[auth]'
95
- robot_cms_host='https://[DOMAIN]'
96
- robot_cms_db_folder=llmVectorDb
97
- robot_cms_files_folder=llmKbFile
86
+ Create a `.env` file in the root directory with the following configuration:
87
+
88
+ ```properties
89
+ # robot configuration
90
+ robot_env=development
91
+ robot_user=your_username
92
+ USER_AGENT=ws-bom-robot-app
93
+
94
+ # cms (bowl) configuration
95
+ robot_cms_host='http://localhost:4000'
96
+ robot_cms_auth='users API-Key your-api-key-here'
97
+
98
+ # llm providers: fill one or more of these with your API keys
99
+ DEEPSEEK_API_KEY="your-deepseek-api-key"
100
+ OPENAI_API_KEY="your-openai-api-key"
101
+ GOOGLE_API_KEY="your-google-api-key"
102
+ ANTHROPIC_API_KEY="your-anthropic-api-key"
103
+ GROQ_API_KEY="your-groq-api-key"
104
+ # ibm
105
+ WATSONX_URL="https://eu-gb.ml.cloud.ibm.com"
106
+ WATSONX_APIKEY="your-watsonx-api-key"
107
+ WATSONX_PROJECTID="your-watsonx-project-id"
108
+ # gvertex: ensure to mount the file in docker
109
+ GOOGLE_APPLICATION_CREDENTIALS="./.data/secrets/google-credentials.json"
98
110
  ```
99
111
 
100
112
  ## 🚀 Run the app
@@ -120,15 +132,52 @@ robot_cms_files_folder=llmKbFile
120
132
  #gunicorn -w 4 -k uvicorn.workers.UvicornWorker main:app --bind
121
133
  ```
122
134
 
123
- ### 🔖 Windows requirements
135
+ ## 📖 API documentation
136
+
137
+ - [swagger](http://localhost:6001/docs)
138
+ - [redoc](http://localhost:6001/redoc)
139
+
140
+ ---
141
+
142
+ ## 🐳 Docker
143
+
144
+ dockerize base image
145
+
146
+ ```pwsh
147
+ <# cpu #>
148
+ docker build -f Dockerfile-robot-base-cpu -t ghcr.io/websolutespa/ws-bom-robot-base:cpu .
149
+ docker push ghcr.io/websolutespa/ws-bom-robot-base:cpu
150
+ <# gpu #>
151
+ docker build -f Dockerfile-robot-base-gpu -t ghcr.io/websolutespa/ws-bom-robot-base:gpu .
152
+ docker push ghcr.io/websolutespa/ws-bom-robot-base:gpu
153
+ ```
154
+
155
+ dockerize app
156
+
157
+ ```pwsh
158
+ docker build -f Dockerfile -t ws-bom-robot-app .
159
+ docker run --rm --name ws-bom-robot-app -d --env-file .env -p 6001:6001 ws-bom-robot-app
160
+ ```
161
+
162
+ docker run mounted to src (dev mode)
124
163
 
125
- #### libmagic (mandatory)
164
+ ```pwsh
165
+ docker run --rm --name ws-bom-robot-app-src -d --env-file .env -v "$(pwd)/ws_bom_robot_app:/app/ws_bom_robot_app" -v "$(pwd)/.data:/app/.data" -v "$(pwd)/tmp:/tmp" -p 6001:6001 ws-bom-robot-app fastapi dev ./ws_bom_robot_app/main.py --host 0.0.0.0 --port 6001
166
+ ```
167
+
168
+ ---
169
+
170
+ ## 🔖 Windows requirements (for RAG functionality only)
171
+
172
+ > ⚠️ While it's strongly recommended to use a docker container for development, you can run the app on Windows with the following requirements
173
+
174
+ ### libmagic (mandatory)
126
175
 
127
176
  ```bash
128
177
  py -m pip install --upgrade python-magic-bin
129
178
  ```
130
179
 
131
- #### tesseract-ocr (mandatory)
180
+ ### tesseract-ocr (mandatory)
132
181
 
133
182
  [Install tesseract](https://github.com/UB-Mannheim/tesseract/wiki)
134
183
  [Last win-64 release](https://github.com/tesseract-ocr/tesseract/releases/download/5.5.0/tesseract-ocr-w64-setup-5.5.0.20241111.exe)
@@ -143,15 +192,15 @@ robot_cms_files_folder=llmKbFile
143
192
  }
144
193
  ```
145
194
 
146
- #### docling
147
-
195
+ ### docling
196
+
148
197
  Set the following environment variables
149
198
 
150
199
  ```pwsh
151
200
  KMP_DUPLICATE_LIB_OK=TRUE
152
201
  ```
153
202
 
154
- #### libreoffice (optional: for robot_env set to development/production)
203
+ ### libreoffice (optional: for robot_env set to development/production)
155
204
 
156
205
  [Install libreoffice](https://www.libreoffice.org/download/download-libreoffice/)
157
206
  [Last win-64 release](https://download.documentfoundation.org/libreoffice/stable/24.8.2/win/x86_64/LibreOffice_24.8.2_Win_x86-64.msi)
@@ -166,7 +215,7 @@ robot_cms_files_folder=llmKbFile
166
215
  }
167
216
  ```
168
217
 
169
- #### poppler (optional: for robot_env set to development/production)
218
+ ### poppler (optional: for robot_env set to development/production)
170
219
 
171
220
  [Download win poppler release](https://github.com/oschwartz10612/poppler-windows/releases)
172
221
  Extract the zip, copy the nested folder "poppler-x.x.x." to a program folder (e.g. C:\Program Files\poppler-24.08.0)
@@ -210,7 +259,7 @@ py -m build && twine check dist/*
210
259
  Install the package in editable project location
211
260
 
212
261
  ```pwsh
213
- py -m pip install --upgrade -e .
262
+ py -m pip install -U -e .
214
263
  py -m pip show ws-bom-robot-app
215
264
  ```
216
265
 
@@ -231,7 +280,7 @@ prospector ./ws_bom_robot_app -t dodgy -t bandit
231
280
  prospector ./ws_bom_robot_app -t pyroma
232
281
  ```
233
282
 
234
- lauch pytest
283
+ #### 🧪 run tests
235
284
 
236
285
  ```pwsh
237
286
  !py -m pip install -U pytest pytest-asyncio pytest-mock pytest-cov pyclean
@@ -242,48 +291,24 @@ pytest --cov=ws_bom_robot_app --log-cli-level=info
242
291
  # pytest --cov=ws_bom_robot_app --log-cli-level=info ./tests/app/llm/vector_store/db
243
292
  ```
244
293
 
245
- launch debugger
294
+ #### 🐞 start debugger
246
295
 
247
296
  ```pwsh
248
297
  streamlit run debugger.py --server.port 8051
249
298
  ```
250
299
 
251
- dockerize base image
252
-
253
- ```pwsh
254
- <# cpu #>
255
- docker build -f Dockerfile-robot-base-cpu -t ghcr.io/websolutespa/ws-bom-robot-base:cpu .
256
- docker push ghcr.io/websolutespa/ws-bom-robot-base:cpu
257
- <# gpu #>
258
- docker build -f Dockerfile-robot-base-gpu -t ghcr.io/websolutespa/ws-bom-robot-base:gpu .
259
- docker push ghcr.io/websolutespa/ws-bom-robot-base:gpu
260
- ```
261
-
262
- dockerize app
263
-
264
- ```pwsh
265
- docker build -f Dockerfile -t ws-bom-robot-app .
266
- docker run --rm --name ws-bom-robot-app -d -p 6001:6001 ws-bom-robot-app
267
- ```
268
-
269
- docker run mounted to src
270
-
271
- ```pwsh
272
- docker run --rm --name ws-bom-robot-app-src -d -v "$(pwd)/ws_bom_robot_app:/app/ws_bom_robot_app" -v "$(pwd)/.data:/app/.data" -v "$(pwd)/tmp:/tmp" -p 6001:6001 ws-bom-robot-app
273
- ```
274
-
275
300
  ### ✈️ publish
276
301
 
277
302
  - [testpypi](https://test.pypi.org/project/ws-bom-robot-app/)
278
303
 
279
304
  ```pwsh
280
305
  twine upload --verbose -r testpypi dist/*
281
- #py -m pip install -i https://test.pypi.org/simple/ --upgrade ws-bom-robot-app
306
+ #pip install -i https://test.pypi.org/simple/ -U ws-bom-robot-app
282
307
  ```
283
308
 
284
309
  - [pypi](https://pypi.org/project/ws-bom-robot-app/)
285
310
 
286
311
  ```pwsh
287
312
  twine upload --verbose dist/*
288
- #py -m pip install --upgrade ws-bom-robot-app
313
+
289
314
  ```
@@ -17,18 +17,30 @@ from ws_bom_robot_app import main
17
17
  app = main.app
18
18
  ```
19
19
 
20
- FIll `.env` with the following code:
21
-
22
- ```env
23
- #robot_env=local/development/production
24
- robot_env=local
25
- robot_user='[user]'
26
- robot_password='[pwd]'
27
- robot_data_folder='./.data'
28
- robot_cms_auth='[auth]'
29
- robot_cms_host='https://[DOMAIN]'
30
- robot_cms_db_folder=llmVectorDb
31
- robot_cms_files_folder=llmKbFile
20
+ Create a `.env` file in the root directory with the following configuration:
21
+
22
+ ```properties
23
+ # robot configuration
24
+ robot_env=development
25
+ robot_user=your_username
26
+ USER_AGENT=ws-bom-robot-app
27
+
28
+ # cms (bowl) configuration
29
+ robot_cms_host='http://localhost:4000'
30
+ robot_cms_auth='users API-Key your-api-key-here'
31
+
32
+ # llm providers: fill one or more of these with your API keys
33
+ DEEPSEEK_API_KEY="your-deepseek-api-key"
34
+ OPENAI_API_KEY="your-openai-api-key"
35
+ GOOGLE_API_KEY="your-google-api-key"
36
+ ANTHROPIC_API_KEY="your-anthropic-api-key"
37
+ GROQ_API_KEY="your-groq-api-key"
38
+ # ibm
39
+ WATSONX_URL="https://eu-gb.ml.cloud.ibm.com"
40
+ WATSONX_APIKEY="your-watsonx-api-key"
41
+ WATSONX_PROJECTID="your-watsonx-project-id"
42
+ # gvertex: ensure to mount the file in docker
43
+ GOOGLE_APPLICATION_CREDENTIALS="./.data/secrets/google-credentials.json"
32
44
  ```
33
45
 
34
46
  ## 🚀 Run the app
@@ -54,15 +66,52 @@ robot_cms_files_folder=llmKbFile
54
66
  #gunicorn -w 4 -k uvicorn.workers.UvicornWorker main:app --bind
55
67
  ```
56
68
 
57
- ### 🔖 Windows requirements
69
+ ## 📖 API documentation
70
+
71
+ - [swagger](http://localhost:6001/docs)
72
+ - [redoc](http://localhost:6001/redoc)
73
+
74
+ ---
75
+
76
+ ## 🐳 Docker
77
+
78
+ dockerize base image
79
+
80
+ ```pwsh
81
+ <# cpu #>
82
+ docker build -f Dockerfile-robot-base-cpu -t ghcr.io/websolutespa/ws-bom-robot-base:cpu .
83
+ docker push ghcr.io/websolutespa/ws-bom-robot-base:cpu
84
+ <# gpu #>
85
+ docker build -f Dockerfile-robot-base-gpu -t ghcr.io/websolutespa/ws-bom-robot-base:gpu .
86
+ docker push ghcr.io/websolutespa/ws-bom-robot-base:gpu
87
+ ```
88
+
89
+ dockerize app
90
+
91
+ ```pwsh
92
+ docker build -f Dockerfile -t ws-bom-robot-app .
93
+ docker run --rm --name ws-bom-robot-app -d --env-file .env -p 6001:6001 ws-bom-robot-app
94
+ ```
95
+
96
+ docker run mounted to src (dev mode)
58
97
 
59
- #### libmagic (mandatory)
98
+ ```pwsh
99
+ docker run --rm --name ws-bom-robot-app-src -d --env-file .env -v "$(pwd)/ws_bom_robot_app:/app/ws_bom_robot_app" -v "$(pwd)/.data:/app/.data" -v "$(pwd)/tmp:/tmp" -p 6001:6001 ws-bom-robot-app fastapi dev ./ws_bom_robot_app/main.py --host 0.0.0.0 --port 6001
100
+ ```
101
+
102
+ ---
103
+
104
+ ## 🔖 Windows requirements (for RAG functionality only)
105
+
106
+ > ⚠️ While it's strongly recommended to use a docker container for development, you can run the app on Windows with the following requirements
107
+
108
+ ### libmagic (mandatory)
60
109
 
61
110
  ```bash
62
111
  py -m pip install --upgrade python-magic-bin
63
112
  ```
64
113
 
65
- #### tesseract-ocr (mandatory)
114
+ ### tesseract-ocr (mandatory)
66
115
 
67
116
  [Install tesseract](https://github.com/UB-Mannheim/tesseract/wiki)
68
117
  [Last win-64 release](https://github.com/tesseract-ocr/tesseract/releases/download/5.5.0/tesseract-ocr-w64-setup-5.5.0.20241111.exe)
@@ -77,15 +126,15 @@ robot_cms_files_folder=llmKbFile
77
126
  }
78
127
  ```
79
128
 
80
- #### docling
81
-
129
+ ### docling
130
+
82
131
  Set the following environment variables
83
132
 
84
133
  ```pwsh
85
134
  KMP_DUPLICATE_LIB_OK=TRUE
86
135
  ```
87
136
 
88
- #### libreoffice (optional: for robot_env set to development/production)
137
+ ### libreoffice (optional: for robot_env set to development/production)
89
138
 
90
139
  [Install libreoffice](https://www.libreoffice.org/download/download-libreoffice/)
91
140
  [Last win-64 release](https://download.documentfoundation.org/libreoffice/stable/24.8.2/win/x86_64/LibreOffice_24.8.2_Win_x86-64.msi)
@@ -100,7 +149,7 @@ robot_cms_files_folder=llmKbFile
100
149
  }
101
150
  ```
102
151
 
103
- #### poppler (optional: for robot_env set to development/production)
152
+ ### poppler (optional: for robot_env set to development/production)
104
153
 
105
154
  [Download win poppler release](https://github.com/oschwartz10612/poppler-windows/releases)
106
155
  Extract the zip, copy the nested folder "poppler-x.x.x." to a program folder (e.g. C:\Program Files\poppler-24.08.0)
@@ -144,7 +193,7 @@ py -m build && twine check dist/*
144
193
  Install the package in editable project location
145
194
 
146
195
  ```pwsh
147
- py -m pip install --upgrade -e .
196
+ py -m pip install -U -e .
148
197
  py -m pip show ws-bom-robot-app
149
198
  ```
150
199
 
@@ -165,7 +214,7 @@ prospector ./ws_bom_robot_app -t dodgy -t bandit
165
214
  prospector ./ws_bom_robot_app -t pyroma
166
215
  ```
167
216
 
168
- lauch pytest
217
+ #### 🧪 run tests
169
218
 
170
219
  ```pwsh
171
220
  !py -m pip install -U pytest pytest-asyncio pytest-mock pytest-cov pyclean
@@ -176,48 +225,24 @@ pytest --cov=ws_bom_robot_app --log-cli-level=info
176
225
  # pytest --cov=ws_bom_robot_app --log-cli-level=info ./tests/app/llm/vector_store/db
177
226
  ```
178
227
 
179
- launch debugger
228
+ #### 🐞 start debugger
180
229
 
181
230
  ```pwsh
182
231
  streamlit run debugger.py --server.port 8051
183
232
  ```
184
233
 
185
- dockerize base image
186
-
187
- ```pwsh
188
- <# cpu #>
189
- docker build -f Dockerfile-robot-base-cpu -t ghcr.io/websolutespa/ws-bom-robot-base:cpu .
190
- docker push ghcr.io/websolutespa/ws-bom-robot-base:cpu
191
- <# gpu #>
192
- docker build -f Dockerfile-robot-base-gpu -t ghcr.io/websolutespa/ws-bom-robot-base:gpu .
193
- docker push ghcr.io/websolutespa/ws-bom-robot-base:gpu
194
- ```
195
-
196
- dockerize app
197
-
198
- ```pwsh
199
- docker build -f Dockerfile -t ws-bom-robot-app .
200
- docker run --rm --name ws-bom-robot-app -d -p 6001:6001 ws-bom-robot-app
201
- ```
202
-
203
- docker run mounted to src
204
-
205
- ```pwsh
206
- docker run --rm --name ws-bom-robot-app-src -d -v "$(pwd)/ws_bom_robot_app:/app/ws_bom_robot_app" -v "$(pwd)/.data:/app/.data" -v "$(pwd)/tmp:/tmp" -p 6001:6001 ws-bom-robot-app
207
- ```
208
-
209
234
  ### ✈️ publish
210
235
 
211
236
  - [testpypi](https://test.pypi.org/project/ws-bom-robot-app/)
212
237
 
213
238
  ```pwsh
214
239
  twine upload --verbose -r testpypi dist/*
215
- #py -m pip install -i https://test.pypi.org/simple/ --upgrade ws-bom-robot-app
240
+ #pip install -i https://test.pypi.org/simple/ -U ws-bom-robot-app
216
241
  ```
217
242
 
218
243
  - [pypi](https://pypi.org/project/ws-bom-robot-app/)
219
244
 
220
245
  ```pwsh
221
246
  twine upload --verbose dist/*
222
- #py -m pip install --upgrade ws-bom-robot-app
247
+
223
248
  ```
@@ -4,7 +4,7 @@ _requirements = [line.split('#')[0].strip() for line in open("requirements.txt")
4
4
 
5
5
  setup(
6
6
  name="ws_bom_robot_app",
7
- version="0.0.78",
7
+ version="0.0.80",
8
8
  description="A FastAPI application serving ws bom/robot/llm platform ai.",
9
9
  long_description=open("README.md", encoding='utf-8').read(),
10
10
  long_description_content_type="text/markdown",
@@ -14,6 +14,8 @@ class Settings(BaseSettings):
14
14
  robot_data_db_folder_out: str = 'out'
15
15
  robot_data_db_folder_store: str = 'store'
16
16
  robot_data_db_retention_days: float = 60
17
+ robot_data_attachment_folder: str = 'attachment'
18
+ robot_data_attachment_retention_days: float = 1
17
19
  robot_loader_max_threads: int = 1
18
20
  robot_task_max_total_parallelism: int = 2 * (os.cpu_count() or 1)
19
21
  robot_task_retention_days: float = 1
@@ -30,7 +32,7 @@ class Settings(BaseSettings):
30
32
  WATSONX_URL: str = ''
31
33
  WATSONX_APIKEY: str = ''
32
34
  WATSONX_PROJECTID: str = ''
33
- NEBULY_API_URL: str =''
35
+ NEBULY_API_URL: str ='https://backend.nebuly.com/'
34
36
  GOOGLE_APPLICATION_CREDENTIALS: str = '' # path to google credentials iam file, e.d. ./.secrets/google-credentials.json
35
37
  model_config = ConfigDict(
36
38
  env_file='./.env',
@@ -8,7 +8,7 @@ from apscheduler.triggers.date import DateTrigger
8
8
  from fastapi import APIRouter
9
9
  from datetime import datetime
10
10
  from ws_bom_robot_app.task_manager import task_manager
11
- from ws_bom_robot_app.llm.utils.kb import kb_cleanup_data_file
11
+ from ws_bom_robot_app.llm.utils.cleanup import kb_cleanup_data_file, chat_cleanup_attachment
12
12
  from ws_bom_robot_app.util import _log
13
13
  from ws_bom_robot_app.config import config
14
14
 
@@ -57,7 +57,8 @@ class Job:
57
57
  class CronManager:
58
58
  _list_default = [
59
59
  Job('cleanup-task',task_manager.cleanup_task, interval=5 * 60),
60
- Job('cleanup-data',kb_cleanup_data_file, interval=180 * 60),
60
+ Job('cleanup-kb-data',kb_cleanup_data_file, interval=180 * 60),
61
+ Job('cleanup-chat-attachment',chat_cleanup_attachment, interval=120 * 60),
61
62
  ]
62
63
  def __get_jobstore_strategy(self) -> JobstoreStrategy:
63
64
  if True or config.runtime_options().is_multi_process:
@@ -139,22 +140,22 @@ class CronManager:
139
140
 
140
141
  def execute_recurring_jobs(self):
141
142
  for job in self.scheduler.get_jobs():
142
- if job.interval:
143
- job.job_func()
143
+ if job.trigger.interval:
144
+ job.func()
144
145
 
145
146
  def pause_recurring_jobs(self):
146
147
  for job in self.scheduler.get_jobs():
147
- if job.interval:
148
+ if job.trigger.interval:
148
149
  self.pause_job(job.id)
149
150
 
150
151
  def resume_recurring_jobs(self):
151
152
  for job in self.scheduler.get_jobs():
152
- if job.interval:
153
+ if job.trigger.interval:
153
154
  self.resume_job(job.id)
154
155
 
155
156
  def remove_recurring_jobs(self):
156
157
  for job in self.scheduler.get_jobs():
157
- if job.interval:
158
+ if job.trigger.interval:
158
159
  self.remove_job(job.id)
159
160
 
160
161
  def clear(self):
@@ -39,6 +39,7 @@ def _parse_formatted_message(message: str) -> str:
39
39
  except:
40
40
  result = message
41
41
  return result
42
+
42
43
  async def __stream(rq: StreamRequest, ctx: Request, queue: Queue, formatted: bool = True) -> None:
43
44
  #os.environ["KMP_DUPLICATE_LIB_OK"] = "TRUE"
44
45
 
@@ -47,11 +48,21 @@ async def __stream(rq: StreamRequest, ctx: Request, queue: Queue, formatted: boo
47
48
  for tool in rq.app_tools:
48
49
  tool.thread_id = rq.thread_id
49
50
 
51
+ #llm
52
+ __llm: LlmInterface = rq.get_llm()
53
+
50
54
  #chat history
51
55
  chat_history: list[BaseMessage] = []
52
56
  for message in rq.messages:
53
57
  if message.role in ["human","user"]:
54
- chat_history.append(HumanMessage(content=message.content))
58
+ _content = message.content
59
+ # multimodal content parsing
60
+ if isinstance(_content, list):
61
+ try:
62
+ _content = await __llm.format_multimodal_content(_content)
63
+ except Exception as e:
64
+ logging.warning(f"Error parsing multimodal content {_content[:100]}: {e}")
65
+ chat_history.append(HumanMessage(content=_content))
55
66
  elif message.role in ["ai","assistant"]:
56
67
  message_content = ""
57
68
  if formatted:
@@ -78,8 +89,6 @@ async def __stream(rq: StreamRequest, ctx: Request, queue: Queue, formatted: boo
78
89
  if message_content:
79
90
  chat_history.append(AIMessage(content=message_content))
80
91
 
81
- #llm
82
- __llm: LlmInterface = rq.get_llm()
83
92
 
84
93
  #agent handler
85
94
  if formatted:
@@ -11,6 +11,39 @@ import os, shutil, uuid
11
11
  from ws_bom_robot_app.config import Settings, config
12
12
 
13
13
  class LlmMessage(BaseModel):
14
+ """
15
+ 💬 multimodal chat
16
+
17
+ The multimodal message allows users to interact with the application using both text and media files.
18
+ `robot` accept multimodal input in a uniform way, regarding the llm provider used.
19
+
20
+ - simple message
21
+
22
+ ```json
23
+ {
24
+ "role": "user",
25
+ "content": "What is the capital of France?"
26
+ }
27
+ ```
28
+
29
+ - multimodal message
30
+
31
+ ```jsonc
32
+ {
33
+ "role": "user",
34
+ "content": [
35
+ { "type": "text", "text": "Read carefully all the attachments, analize the content and provide a summary for each one:" },
36
+ { "type": "image", "url": "https://www.example.com/image/foo.jpg" },
37
+ { "type": "file", "url": "https://www.example.com/pdf/bar.pdf" },
38
+ { "type": "file", "url": "data:plain/text;base64,CiAgICAgIF9fX19fCiAgICAgLyAgIC..." }, // base64 encoded file
39
+ { "type": "media", "mime_type": "plain/text", "data": "CiAgICAgIF9fX19fCiAgICAgLyAgIC..." } // google/gemini specific input format
40
+ ]
41
+ }
42
+ ```
43
+
44
+ > 💡 `url` can be a remote url or a base64 representation of the file: [rfc 2397](https://datatracker.ietf.org/doc/html/rfc2397).
45
+ Can also be used the llm/model specific input format.
46
+ """
14
47
  role: str
15
48
  content: Union[str, list]
16
49
 
@@ -145,16 +145,20 @@ class NebulyHandler(AsyncCallbackHandler):
145
145
  return payload
146
146
 
147
147
  def __parse_multimodal_input(self, input: list[dict]) -> str:
148
- # Parse the multimodal input and return a string representation
149
- # This is a placeholder implementation, you can customize it as needed
150
- parsed_input = ""
151
- for item in input:
152
- if item.get("type") == "text":
153
- parsed_input += item.get("text", "")
154
- elif item.get("type") == "image_url":
155
- parsed_input += " <image>"
156
- # print(parsed_input)
157
- return parsed_input
148
+ """Parse multimodal input and return a string representation."""
149
+ type_mapping = {
150
+ "text": lambda item: item.get("text", ""),
151
+ "image": lambda _: " <image>",
152
+ "image_url": lambda _: " <image>",
153
+ "file": lambda _: " <file>",
154
+ "media": lambda _: " <file>",
155
+ "document": lambda _: " <file>",
156
+ }
157
+
158
+ return "".join(
159
+ type_mapping.get(item.get("type", ""), lambda item: f" <{item.get('type', '')}>")
160
+ (item) for item in input
161
+ )
158
162
 
159
163
  def __parse_multimodal_history(self, messages: list[dict]) -> list[dict]:
160
164
  # Parse the multimodal history and return a list of dictionaries