ws-bom-robot-app 0.0.81__tar.gz → 0.0.83__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 (84) hide show
  1. {ws_bom_robot_app-0.0.81/ws_bom_robot_app.egg-info → ws_bom_robot_app-0.0.83}/PKG-INFO +19 -9
  2. {ws_bom_robot_app-0.0.81 → ws_bom_robot_app-0.0.83}/README.md +15 -5
  3. {ws_bom_robot_app-0.0.81 → ws_bom_robot_app-0.0.83}/requirements.txt +3 -3
  4. {ws_bom_robot_app-0.0.81 → ws_bom_robot_app-0.0.83}/setup.py +1 -1
  5. {ws_bom_robot_app-0.0.81 → ws_bom_robot_app-0.0.83}/ws_bom_robot_app/config.py +10 -0
  6. {ws_bom_robot_app-0.0.81 → ws_bom_robot_app-0.0.83}/ws_bom_robot_app/cron_manager.py +6 -6
  7. {ws_bom_robot_app-0.0.81 → ws_bom_robot_app-0.0.83}/ws_bom_robot_app/llm/agent_description.py +123 -123
  8. {ws_bom_robot_app-0.0.81 → ws_bom_robot_app-0.0.83}/ws_bom_robot_app/llm/agent_handler.py +166 -166
  9. {ws_bom_robot_app-0.0.81 → ws_bom_robot_app-0.0.83}/ws_bom_robot_app/llm/agent_lcel.py +50 -50
  10. {ws_bom_robot_app-0.0.81 → ws_bom_robot_app-0.0.83}/ws_bom_robot_app/llm/api.py +2 -2
  11. {ws_bom_robot_app-0.0.81 → ws_bom_robot_app-0.0.83}/ws_bom_robot_app/llm/defaut_prompt.py +15 -15
  12. {ws_bom_robot_app-0.0.81 → ws_bom_robot_app-0.0.83}/ws_bom_robot_app/llm/feedbacks/feedback_manager.py +66 -66
  13. {ws_bom_robot_app-0.0.81 → ws_bom_robot_app-0.0.83}/ws_bom_robot_app/llm/main.py +158 -158
  14. {ws_bom_robot_app-0.0.81 → ws_bom_robot_app-0.0.83}/ws_bom_robot_app/llm/models/feedback.py +30 -30
  15. {ws_bom_robot_app-0.0.81 → ws_bom_robot_app-0.0.83}/ws_bom_robot_app/llm/nebuly_handler.py +185 -185
  16. {ws_bom_robot_app-0.0.81 → ws_bom_robot_app-0.0.83}/ws_bom_robot_app/llm/providers/llm_manager.py +5 -6
  17. {ws_bom_robot_app-0.0.81 → ws_bom_robot_app-0.0.83}/ws_bom_robot_app/llm/tools/tool_builder.py +65 -65
  18. {ws_bom_robot_app-0.0.81 → ws_bom_robot_app-0.0.83}/ws_bom_robot_app/llm/tools/tool_manager.py +330 -330
  19. {ws_bom_robot_app-0.0.81 → ws_bom_robot_app-0.0.83}/ws_bom_robot_app/llm/tools/utils.py +41 -41
  20. {ws_bom_robot_app-0.0.81 → ws_bom_robot_app-0.0.83}/ws_bom_robot_app/llm/utils/agent.py +34 -34
  21. {ws_bom_robot_app-0.0.81 → ws_bom_robot_app-0.0.83}/ws_bom_robot_app/llm/utils/cleanup.py +7 -0
  22. {ws_bom_robot_app-0.0.81 → ws_bom_robot_app-0.0.83}/ws_bom_robot_app/llm/utils/cms.py +114 -114
  23. {ws_bom_robot_app-0.0.81 → ws_bom_robot_app-0.0.83}/ws_bom_robot_app/llm/utils/download.py +183 -185
  24. {ws_bom_robot_app-0.0.81 → ws_bom_robot_app-0.0.83}/ws_bom_robot_app/llm/utils/print.py +29 -29
  25. {ws_bom_robot_app-0.0.81 → ws_bom_robot_app-0.0.83}/ws_bom_robot_app/llm/vector_store/generator.py +137 -137
  26. {ws_bom_robot_app-0.0.81 → ws_bom_robot_app-0.0.83}/ws_bom_robot_app/llm/vector_store/integration/azure.py +1 -1
  27. ws_bom_robot_app-0.0.83/ws_bom_robot_app/llm/vector_store/integration/base.py +96 -0
  28. {ws_bom_robot_app-0.0.81 → ws_bom_robot_app-0.0.83}/ws_bom_robot_app/llm/vector_store/integration/confluence.py +1 -1
  29. {ws_bom_robot_app-0.0.81 → ws_bom_robot_app-0.0.83}/ws_bom_robot_app/llm/vector_store/integration/dropbox.py +1 -1
  30. {ws_bom_robot_app-0.0.81 → ws_bom_robot_app-0.0.83}/ws_bom_robot_app/llm/vector_store/integration/gcs.py +1 -1
  31. {ws_bom_robot_app-0.0.81 → ws_bom_robot_app-0.0.83}/ws_bom_robot_app/llm/vector_store/integration/github.py +22 -22
  32. {ws_bom_robot_app-0.0.81 → ws_bom_robot_app-0.0.83}/ws_bom_robot_app/llm/vector_store/integration/googledrive.py +1 -1
  33. ws_bom_robot_app-0.0.83/ws_bom_robot_app/llm/vector_store/integration/jira.py +151 -0
  34. {ws_bom_robot_app-0.0.81 → ws_bom_robot_app-0.0.83}/ws_bom_robot_app/llm/vector_store/integration/s3.py +1 -1
  35. {ws_bom_robot_app-0.0.81 → ws_bom_robot_app-0.0.83}/ws_bom_robot_app/llm/vector_store/integration/sftp.py +1 -1
  36. {ws_bom_robot_app-0.0.81 → ws_bom_robot_app-0.0.83}/ws_bom_robot_app/llm/vector_store/integration/sharepoint.py +7 -14
  37. {ws_bom_robot_app-0.0.81 → ws_bom_robot_app-0.0.83}/ws_bom_robot_app/llm/vector_store/integration/shopify.py +143 -144
  38. {ws_bom_robot_app-0.0.81 → ws_bom_robot_app-0.0.83}/ws_bom_robot_app/llm/vector_store/integration/sitemap.py +3 -0
  39. {ws_bom_robot_app-0.0.81 → ws_bom_robot_app-0.0.83}/ws_bom_robot_app/llm/vector_store/integration/slack.py +3 -2
  40. {ws_bom_robot_app-0.0.81 → ws_bom_robot_app-0.0.83}/ws_bom_robot_app/llm/vector_store/integration/thron.py +102 -103
  41. {ws_bom_robot_app-0.0.81 → ws_bom_robot_app-0.0.83}/ws_bom_robot_app/llm/vector_store/loader/base.py +8 -6
  42. {ws_bom_robot_app-0.0.81 → ws_bom_robot_app-0.0.83}/ws_bom_robot_app/llm/vector_store/loader/docling.py +1 -1
  43. {ws_bom_robot_app-0.0.81 → ws_bom_robot_app-0.0.83}/ws_bom_robot_app/llm/vector_store/loader/json_loader.py +25 -25
  44. ws_bom_robot_app-0.0.83/ws_bom_robot_app/subprocess_runner.py +103 -0
  45. {ws_bom_robot_app-0.0.81 → ws_bom_robot_app-0.0.83}/ws_bom_robot_app/task_manager.py +169 -41
  46. {ws_bom_robot_app-0.0.81 → ws_bom_robot_app-0.0.83/ws_bom_robot_app.egg-info}/PKG-INFO +19 -9
  47. {ws_bom_robot_app-0.0.81 → ws_bom_robot_app-0.0.83}/ws_bom_robot_app.egg-info/SOURCES.txt +1 -0
  48. {ws_bom_robot_app-0.0.81 → ws_bom_robot_app-0.0.83}/ws_bom_robot_app.egg-info/requires.txt +3 -3
  49. ws_bom_robot_app-0.0.81/ws_bom_robot_app/llm/vector_store/integration/base.py +0 -54
  50. ws_bom_robot_app-0.0.81/ws_bom_robot_app/llm/vector_store/integration/jira.py +0 -118
  51. {ws_bom_robot_app-0.0.81 → ws_bom_robot_app-0.0.83}/MANIFEST.in +0 -0
  52. {ws_bom_robot_app-0.0.81 → ws_bom_robot_app-0.0.83}/pyproject.toml +0 -0
  53. {ws_bom_robot_app-0.0.81 → ws_bom_robot_app-0.0.83}/setup.cfg +0 -0
  54. {ws_bom_robot_app-0.0.81 → ws_bom_robot_app-0.0.83}/ws_bom_robot_app/__init__.py +0 -0
  55. {ws_bom_robot_app-0.0.81 → ws_bom_robot_app-0.0.83}/ws_bom_robot_app/auth.py +0 -0
  56. {ws_bom_robot_app-0.0.81 → ws_bom_robot_app-0.0.83}/ws_bom_robot_app/llm/__init__.py +0 -0
  57. {ws_bom_robot_app-0.0.81 → ws_bom_robot_app-0.0.83}/ws_bom_robot_app/llm/agent_context.py +0 -0
  58. {ws_bom_robot_app-0.0.81 → ws_bom_robot_app-0.0.83}/ws_bom_robot_app/llm/feedbacks/__init__.py +0 -0
  59. {ws_bom_robot_app-0.0.81 → ws_bom_robot_app-0.0.83}/ws_bom_robot_app/llm/models/__init__.py +0 -0
  60. {ws_bom_robot_app-0.0.81 → ws_bom_robot_app-0.0.83}/ws_bom_robot_app/llm/models/api.py +0 -0
  61. {ws_bom_robot_app-0.0.81 → ws_bom_robot_app-0.0.83}/ws_bom_robot_app/llm/models/base.py +0 -0
  62. {ws_bom_robot_app-0.0.81 → ws_bom_robot_app-0.0.83}/ws_bom_robot_app/llm/models/kb.py +0 -0
  63. {ws_bom_robot_app-0.0.81 → ws_bom_robot_app-0.0.83}/ws_bom_robot_app/llm/providers/__init__.py +0 -0
  64. {ws_bom_robot_app-0.0.81 → ws_bom_robot_app-0.0.83}/ws_bom_robot_app/llm/tools/__init__.py +0 -0
  65. {ws_bom_robot_app-0.0.81 → ws_bom_robot_app-0.0.83}/ws_bom_robot_app/llm/tools/models/__init__.py +0 -0
  66. {ws_bom_robot_app-0.0.81 → ws_bom_robot_app-0.0.83}/ws_bom_robot_app/llm/tools/models/main.py +0 -0
  67. {ws_bom_robot_app-0.0.81 → ws_bom_robot_app-0.0.83}/ws_bom_robot_app/llm/utils/__init__.py +0 -0
  68. {ws_bom_robot_app-0.0.81 → ws_bom_robot_app-0.0.83}/ws_bom_robot_app/llm/utils/chunker.py +0 -0
  69. {ws_bom_robot_app-0.0.81 → ws_bom_robot_app-0.0.83}/ws_bom_robot_app/llm/utils/secrets.py +0 -0
  70. {ws_bom_robot_app-0.0.81 → ws_bom_robot_app-0.0.83}/ws_bom_robot_app/llm/utils/webhooks.py +0 -0
  71. {ws_bom_robot_app-0.0.81 → ws_bom_robot_app-0.0.83}/ws_bom_robot_app/llm/vector_store/__init__.py +0 -0
  72. {ws_bom_robot_app-0.0.81 → ws_bom_robot_app-0.0.83}/ws_bom_robot_app/llm/vector_store/db/__init__.py +0 -0
  73. {ws_bom_robot_app-0.0.81 → ws_bom_robot_app-0.0.83}/ws_bom_robot_app/llm/vector_store/db/base.py +0 -0
  74. {ws_bom_robot_app-0.0.81 → ws_bom_robot_app-0.0.83}/ws_bom_robot_app/llm/vector_store/db/chroma.py +0 -0
  75. {ws_bom_robot_app-0.0.81 → ws_bom_robot_app-0.0.83}/ws_bom_robot_app/llm/vector_store/db/faiss.py +0 -0
  76. {ws_bom_robot_app-0.0.81 → ws_bom_robot_app-0.0.83}/ws_bom_robot_app/llm/vector_store/db/manager.py +0 -0
  77. {ws_bom_robot_app-0.0.81 → ws_bom_robot_app-0.0.83}/ws_bom_robot_app/llm/vector_store/db/qdrant.py +0 -0
  78. {ws_bom_robot_app-0.0.81 → ws_bom_robot_app-0.0.83}/ws_bom_robot_app/llm/vector_store/integration/__init__.py +0 -0
  79. {ws_bom_robot_app-0.0.81 → ws_bom_robot_app-0.0.83}/ws_bom_robot_app/llm/vector_store/integration/manager.py +0 -0
  80. {ws_bom_robot_app-0.0.81 → ws_bom_robot_app-0.0.83}/ws_bom_robot_app/llm/vector_store/loader/__init__.py +0 -0
  81. {ws_bom_robot_app-0.0.81 → ws_bom_robot_app-0.0.83}/ws_bom_robot_app/main.py +0 -0
  82. {ws_bom_robot_app-0.0.81 → ws_bom_robot_app-0.0.83}/ws_bom_robot_app/util.py +0 -0
  83. {ws_bom_robot_app-0.0.81 → ws_bom_robot_app-0.0.83}/ws_bom_robot_app.egg-info/dependency_links.txt +0 -0
  84. {ws_bom_robot_app-0.0.81 → ws_bom_robot_app-0.0.83}/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.81
