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.
- {ws_bom_robot_app-0.0.78/ws_bom_robot_app.egg-info → ws_bom_robot_app-0.0.80}/PKG-INFO +74 -49
- {ws_bom_robot_app-0.0.78 → ws_bom_robot_app-0.0.80}/README.md +73 -48
- {ws_bom_robot_app-0.0.78 → ws_bom_robot_app-0.0.80}/setup.py +1 -1
- {ws_bom_robot_app-0.0.78 → ws_bom_robot_app-0.0.80}/ws_bom_robot_app/config.py +3 -1
- {ws_bom_robot_app-0.0.78 → ws_bom_robot_app-0.0.80}/ws_bom_robot_app/cron_manager.py +8 -7
- {ws_bom_robot_app-0.0.78 → ws_bom_robot_app-0.0.80}/ws_bom_robot_app/llm/main.py +12 -3
- {ws_bom_robot_app-0.0.78 → ws_bom_robot_app-0.0.80}/ws_bom_robot_app/llm/models/api.py +33 -0
- {ws_bom_robot_app-0.0.78 → ws_bom_robot_app-0.0.80}/ws_bom_robot_app/llm/nebuly_handler.py +14 -10
- {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
- ws_bom_robot_app-0.0.80/ws_bom_robot_app/llm/utils/cleanup.py +74 -0
- ws_bom_robot_app-0.0.80/ws_bom_robot_app/llm/utils/download.py +185 -0
- {ws_bom_robot_app-0.0.78 → ws_bom_robot_app-0.0.80}/ws_bom_robot_app/main.py +4 -1
- {ws_bom_robot_app-0.0.78 → ws_bom_robot_app-0.0.80/ws_bom_robot_app.egg-info}/PKG-INFO +74 -49
- {ws_bom_robot_app-0.0.78 → ws_bom_robot_app-0.0.80}/ws_bom_robot_app.egg-info/SOURCES.txt +1 -1
- ws_bom_robot_app-0.0.78/ws_bom_robot_app/llm/utils/download.py +0 -79
- ws_bom_robot_app-0.0.78/ws_bom_robot_app/llm/utils/kb.py +0 -34
- {ws_bom_robot_app-0.0.78 → ws_bom_robot_app-0.0.80}/MANIFEST.in +0 -0
- {ws_bom_robot_app-0.0.78 → ws_bom_robot_app-0.0.80}/pyproject.toml +0 -0
- {ws_bom_robot_app-0.0.78 → ws_bom_robot_app-0.0.80}/requirements.txt +0 -0
- {ws_bom_robot_app-0.0.78 → ws_bom_robot_app-0.0.80}/setup.cfg +0 -0
- {ws_bom_robot_app-0.0.78 → ws_bom_robot_app-0.0.80}/ws_bom_robot_app/__init__.py +0 -0
- {ws_bom_robot_app-0.0.78 → ws_bom_robot_app-0.0.80}/ws_bom_robot_app/auth.py +0 -0
- {ws_bom_robot_app-0.0.78 → ws_bom_robot_app-0.0.80}/ws_bom_robot_app/llm/__init__.py +0 -0
- {ws_bom_robot_app-0.0.78 → ws_bom_robot_app-0.0.80}/ws_bom_robot_app/llm/agent_context.py +0 -0
- {ws_bom_robot_app-0.0.78 → ws_bom_robot_app-0.0.80}/ws_bom_robot_app/llm/agent_description.py +0 -0
- {ws_bom_robot_app-0.0.78 → ws_bom_robot_app-0.0.80}/ws_bom_robot_app/llm/agent_handler.py +0 -0
- {ws_bom_robot_app-0.0.78 → ws_bom_robot_app-0.0.80}/ws_bom_robot_app/llm/agent_lcel.py +0 -0
- {ws_bom_robot_app-0.0.78 → ws_bom_robot_app-0.0.80}/ws_bom_robot_app/llm/api.py +0 -0
- {ws_bom_robot_app-0.0.78 → ws_bom_robot_app-0.0.80}/ws_bom_robot_app/llm/defaut_prompt.py +0 -0
- {ws_bom_robot_app-0.0.78 → ws_bom_robot_app-0.0.80}/ws_bom_robot_app/llm/feedbacks/__init__.py +0 -0
- {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
- {ws_bom_robot_app-0.0.78 → ws_bom_robot_app-0.0.80}/ws_bom_robot_app/llm/models/__init__.py +0 -0
- {ws_bom_robot_app-0.0.78 → ws_bom_robot_app-0.0.80}/ws_bom_robot_app/llm/models/base.py +0 -0
- {ws_bom_robot_app-0.0.78 → ws_bom_robot_app-0.0.80}/ws_bom_robot_app/llm/models/feedback.py +0 -0
- {ws_bom_robot_app-0.0.78 → ws_bom_robot_app-0.0.80}/ws_bom_robot_app/llm/models/kb.py +0 -0
- {ws_bom_robot_app-0.0.78 → ws_bom_robot_app-0.0.80}/ws_bom_robot_app/llm/providers/__init__.py +0 -0
- {ws_bom_robot_app-0.0.78 → ws_bom_robot_app-0.0.80}/ws_bom_robot_app/llm/tools/__init__.py +0 -0
- {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
- {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
- {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
- {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
- {ws_bom_robot_app-0.0.78 → ws_bom_robot_app-0.0.80}/ws_bom_robot_app/llm/tools/utils.py +0 -0
- {ws_bom_robot_app-0.0.78 → ws_bom_robot_app-0.0.80}/ws_bom_robot_app/llm/utils/__init__.py +0 -0
- {ws_bom_robot_app-0.0.78 → ws_bom_robot_app-0.0.80}/ws_bom_robot_app/llm/utils/agent.py +0 -0
- {ws_bom_robot_app-0.0.78 → ws_bom_robot_app-0.0.80}/ws_bom_robot_app/llm/utils/chunker.py +0 -0
- {ws_bom_robot_app-0.0.78 → ws_bom_robot_app-0.0.80}/ws_bom_robot_app/llm/utils/cms.py +0 -0
- {ws_bom_robot_app-0.0.78 → ws_bom_robot_app-0.0.80}/ws_bom_robot_app/llm/utils/print.py +0 -0
- {ws_bom_robot_app-0.0.78 → ws_bom_robot_app-0.0.80}/ws_bom_robot_app/llm/utils/secrets.py +0 -0
- {ws_bom_robot_app-0.0.78 → ws_bom_robot_app-0.0.80}/ws_bom_robot_app/llm/utils/webhooks.py +0 -0
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {ws_bom_robot_app-0.0.78 → ws_bom_robot_app-0.0.80}/ws_bom_robot_app/task_manager.py +0 -0
- {ws_bom_robot_app-0.0.78 → ws_bom_robot_app-0.0.80}/ws_bom_robot_app/util.py +0 -0
- {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
- {ws_bom_robot_app-0.0.78 → ws_bom_robot_app-0.0.80}/ws_bom_robot_app.egg-info/requires.txt +0 -0
- {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.
|
|
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
|
-
|
|
87
|
-
|
|
88
|
-
```
|
|
89
|
-
#
|
|
90
|
-
robot_env=
|
|
91
|
-
robot_user=
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
robot_cms_host='
|
|
96
|
-
|
|
97
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
#
|
|
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
|
-
|
|
313
|
+
|
|
289
314
|
```
|
|
@@ -17,18 +17,30 @@ from ws_bom_robot_app import main
|
|
|
17
17
|
app = main.app
|
|
18
18
|
```
|
|
19
19
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
```
|
|
23
|
-
#
|
|
24
|
-
robot_env=
|
|
25
|
-
robot_user=
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
robot_cms_host='
|
|
30
|
-
|
|
31
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
#
|
|
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
|
-
|
|
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.
|
|
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.
|
|
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.
|
|
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
|
-
|
|
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
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
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
|