ws-bom-robot-app 0.0.67__tar.gz → 0.0.69__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.67/ws_bom_robot_app.egg-info → ws_bom_robot_app-0.0.69}/PKG-INFO +11 -5
- {ws_bom_robot_app-0.0.67 → ws_bom_robot_app-0.0.69}/README.md +10 -4
- {ws_bom_robot_app-0.0.67 → ws_bom_robot_app-0.0.69}/setup.py +1 -1
- {ws_bom_robot_app-0.0.67 → ws_bom_robot_app-0.0.69}/ws_bom_robot_app/config.py +7 -7
- {ws_bom_robot_app-0.0.67 → ws_bom_robot_app-0.0.69}/ws_bom_robot_app/llm/agent_description.py +123 -123
- {ws_bom_robot_app-0.0.67 → ws_bom_robot_app-0.0.69}/ws_bom_robot_app/llm/agent_handler.py +177 -177
- {ws_bom_robot_app-0.0.67 → ws_bom_robot_app-0.0.69}/ws_bom_robot_app/llm/agent_lcel.py +45 -45
- {ws_bom_robot_app-0.0.67 → ws_bom_robot_app-0.0.69}/ws_bom_robot_app/llm/defaut_prompt.py +15 -15
- {ws_bom_robot_app-0.0.67 → ws_bom_robot_app-0.0.69}/ws_bom_robot_app/llm/feedbacks/feedback_manager.py +66 -66
- {ws_bom_robot_app-0.0.67 → ws_bom_robot_app-0.0.69}/ws_bom_robot_app/llm/main.py +138 -138
- {ws_bom_robot_app-0.0.67 → ws_bom_robot_app-0.0.69}/ws_bom_robot_app/llm/models/feedback.py +30 -30
- {ws_bom_robot_app-0.0.67 → ws_bom_robot_app-0.0.69}/ws_bom_robot_app/llm/nebuly_handler.py +181 -181
- {ws_bom_robot_app-0.0.67 → ws_bom_robot_app-0.0.69}/ws_bom_robot_app/llm/providers/llm_manager.py +3 -3
- {ws_bom_robot_app-0.0.67 → ws_bom_robot_app-0.0.69}/ws_bom_robot_app/llm/settings.py +4 -4
- {ws_bom_robot_app-0.0.67 → ws_bom_robot_app-0.0.69}/ws_bom_robot_app/llm/tools/tool_builder.py +65 -65
- {ws_bom_robot_app-0.0.67 → ws_bom_robot_app-0.0.69}/ws_bom_robot_app/llm/tools/tool_manager.py +330 -317
- {ws_bom_robot_app-0.0.67 → ws_bom_robot_app-0.0.69}/ws_bom_robot_app/llm/tools/utils.py +41 -41
- {ws_bom_robot_app-0.0.67 → ws_bom_robot_app-0.0.69}/ws_bom_robot_app/llm/utils/agent.py +34 -34
- ws_bom_robot_app-0.0.69/ws_bom_robot_app/llm/utils/cms.py +109 -0
- {ws_bom_robot_app-0.0.67 → ws_bom_robot_app-0.0.69}/ws_bom_robot_app/llm/utils/download.py +79 -79
- {ws_bom_robot_app-0.0.67 → ws_bom_robot_app-0.0.69}/ws_bom_robot_app/llm/utils/print.py +29 -29
- {ws_bom_robot_app-0.0.67 → ws_bom_robot_app-0.0.69}/ws_bom_robot_app/llm/vector_store/generator.py +137 -137
- {ws_bom_robot_app-0.0.67 → ws_bom_robot_app-0.0.69}/ws_bom_robot_app/llm/vector_store/integration/manager.py +2 -2
- ws_bom_robot_app-0.0.69/ws_bom_robot_app/llm/vector_store/integration/thron.py +123 -0
- {ws_bom_robot_app-0.0.67 → ws_bom_robot_app-0.0.69}/ws_bom_robot_app/llm/vector_store/loader/json_loader.py +25 -25
- {ws_bom_robot_app-0.0.67 → ws_bom_robot_app-0.0.69/ws_bom_robot_app.egg-info}/PKG-INFO +11 -5
- {ws_bom_robot_app-0.0.67 → ws_bom_robot_app-0.0.69}/ws_bom_robot_app.egg-info/SOURCES.txt +1 -0
- ws_bom_robot_app-0.0.67/ws_bom_robot_app/llm/utils/cms.py +0 -77
- {ws_bom_robot_app-0.0.67 → ws_bom_robot_app-0.0.69}/MANIFEST.in +0 -0
- {ws_bom_robot_app-0.0.67 → ws_bom_robot_app-0.0.69}/pyproject.toml +0 -0
- {ws_bom_robot_app-0.0.67 → ws_bom_robot_app-0.0.69}/requirements.txt +0 -0
- {ws_bom_robot_app-0.0.67 → ws_bom_robot_app-0.0.69}/setup.cfg +0 -0
- {ws_bom_robot_app-0.0.67 → ws_bom_robot_app-0.0.69}/ws_bom_robot_app/__init__.py +0 -0
- {ws_bom_robot_app-0.0.67 → ws_bom_robot_app-0.0.69}/ws_bom_robot_app/auth.py +0 -0
- {ws_bom_robot_app-0.0.67 → ws_bom_robot_app-0.0.69}/ws_bom_robot_app/cron_manager.py +0 -0
- {ws_bom_robot_app-0.0.67 → ws_bom_robot_app-0.0.69}/ws_bom_robot_app/llm/__init__.py +0 -0
- {ws_bom_robot_app-0.0.67 → ws_bom_robot_app-0.0.69}/ws_bom_robot_app/llm/agent_context.py +0 -0
- {ws_bom_robot_app-0.0.67 → ws_bom_robot_app-0.0.69}/ws_bom_robot_app/llm/api.py +0 -0
- {ws_bom_robot_app-0.0.67 → ws_bom_robot_app-0.0.69}/ws_bom_robot_app/llm/feedbacks/__init__.py +0 -0
- {ws_bom_robot_app-0.0.67 → ws_bom_robot_app-0.0.69}/ws_bom_robot_app/llm/models/__init__.py +0 -0
- {ws_bom_robot_app-0.0.67 → ws_bom_robot_app-0.0.69}/ws_bom_robot_app/llm/models/api.py +0 -0
- {ws_bom_robot_app-0.0.67 → ws_bom_robot_app-0.0.69}/ws_bom_robot_app/llm/models/base.py +0 -0
- {ws_bom_robot_app-0.0.67 → ws_bom_robot_app-0.0.69}/ws_bom_robot_app/llm/models/kb.py +0 -0
- {ws_bom_robot_app-0.0.67 → ws_bom_robot_app-0.0.69}/ws_bom_robot_app/llm/providers/__init__.py +0 -0
- {ws_bom_robot_app-0.0.67 → ws_bom_robot_app-0.0.69}/ws_bom_robot_app/llm/tools/__init__.py +0 -0
- {ws_bom_robot_app-0.0.67 → ws_bom_robot_app-0.0.69}/ws_bom_robot_app/llm/tools/models/__init__.py +0 -0
- {ws_bom_robot_app-0.0.67 → ws_bom_robot_app-0.0.69}/ws_bom_robot_app/llm/tools/models/main.py +0 -0
- {ws_bom_robot_app-0.0.67 → ws_bom_robot_app-0.0.69}/ws_bom_robot_app/llm/utils/__init__.py +0 -0
- {ws_bom_robot_app-0.0.67 → ws_bom_robot_app-0.0.69}/ws_bom_robot_app/llm/utils/chunker.py +0 -0
- {ws_bom_robot_app-0.0.67 → ws_bom_robot_app-0.0.69}/ws_bom_robot_app/llm/utils/kb.py +0 -0
- {ws_bom_robot_app-0.0.67 → ws_bom_robot_app-0.0.69}/ws_bom_robot_app/llm/utils/secrets.py +0 -0
- {ws_bom_robot_app-0.0.67 → ws_bom_robot_app-0.0.69}/ws_bom_robot_app/llm/utils/webhooks.py +0 -0
- {ws_bom_robot_app-0.0.67 → ws_bom_robot_app-0.0.69}/ws_bom_robot_app/llm/vector_store/__init__.py +0 -0
- {ws_bom_robot_app-0.0.67 → ws_bom_robot_app-0.0.69}/ws_bom_robot_app/llm/vector_store/db/__init__.py +0 -0
- {ws_bom_robot_app-0.0.67 → ws_bom_robot_app-0.0.69}/ws_bom_robot_app/llm/vector_store/db/base.py +0 -0
- {ws_bom_robot_app-0.0.67 → ws_bom_robot_app-0.0.69}/ws_bom_robot_app/llm/vector_store/db/chroma.py +0 -0
- {ws_bom_robot_app-0.0.67 → ws_bom_robot_app-0.0.69}/ws_bom_robot_app/llm/vector_store/db/faiss.py +0 -0
- {ws_bom_robot_app-0.0.67 → ws_bom_robot_app-0.0.69}/ws_bom_robot_app/llm/vector_store/db/manager.py +0 -0
- {ws_bom_robot_app-0.0.67 → ws_bom_robot_app-0.0.69}/ws_bom_robot_app/llm/vector_store/db/qdrant.py +0 -0
- {ws_bom_robot_app-0.0.67 → ws_bom_robot_app-0.0.69}/ws_bom_robot_app/llm/vector_store/integration/__init__.py +0 -0
- {ws_bom_robot_app-0.0.67 → ws_bom_robot_app-0.0.69}/ws_bom_robot_app/llm/vector_store/integration/azure.py +0 -0
- {ws_bom_robot_app-0.0.67 → ws_bom_robot_app-0.0.69}/ws_bom_robot_app/llm/vector_store/integration/base.py +0 -0
- {ws_bom_robot_app-0.0.67 → ws_bom_robot_app-0.0.69}/ws_bom_robot_app/llm/vector_store/integration/confluence.py +0 -0
- {ws_bom_robot_app-0.0.67 → ws_bom_robot_app-0.0.69}/ws_bom_robot_app/llm/vector_store/integration/dropbox.py +0 -0
- {ws_bom_robot_app-0.0.67 → ws_bom_robot_app-0.0.69}/ws_bom_robot_app/llm/vector_store/integration/gcs.py +0 -0
- {ws_bom_robot_app-0.0.67 → ws_bom_robot_app-0.0.69}/ws_bom_robot_app/llm/vector_store/integration/github.py +0 -0
- {ws_bom_robot_app-0.0.67 → ws_bom_robot_app-0.0.69}/ws_bom_robot_app/llm/vector_store/integration/googledrive.py +0 -0
- {ws_bom_robot_app-0.0.67 → ws_bom_robot_app-0.0.69}/ws_bom_robot_app/llm/vector_store/integration/jira.py +0 -0
- {ws_bom_robot_app-0.0.67 → ws_bom_robot_app-0.0.69}/ws_bom_robot_app/llm/vector_store/integration/s3.py +0 -0
- {ws_bom_robot_app-0.0.67 → ws_bom_robot_app-0.0.69}/ws_bom_robot_app/llm/vector_store/integration/sftp.py +0 -0
- {ws_bom_robot_app-0.0.67 → ws_bom_robot_app-0.0.69}/ws_bom_robot_app/llm/vector_store/integration/sharepoint.py +0 -0
- {ws_bom_robot_app-0.0.67 → ws_bom_robot_app-0.0.69}/ws_bom_robot_app/llm/vector_store/integration/sitemap.py +0 -0
- {ws_bom_robot_app-0.0.67 → ws_bom_robot_app-0.0.69}/ws_bom_robot_app/llm/vector_store/integration/slack.py +0 -0
- {ws_bom_robot_app-0.0.67 → ws_bom_robot_app-0.0.69}/ws_bom_robot_app/llm/vector_store/loader/__init__.py +0 -0
- {ws_bom_robot_app-0.0.67 → ws_bom_robot_app-0.0.69}/ws_bom_robot_app/llm/vector_store/loader/base.py +0 -0
- {ws_bom_robot_app-0.0.67 → ws_bom_robot_app-0.0.69}/ws_bom_robot_app/llm/vector_store/loader/docling.py +0 -0
- {ws_bom_robot_app-0.0.67 → ws_bom_robot_app-0.0.69}/ws_bom_robot_app/main.py +0 -0
- {ws_bom_robot_app-0.0.67 → ws_bom_robot_app-0.0.69}/ws_bom_robot_app/task_manager.py +0 -0
- {ws_bom_robot_app-0.0.67 → ws_bom_robot_app-0.0.69}/ws_bom_robot_app/util.py +0 -0
- {ws_bom_robot_app-0.0.67 → ws_bom_robot_app-0.0.69}/ws_bom_robot_app.egg-info/dependency_links.txt +0 -0
- {ws_bom_robot_app-0.0.67 → ws_bom_robot_app-0.0.69}/ws_bom_robot_app.egg-info/requires.txt +0 -0
- {ws_bom_robot_app-0.0.67 → ws_bom_robot_app-0.0.69}/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.69
|
|
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
|
|
@@ -244,7 +244,7 @@ pytest --cov=ws_bom_robot_app --log-cli-level=info
|
|
|
244
244
|
launch debugger
|
|
245
245
|
|
|
246
246
|
```pwsh
|
|
247
|
-
streamlit run debugger.py --server.port
|
|
247
|
+
streamlit run debugger.py --server.port 8051
|
|
248
248
|
```
|
|
249
249
|
|
|
250
250
|
dockerize base image
|
|
@@ -258,11 +258,17 @@ docker build -f Dockerfile-robot-base-gpu -t ghcr.io/websolutespa/ws-bom-robot-b
|
|
|
258
258
|
docker push ghcr.io/websolutespa/ws-bom-robot-base:gpu
|
|
259
259
|
```
|
|
260
260
|
|
|
261
|
-
dockerize app
|
|
261
|
+
dockerize app
|
|
262
262
|
|
|
263
263
|
```pwsh
|
|
264
|
-
docker build -f Dockerfile
|
|
265
|
-
docker run --name ws-bom-robot-app
|
|
264
|
+
docker build -f Dockerfile -t ws-bom-robot-app .
|
|
265
|
+
docker run --rm --name ws-bom-robot-app -d -p 6001:6001 ws-bom-robot-app
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
docker run mounted to src
|
|
269
|
+
|
|
270
|
+
```pwsh
|
|
271
|
+
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
|
|
266
272
|
```
|
|
267
273
|
|
|
268
274
|
### ✈️ publish
|
|
@@ -179,7 +179,7 @@ pytest --cov=ws_bom_robot_app --log-cli-level=info
|
|
|
179
179
|
launch debugger
|
|
180
180
|
|
|
181
181
|
```pwsh
|
|
182
|
-
streamlit run debugger.py --server.port
|
|
182
|
+
streamlit run debugger.py --server.port 8051
|
|
183
183
|
```
|
|
184
184
|
|
|
185
185
|
dockerize base image
|
|
@@ -193,11 +193,17 @@ docker build -f Dockerfile-robot-base-gpu -t ghcr.io/websolutespa/ws-bom-robot-b
|
|
|
193
193
|
docker push ghcr.io/websolutespa/ws-bom-robot-base:gpu
|
|
194
194
|
```
|
|
195
195
|
|
|
196
|
-
dockerize app
|
|
196
|
+
dockerize app
|
|
197
197
|
|
|
198
198
|
```pwsh
|
|
199
|
-
docker build -f Dockerfile
|
|
200
|
-
docker run --name ws-bom-robot-app
|
|
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
|
|
201
207
|
```
|
|
202
208
|
|
|
203
209
|
### ✈️ publish
|
|
@@ -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.69",
|
|
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",
|
|
@@ -54,7 +54,7 @@ class Settings(BaseSettings):
|
|
|
54
54
|
|
|
55
55
|
class RuntimeOptions(BaseModel):
|
|
56
56
|
@staticmethod
|
|
57
|
-
def
|
|
57
|
+
def _get_sys_arg(arg: str, default: int) -> int:
|
|
58
58
|
"""
|
|
59
59
|
Returns the number of worker processes to use for the application.
|
|
60
60
|
|
|
@@ -72,18 +72,18 @@ class Settings(BaseSettings):
|
|
|
72
72
|
"""
|
|
73
73
|
import sys
|
|
74
74
|
try:
|
|
75
|
-
for i,
|
|
76
|
-
if
|
|
75
|
+
for i, argv in enumerate(sys.argv):
|
|
76
|
+
if argv == f"--{arg}" and i + 1 < len(sys.argv):
|
|
77
77
|
return int(sys.argv[i + 1])
|
|
78
78
|
except (ValueError, IndexError):
|
|
79
79
|
pass
|
|
80
|
-
return
|
|
80
|
+
return default
|
|
81
81
|
debug: bool
|
|
82
|
+
tcp_port: int = _get_sys_arg("port", 6001)
|
|
82
83
|
loader_show_progress: bool
|
|
83
84
|
loader_silent_errors: bool
|
|
84
|
-
number_of_workers: int =
|
|
85
|
-
is_multi_process: bool =
|
|
86
|
-
|
|
85
|
+
number_of_workers: int = _get_sys_arg("workers", 1)
|
|
86
|
+
is_multi_process: bool = _get_sys_arg("workers", 1) > 1
|
|
87
87
|
|
|
88
88
|
def runtime_options(self) -> RuntimeOptions:
|
|
89
89
|
"""_summary_
|
{ws_bom_robot_app-0.0.67 → ws_bom_robot_app-0.0.69}/ws_bom_robot_app/llm/agent_description.py
RENAMED
|
@@ -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
|