3
+ Version: 0.0.83
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
@@ -15,7 +15,7 @@ Requires-Dist: apscheduler==3.11.0
15
15
  Requires-Dist: aiofiles==24.1.0
16
16
  Requires-Dist: pydantic==2.11.7
17
17
  Requires-Dist: pydantic-settings==2.10.1
18
- Requires-Dist: fastapi[standard]==0.115.14
18
+ Requires-Dist: fastapi[standard]==0.116.1
19
19
  Requires-Dist: chevron==0.14.0
20
20
  Requires-Dist: langchain==0.3.26
21
21
  Requires-Dist: langchain-community==0.3.26
@@ -34,9 +34,9 @@ Requires-Dist: fastembed==0.7.1
34
34
  Requires-Dist: langchain-qdrant==0.2.0
35
35
  Requires-Dist: qdrant-client==1.15.0
36
36
  Requires-Dist: lark==1.2.2
37
- Requires-Dist: unstructured==0.16.21
37
+ Requires-Dist: unstructured==0.18.11
38
38
  Requires-Dist: unstructured[image]
39
- Requires-Dist: unstructured-ingest==0.5.4
39
+ Requires-Dist: unstructured-ingest==1.2.6
40
40
  Requires-Dist: unstructured-ingest[azure]
41
41
  Requires-Dist: unstructured-ingest[confluence]
42
42
  Requires-Dist: unstructured-ingest[dropbox]
@@ -115,7 +115,7 @@ GOOGLE_APPLICATION_CREDENTIALS="./.data/secrets/google-credentials.json"
115
115
 
116
116
  ```bash
117
117
  fastapi dev --port 6001
118
- #uvicorn main:app --app-dir ./ws_bom_robot_app --reload --host 0.0.0.0 --port 6001
118
+ #uvicorn main:app --app-dir ./ws_bom_robot_app --reload --reload-dir ws_bom_robot_app --host 0.0.0.0 --port 6001
119
119
  ```
120
120
 
121
121
  - production
@@ -145,6 +145,8 @@ dockerize base image
145
145
 
146
146
  ```pwsh
147
147
  <# cpu #>
148
+ #docker build -f Dockerfile-robot-base-cpu -t ws-bom-robot-base:cpu .
149
+ #docker tag ws-bom-robot-base:cpu ghcr.io/websolutespa/ws-bom-robot-base:cpu
148
150
  docker build -f Dockerfile-robot-base-cpu -t ghcr.io/websolutespa/ws-bom-robot-base:cpu .
149
151
  docker push ghcr.io/websolutespa/ws-bom-robot-base:cpu
150
152
  <# gpu #>
@@ -152,17 +154,25 @@ docker build -f Dockerfile-robot-base-gpu -t ghcr.io/websolutespa/ws-bom-robot-b
152
154
  docker push ghcr.io/websolutespa/ws-bom-robot-base:gpu
153
155
  ```
154
156
 
155
- dockerize app
157
+ dockerize app (from src)
156
158
 
157
159
  ```pwsh
158
160
  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
161
+ docker run --rm -d --name ws-bom-robot-app --env-file .env -p 6001:6001 ws-bom-robot-app
162
+ ```
163
+
164
+ dockerize app (from latest)
165
+
166
+ ```pwsh
167
+ docker build -f Dockerfile-pkg -t ws-bom-robot-app-pkg .
168
+ docker run --rm -d --name ws-bom-robot-app-pkg --env-file .env -p 6001:6001 ws-bom-robot-app-pkg
160
169
  ```
161
170
 
162
171
  docker run mounted to src (dev mode)
163
172
 
164
173
  ```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
174
+ docker run --rm -d --env-file .env -v "$(pwd)/.data:/app/.data" -p 6001:6001 ws-bom-robot-app fastapi dev ./ws_bom_robot_app/main.py --host 0.0.0.0 --port 6001
175
+ docker run --rm -d --env-file .env -v "$(pwd)/.data:/app/.data" -p 6001:6001 ws-bom-robot-app uvicorn ws_bom_robot_app.main:app --reload --host 0.0.0.0 --port 6001
166
176
  ```
167
177
 
168
178
  ---
@@ -288,7 +298,7 @@ prospector ./ws_bom_robot_app -t pyroma
288
298
  # pyclean --verbose .
289
299
  pytest --cov=ws_bom_robot_app --log-cli-level=info
290
300
  # directory
291
- # pytest --cov=ws_bom_robot_app --log-cli-level=info ./tests/app/llm/vector_store/db
301
+ # pytest --cov=ws_bom_robot_app.llm.vector_store --log-cli-level=info ./tests/app/llm/vector_store
292
302
  ```
293
303
 
294
304
  #### 🐞 start debugger
@@ -49,7 +49,7 @@ GOOGLE_APPLICATION_CREDENTIALS="./.data/secrets/google-credentials.json"
49
49
 
50
50
  ```bash
51
51
  fastapi dev --port 6001
52
- #uvicorn main:app --app-dir ./ws_bom_robot_app --reload --host 0.0.0.0 --port 6001
52
+ #uvicorn main:app --app-dir ./ws_bom_robot_app --reload --reload-dir ws_bom_robot_app --host 0.0.0.0 --port 6001
53
53
  ```
54
54
 
55
55
  - production
@@ -79,6 +79,8 @@ dockerize base image
79
79
 
80
80
  ```pwsh
81
81
  <# cpu #>
82
+ #docker build -f Dockerfile-robot-base-cpu -t ws-bom-robot-base:cpu .
83
+ #docker tag ws-bom-robot-base:cpu ghcr.io/websolutespa/ws-bom-robot-base:cpu
82
84
  docker build -f Dockerfile-robot-base-cpu -t ghcr.io/websolutespa/ws-bom-robot-base:cpu .
83
85
  docker push ghcr.io/websolutespa/ws-bom-robot-base:cpu
84
86
  <# gpu #>
@@ -86,17 +88,25 @@ docker build -f Dockerfile-robot-base-gpu -t ghcr.io/websolutespa/ws-bom-robot-b
86
88
  docker push ghcr.io/websolutespa/ws-bom-robot-base:gpu
87
89
  ```
88
90
 
89
- dockerize app
91
+ dockerize app (from src)
90
92
 
91
93
  ```pwsh
92
94
  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
95
+ docker run --rm -d --name ws-bom-robot-app --env-file .env -p 6001:6001 ws-bom-robot-app
96
+ ```
97
+
98
+ dockerize app (from latest)
99
+
100
+ ```pwsh
101
+ docker build -f Dockerfile-pkg -t ws-bom-robot-app-pkg .
102
+ docker run --rm -d --name ws-bom-robot-app-pkg --env-file .env -p 6001:6001 ws-bom-robot-app-pkg
94
103
  ```
95
104
 
96
105
  docker run mounted to src (dev mode)
97
106
 
98
107
  ```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
108
+ docker run --rm -d --env-file .env -v "$(pwd)/.data:/app/.data" -p 6001:6001 ws-bom-robot-app fastapi dev ./ws_bom_robot_app/main.py --host 0.0.0.0 --port 6001
109
+ docker run --rm -d --env-file .env -v "$(pwd)/.data:/app/.data" -p 6001:6001 ws-bom-robot-app uvicorn ws_bom_robot_app.main:app --reload --host 0.0.0.0 --port 6001
100
110
  ```
101
111
 
102
112
  ---
@@ -222,7 +232,7 @@ prospector ./ws_bom_robot_app -t pyroma
222
232
  # pyclean --verbose .
223
233
  pytest --cov=ws_bom_robot_app --log-cli-level=info
224
234
  # directory
225
- # pytest --cov=ws_bom_robot_app --log-cli-level=info ./tests/app/llm/vector_store/db
235
+ # pytest --cov=ws_bom_robot_app.llm.vector_store --log-cli-level=info ./tests/app/llm/vector_store
226
236
  ```
227
237
 
228
238
  #### 🐞 start debugger
@@ -4,7 +4,7 @@ apscheduler==3.11.0
4
4
  aiofiles==24.1.0
5
5
  pydantic==2.11.7
6
6
  pydantic-settings==2.10.1
7
- fastapi[standard]==0.115.14
7
+ fastapi[standard]==0.116.1
8
8
  chevron==0.14.0
9
9
 
10
10
  #framework
@@ -29,9 +29,9 @@ qdrant-client==1.15.0
29
29
  lark==1.2.2 #self-query retriever
30
30
 
31
31
  #loaders
32
- unstructured==0.16.21
32
+ unstructured==0.18.11
33
33
  unstructured[image]
34
- unstructured-ingest==0.5.4
34
+ unstructured-ingest==1.2.6
35
35
  unstructured-ingest[azure]
36
36
  unstructured-ingest[confluence]
37
37
  unstructured-ingest[dropbox]
@@ -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.81",
7
+ version="0.0.83",
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",
@@ -16,9 +16,14 @@ class Settings(BaseSettings):
16
16
  robot_data_db_retention_days: float = 60
17
17
  robot_data_attachment_folder: str = 'attachment'
18
18
  robot_data_attachment_retention_days: float = 1
19
+ robot_ingest_max_threads: int = 1 # safe choice to 1, avoid potential process-related issues with Docker
19
20
  robot_loader_max_threads: int = 1
20
21
  robot_task_max_total_parallelism: int = 2 * (os.cpu_count() or 1)
21
22
  robot_task_retention_days: float = 1
23
+ robot_task_strategy: str = 'memory' # memory / db
24
+ robot_task_mp_enable: bool = True
25
+ robot_task_mp_method: str = 'spawn' # spawn / fork
26
+ robot_cron_strategy: str = 'memory' # memory / db
22
27
  robot_cms_host: str = ''
23
28
  robot_cms_auth: str = ''
24
29
  robot_cms_db_folder: str = 'llmVectorDb'
@@ -41,6 +46,7 @@ class Settings(BaseSettings):
41
46
  )
42
47
  def __init__(self, **kwargs):
43
48
  super().__init__(**kwargs)
49
+ # env
44
50
  os.environ["USER_AGENT"] = self.USER_AGENT
45
51
  os.environ["OPENAI_API_KEY"] = self.OPENAI_API_KEY
46
52
  os.environ["OLLAMA_API_URL"] = self.OLLAMA_API_URL
@@ -53,6 +59,10 @@ class Settings(BaseSettings):
53
59
  os.environ["WATSONX_APIKEY"] = self.WATSONX_APIKEY
54
60
  os.environ["WATSONX_PROJECTID"] = self.WATSONX_PROJECTID
55
61
  os.environ["NEBULY_API_URL"] = self.NEBULY_API_URL
62
+ # dir
63
+ os.makedirs(self.robot_data_folder, exist_ok=True)
64
+ for subfolder in [self.robot_data_db_folder, self.robot_data_attachment_folder, 'db']:
65
+ os.makedirs(os.path.join(self.robot_data_folder, subfolder), exist_ok=True)
56
66
 
57
67
  class RuntimeOptions(BaseModel):
58
68
  @staticmethod
@@ -1,3 +1,4 @@
1
+ import os
1
2
  from apscheduler.schedulers.background import BackgroundScheduler
2
3
  #from apscheduler.schedulers.asyncio import AsyncIOScheduler
3
4
  from apscheduler.jobstores.memory import MemoryJobStore
@@ -7,8 +8,7 @@ from apscheduler.triggers.interval import IntervalTrigger
7
8
  from apscheduler.triggers.date import DateTrigger
8
9
  from fastapi import APIRouter
9
10
  from datetime import datetime
10
- from ws_bom_robot_app.task_manager import task_manager
11
- from ws_bom_robot_app.llm.utils.cleanup import kb_cleanup_data_file, chat_cleanup_attachment
11
+ from ws_bom_robot_app.llm.utils.cleanup import kb_cleanup_data_file, chat_cleanup_attachment, task_cleanup_history
12
12
  from ws_bom_robot_app.util import _log
13
13
  from ws_bom_robot_app.config import config
14
14
 
@@ -22,8 +22,8 @@ class MemoryJobstoreStrategy(JobstoreStrategy):
22
22
  return {"default": MemoryJobStore()}
23
23
 
24
24
  class PersistentJobstoreStrategy(JobstoreStrategy):
25
- def get_jobstore(self, db_url: str = "sqlite:///.data/db/jobs.sqlite"):
26
- _log.info(f"Using persistent crob jobstore with database URL: {db_url}.")
25
+ def get_jobstore(self, db_url: str = f"sqlite:///{config.robot_data_folder}/db/jobs.sqlite"):
26
+ _log.info(f"Using persistent cron jobstore with database URL: {db_url}.")
27
27
  return {"default": SQLAlchemyJobStore(url=db_url)}
28
28
 
29
29
  class Job:
@@ -56,12 +56,12 @@ class Job:
56
56
 
57
57
  class CronManager:
58
58
  _list_default = [
59
- Job('cleanup-task',task_manager.cleanup_task, interval=5 * 60),
59
+ Job('cleanup-task-history',task_cleanup_history, interval=5 * 60),
60
60
  Job('cleanup-kb-data',kb_cleanup_data_file, interval=180 * 60),
61
61
  Job('cleanup-chat-attachment',chat_cleanup_attachment, interval=120 * 60),
62
62
  ]
63
63
  def __get_jobstore_strategy(self) -> JobstoreStrategy:
64
- if True or config.runtime_options().is_multi_process:
64
+ if config.robot_cron_strategy == 'memory':
65
65
  return MemoryJobstoreStrategy()
66
66
  return PersistentJobstoreStrategy()
67
67
  def __init__(self, strategy: JobstoreStrategy = None, enable_defaults: bool = True):
@@ -1,123 +1,123 @@
1
- import json, requests, re
2
- from typing import Any
3
- from abc import ABC, abstractmethod
4
- from langchain_core.prompts import ChatPromptTemplate
5
- from langchain_core.messages import AIMessage
6
- from langchain_core.runnables import RunnableSerializable
7
- from langchain_core.runnables import RunnableLambda
8
- from bs4 import BeautifulSoup
9
- from ws_bom_robot_app.llm.models.api import LlmRules
10
- from ws_bom_robot_app.llm.providers.llm_manager import LlmInterface
11
- from ws_bom_robot_app.llm.utils.agent import get_rules
12
-
13
- # SafeDict helper class
14
- class SafeDict(dict):
15
- def __missing__(self, key):
16
- return ''
17
-
18
- # Strategy Interface
19
- class AgentDescriptorStrategy(ABC):
20
- @abstractmethod
21
- def enrich_prompt(self, prompt: str, input: dict) -> str:
22
- pass
23
-
24
- @abstractmethod
25
- def rule_input(self, input: dict) -> str:
26
- pass
27
-
28
- # Concrete Strategy for Default Agent
29
- class DefaultAgentDescriptor(AgentDescriptorStrategy):
30
- def enrich_prompt(self, prompt: str, input: dict) -> str:
31
- # Default enrichment logic (could be minimal or no-op)
32
- return prompt.format_map(SafeDict(input))
33
-
34
- def rule_input(self, input: dict) -> str:
35
- return input.get('content', "")
36
-
37
- # Concrete Strategy for URL2Text Agent
38
- class URL2TextAgentDescriptor(AgentDescriptorStrategy):
39
- def enrich_prompt(self, prompt: str, input: dict) -> str:
40
- input["context"] = self._get_page_text(input)
41
- return prompt.format_map(SafeDict(input))
42
-
43
- def rule_input(self, input: dict) -> str:
44
- return input.get('context', "")
45
-
46
- def _get_page_text(self, input: dict) -> str:
47
- url = input.get("content", "")
48
- exclusions = input.get("exclude", {})
49
- response = requests.get(url)
50
- response.raise_for_status()
51
- soup = BeautifulSoup(response.content, 'html5lib')
52
- classes_to_exclude = exclusions.get("classes", [])
53
- ids_to_exclude = exclusions.get("ids", [])
54
- for class_name in classes_to_exclude:
55
- for element in soup.find_all(class_=class_name):
56
- element.extract()
57
- for id_name in ids_to_exclude:
58
- for element in soup.find_all(id=id_name):
59
- element.extract()
60
- for script in soup(["script", "noscript", "style", "head", "footer", "iframe"]):
61
- script.extract()
62
- return re.sub(' +', ' ', soup.get_text())
63
-
64
-
65
- class AgentDescriptor:
66
- # Dictionary to hold all agent strategies
67
- _list: dict[str,AgentDescriptorStrategy] = {
68
- "default": DefaultAgentDescriptor(),
69
- "url2text": URL2TextAgentDescriptor(),
70
- }
71
-
72
- # Functions to manage strategies
73
- @staticmethod
74
- def add_strategy(name: str, strategy: AgentDescriptorStrategy):
75
- """_summary_
76
- add a new strategy to the dictionary
77
- Args:
78
- name (str): name of the strategy, in lowercase
79
- strategy (AgentDescriptorStrategy): class implementing the strategy
80
- Examples:
81
- AgentDescriptor.add_strategy("custom_agent_descriptor", CustomAgentDescriptor())
82
- """
83
- AgentDescriptor._list[name.lower()] = strategy
84
-
85
- @staticmethod
86
- def get_strategy(name: str) -> AgentDescriptorStrategy:
87
- return AgentDescriptor._list.get(name.lower(), DefaultAgentDescriptor())
88
-
89
- def __init__(self, llm: LlmInterface, prompt: str, mode: str, rules: LlmRules = None):
90
- self.__prompt = prompt
91
- self.__llm = llm
92
- self.rules= rules
93
- self.strategy = self.get_strategy(mode) # Selects the strategy from the dictionary
94
-
95
- async def __create_prompt(self, input_dict: dict):
96
- input_data = json.loads(input_dict.get("input", {}))
97
- system = self.strategy.enrich_prompt(self.__prompt, input_data)
98
- if self.rules:
99
- rule_input = self.strategy.rule_input(input_data)
100
- rules_prompt = await get_rules(self.__llm.get_embeddings(), self.rules, rule_input)
101
- system += rules_prompt
102
- return ChatPromptTemplate.from_messages(
103
- [
104
- ("system", system),
105
- ("user", input_data.get("content", ""))
106
- ]
107
- )
108
-
109
- def __create_agent_descriptor(self, content) -> RunnableSerializable[Any, Any]:
110
- content = json.loads(content)
111
- agent = (
112
- {
113
- "input": lambda x: x["input"],
114
- }
115
- | RunnableLambda(self.__create_prompt)
116
- | self.__llm.get_llm()
117
- )
118
- return agent
119
-
120
- async def run_agent(self, content) -> Any:
121
- agent_descriptor = self.__create_agent_descriptor(content)
122
- response: AIMessage = await agent_descriptor.ainvoke({"input": content})
123
- return response
1
+ import json, requests, re
2
+ from typing import Any
3
+ from abc import ABC, abstractmethod
4
+ from langchain_core.prompts import ChatPromptTemplate
5
+ from langchain_core.messages import AIMessage
6
+ from langchain_core.runnables import RunnableSerializable
7
+ from langchain_core.runnables import RunnableLambda
8
+ from bs4 import BeautifulSoup
9
+ from ws_bom_robot_app.llm.models.api import LlmRules
10
+ from ws_bom_robot_app.llm.providers.llm_manager import LlmInterface
11
+ from ws_bom_robot_app.llm.utils.agent import get_rules
12
+
13
+ # SafeDict helper class
14
+ class SafeDict(dict):
15
+ def __missing__(self, key):
16
+ return ''
17
+
18
+ # Strategy Interface
19
+ class AgentDescriptorStrategy(ABC):
20
+ @abstractmethod
21
+ def enrich_prompt(self, prompt: str, input: dict) -> str:
22
+ pass
23
+
24
+ @abstractmethod
25
+ def rule_input(self, input: dict) -> str:
26
+ pass
27
+
28
+ # Concrete Strategy for Default Agent
29
+ class DefaultAgentDescriptor(AgentDescriptorStrategy):
30
+ def enrich_prompt(self, prompt: str, input: dict) -> str:
31
+ # Default enrichment logic (could be minimal or no-op)
32
+ return prompt.format_map(SafeDict(input))
33
+
34
+ def rule_input(self, input: dict) -> str:
35
+ return input.get('content', "")
36
+
37
+ # Concrete Strategy for URL2Text Agent
38
+ class URL2TextAgentDescriptor(AgentDescriptorStrategy):
39
+ def enrich_prompt(self, prompt: str, input: dict) -> str:
40
+ input["context"] = self._get_page_text(input)
41
+ return prompt.format_map(SafeDict(input))
42
+
43
+ def rule_input(self, input: dict) -> str:
44
+ return input.get('context', "")
45
+
46
+ def _get_page_text(self, input: dict) -> str:
47
+ url = input.get("content", "")
48
+ exclusions = input.get("exclude", {})
49
+ response = requests.get(url)
50
+ response.raise_for_status()
51
+ soup = BeautifulSoup(response.content, 'html5lib')
52
+ classes_to_exclude = exclusions.get("classes", [])
53
+ ids_to_exclude = exclusions.get("ids", [])
54
+ for class_name in classes_to_exclude:
55
+ for element in soup.find_all(class_=class_name):
56
+ element.extract()
57
+ for id_name in ids_to_exclude:
58
+ for element in soup.find_all(id=id_name):
59
+ element.extract()
60
+ for script in soup(["script", "noscript", "style", "head", "footer", "iframe"]):
61
+ script.extract()
62
+ return re.sub(' +', ' ', soup.get_text())
63
+
64
+
65
+ class AgentDescriptor:
66
+ # Dictionary to hold all agent strategies
67
+ _list: dict[str,AgentDescriptorStrategy] = {
68
+ "default": DefaultAgentDescriptor(),
69
+ "url2text": URL2TextAgentDescriptor(),
70
+ }
71
+
72
+ # Functions to manage strategies
73
+ @staticmethod
74
+ def add_strategy(name: str, strategy: AgentDescriptorStrategy):
75
+ """_summary_
76
+ add a new strategy to the dictionary
77
+ Args:
78
+ name (str): name of the strategy, in lowercase
79
+ strategy (AgentDescriptorStrategy): class implementing the strategy
80
+ Examples:
81
+ AgentDescriptor.add_strategy("custom_agent_descriptor", CustomAgentDescriptor())
82
+ """
83
+ AgentDescriptor._list[name.lower()] = strategy
84
+
85
+ @staticmethod
86
+ def get_strategy(name: str) -> AgentDescriptorStrategy:
87
+ return AgentDescriptor._list.get(name.lower(), DefaultAgentDescriptor())
88
+
89
+ def __init__(self, llm: LlmInterface, prompt: str, mode: str, rules: LlmRules = None):
90
+ self.__prompt = prompt
91
+ self.__llm = llm
92
+ self.rules= rules
93
+ self.strategy = self.get_strategy(mode) # Selects the strategy from the dictionary
94
+
95
+ async def __create_prompt(self, input_dict: dict):
96
+ input_data = json.loads(input_dict.get("input", {}))
97
+ system = self.strategy.enrich_prompt(self.__prompt, input_data)
98
+ if self.rules:
99
+ rule_input = self.strategy.rule_input(input_data)
100
+ rules_prompt = await get_rules(self.__llm.get_embeddings(), self.rules, rule_input)
101
+ system += rules_prompt
102
+ return ChatPromptTemplate.from_messages(
103
+ [
104
+ ("system", system),
105
+ ("user", input_data.get("content", ""))
106
+ ]
107
+ )
108
+
109
+ def __create_agent_descriptor(self, content) -> RunnableSerializable[Any, Any]:
110
+ content = json.loads(content)
111
+ agent = (
112
+ {
113
+ "input": lambda x: x["input"],
114
+ }
115
+ | RunnableLambda(self.__create_prompt)
116
+ | self.__llm.get_llm()
117
+ )
118
+ return agent
119
+
120
+ async def run_agent(self, content) -> Any:
121
+ agent_descriptor = self.__create_agent_descriptor(content)
122
+ response: AIMessage = await agent_descriptor.ainvoke({"input": content})
123
+ return response