ws-bom-robot-app 0.0.63__py3-none-any.whl → 0.0.65__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -27,6 +27,7 @@ class Settings(BaseSettings):
27
27
  OLLAMA_API_URL: str = 'http://localhost:11434'
28
28
  GROQ_API_KEY: str = ''
29
29
  GOOGLE_API_KEY: str = ''
30
+ WATSONX_APIKEY: str = '' # used for ibm watsonx
30
31
  NEBULY_API_URL: str =''
31
32
  GOOGLE_APPLICATION_CREDENTIALS: str = '' # path to google credentials iam file, e.d. ./.secrets/google-credentials.json
32
33
  model_config = ConfigDict(
@@ -44,6 +45,7 @@ class Settings(BaseSettings):
44
45
  os.environ["GROQ_API_KEY"] = self.GROQ_API_KEY
45
46
  os.environ["GOOGLE_API_KEY"] = self.GOOGLE_API_KEY
46
47
  os.environ["GOOGLE_APPLICATION_CREDENTIALS"] = self.GOOGLE_APPLICATION_CREDENTIALS
48
+ os.environ["WATSONX_APIKEY"] = self.WATSONX_APIKEY
47
49
  os.environ["NEBULY_API_URL"] = self.NEBULY_API_URL
48
50
 
49
51
  class RuntimeOptions(BaseModel):
@@ -99,11 +99,15 @@ async def __stream(rq: StreamRequest, ctx: Request, queue: Queue,formatted: bool
99
99
  rules=rq.rules
100
100
  )
101
101
  if rq.secrets.get("nebulyApiKey","") != "":
102
+ user_id = None
103
+ if rq.system_context.user.id:
104
+ user_id = rq.system_context.user.id
102
105
  nebuly_callback = NebulyHandler(
103
106
  llm_model=__llm.config.model,
104
107
  threadId=rq.thread_id,
105
108
  url=config.NEBULY_API_URL,
106
109
  api_key=rq.secrets.get("nebulyApiKey", None),
110
+ user_id=user_id,
107
111
  )
108
112
  callbacks.append(nebuly_callback)
109
113
 
@@ -5,10 +5,9 @@ from langchain_core.callbacks.base import AsyncCallbackHandler
5
5
  import ws_bom_robot_app.llm.settings as settings
6
6
  from langchain_core.messages import BaseMessage, HumanMessage, AIMessage
7
7
  from langchain_core.outputs import ChatGenerationChunk, GenerationChunk
8
- from uuid import UUID
9
8
 
10
9
  class NebulyHandler(AsyncCallbackHandler):
11
- def __init__(self, llm_model: str | None, threadId: str = None, url: str = None, api_key: str = None):
10
+ def __init__(self, llm_model: str | None, threadId: str = None, url: str = None, api_key: str = None, user_id: str | None = None):
12
11
  super().__init__()
13
12
  self.__started: bool = False
14
13
  self.__url: str = url
@@ -19,7 +18,7 @@ class NebulyHandler(AsyncCallbackHandler):
19
18
  output="",
20
19
  time_start="",
21
20
  time_end="",
22
- end_user=threadId,
21
+ end_user= user_id if user_id and user_id != "" else threadId,
23
22
  tags={"model": llm_model},
24
23
  )
25
24
  self.llm_trace = NebulyLLMTrace(
@@ -37,6 +37,31 @@ class LlmInterface:
37
37
  from langchain.agents.output_parsers.openai_tools import OpenAIToolsAgentOutputParser
38
38
  return OpenAIToolsAgentOutputParser()
39
39
 
40
+ class Anthropic(LlmInterface):
41
+ def get_llm(self):
42
+ from langchain_anthropic import ChatAnthropic
43
+ return ChatAnthropic(
44
+ api_key=self.config.api_key or os.getenv("ANTHROPIC_API_KEY"),
45
+ model=self.config.model,
46
+ temperature=self.config.temperature,
47
+ streaming=True,
48
+ stream_usage=True
49
+ )
50
+
51
+ """
52
+ def get_embeddings(self):
53
+ from langchain_voyageai import VoyageAIEmbeddings
54
+ return VoyageAIEmbeddings(
55
+ api_key=self.config.embedding_api_key, #voyage api key
56
+ model="voyage-3")
57
+ """
58
+
59
+ def get_models(self):
60
+ import anthropic
61
+ client = anthropic.Client(api_key=self.config.api_key or os.getenv("ANTHROPIC_API_KEY"))
62
+ response = client.models.list()
63
+ return response.data
64
+
40
65
  class OpenAI(LlmInterface):
41
66
  def __init__(self, config: LlmConfig):
42
67
  super().__init__(config)
@@ -133,31 +158,6 @@ class Gvertex(LlmInterface):
133
158
  {"id":"gemini-1.5-pro-002"}
134
159
  ]
135
160
 
136
- class Anthropic(LlmInterface):
137
- def get_llm(self):
138
- from langchain_anthropic import ChatAnthropic
139
- return ChatAnthropic(
140
- api_key=self.config.api_key or os.getenv("ANTHROPIC_API_KEY"),
141
- model=self.config.model,
142
- temperature=self.config.temperature,
143
- streaming=True,
144
- stream_usage=True
145
- )
146
-
147
- """
148
- def get_embeddings(self):
149
- from langchain_voyageai import VoyageAIEmbeddings
150
- return VoyageAIEmbeddings(
151
- api_key=self.config.embedding_api_key, #voyage api key
152
- model="voyage-3")
153
- """
154
-
155
- def get_models(self):
156
- import anthropic
157
- client = anthropic.Client(api_key=self.config.api_key or os.getenv("ANTHROPIC_API_KEY"))
158
- response = client.models.list()
159
- return response.data
160
-
161
161
  class Groq(LlmInterface):
162
162
  def get_llm(self):
163
163
  from langchain_groq import ChatGroq
@@ -179,10 +179,63 @@ class Groq(LlmInterface):
179
179
  response = requests.get(url, headers=headers)
180
180
  return response.json().get("data", [])
181
181
 
182
+ class IBM(LlmInterface):
183
+ def __init__(self, config: LlmConfig):
184
+ super().__init__(config)
185
+ self.__apy_key = self.config.api_key or os.getenv("WATSONX_APIKEY")
186
+ self.__base_url = self.config.api_url or "https://us-south.ml.cloud.ibm.com"
187
+ def get_llm(self):
188
+ from langchain_ibm import ChatWatsonx
189
+ return ChatWatsonx(
190
+ model_id=self.config.model,
191
+ url=self.__base_url,
192
+ apikey=self.__apy_key
193
+ )
194
+ def get_models(self):
195
+ import requests
196
+ from datetime import date
197
+ try:
198
+ # https://cloud.ibm.com/apidocs/watsonx-ai#list-foundation-model-specs
199
+ today = date.today().strftime("%Y-%m-%d")
200
+ url = f"{self.__base_url}/ml/v1/foundation_model_specs?version={today}&filters=task_generation,task_summarization:and"
201
+ headers = {
202
+ "Authorization": f"Bearer {self.__apy_key}",
203
+ "Content-Type": "application/json"
204
+ }
205
+ response = requests.get(url, headers=headers)
206
+ models = response.json().get("resources", [])
207
+ return [{
208
+ "id": model['model_id'],
209
+ "provider": model['provider'],
210
+ "tasks": model['task_ids'],
211
+ "limits": model.get('model_limits', {}),
212
+ } for model in models if model['provider'].lower() in ['ibm','meta','mistral ai']]
213
+ except Exception as e:
214
+ print(f"Error fetching models from IBM WatsonX: {e}")
215
+ # https://www.ibm.com/products/watsonx-ai/foundation-models
216
+ return [
217
+ {"id":"granite-3-3-8b-instruct"},
218
+ {"id":"granite-vision-3-2-2b"},
219
+ {"id":"granite-13b-instruct"},
220
+ {"id":"llama-4-scout-17b-16e-instruct"},
221
+ {"id":"llama-3-3-70b-instruct"},
222
+ {"id":"mistral-medium-2505"},
223
+ {"id":"mistral-small-3-1-24b-instruct-2503"},
224
+ {"id":"mistral-large-2"}
225
+ ]
226
+
227
+ def get_embeddings(self):
228
+ from langchain_ibm import WatsonxEmbeddings
229
+ return WatsonxEmbeddings(
230
+ model_id="ibm/granite-embedding-107m-multilingual", #https://www.ibm.com/products/watsonx-ai/foundation-models
231
+ url=self.__base_url,
232
+ apikey=self.__apy_key
233
+ )
234
+
182
235
  class Ollama(LlmInterface):
183
236
  def __init__(self, config: LlmConfig):
184
237
  super().__init__(config)
185
- self.__base_url = self.config.api_url or os.getenv("OLLAMA_API_URL")
238
+ self.__base_url = self.config.api_url or os.getenv("OLLAMA_API_URL") or "http://localhost:11434"
186
239
  def get_llm(self):
187
240
  from langchain_ollama.chat_models import ChatOllama
188
241
  return ChatOllama(
@@ -221,6 +274,7 @@ class LlmManager:
221
274
  "google": Google,
222
275
  "gvertex": Gvertex,
223
276
  "groq": Groq,
277
+ "ibm": IBM,
224
278
  "openai": OpenAI,
225
279
  "ollama": Ollama
226
280
  }
ws_bom_robot_app/main.py CHANGED
@@ -70,7 +70,7 @@ def __get_disk_info():
70
70
  return _disks
71
71
  @app.get("/api/diag",tags=["diag"])
72
72
  def diag(authenticate: bool = Depends(authenticate)):
73
- import pkg_resources, psutil
73
+ import importlib,psutil
74
74
  from ws_bom_robot_app.llm.providers.llm_manager import LlmManager as wsllm
75
75
  from ws_bom_robot_app.llm.vector_store.db.manager import VectorDbManager as wsdb
76
76
  from ws_bom_robot_app.llm.vector_store.loader.base import Loader as wsldr
@@ -81,7 +81,7 @@ def diag(authenticate: bool = Depends(authenticate)):
81
81
  svmem = psutil.virtual_memory()
82
82
  swap = psutil.swap_memory()
83
83
  try:
84
- ws_bom_robot_app_version = pkg_resources.get_distribution("ws_bom_robot_app").version
84
+ ws_bom_robot_app_version = importlib.metadata.version("ws_bom_robot_app")
85
85
  except:
86
86
  ws_bom_robot_app_version = "unknown"
87
87
  peer_process_ids = [c.pid for c in psutil.Process(os.getppid()).children()] if config.runtime_options().is_multi_process else None
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ws_bom_robot_app
3
- Version: 0.0.63
3
+ Version: 0.0.65
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
@@ -22,6 +22,7 @@ Requires-Dist: langchain-community==0.3.26
22
22
  Requires-Dist: langchain-core==0.3.67
23
23
  Requires-Dist: langchain-openai==0.3.27
24
24
  Requires-Dist: langchain-anthropic==0.3.6
25
+ Requires-Dist: langchain-ibm==0.3.14
25
26
  Requires-Dist: langchain-google-genai==2.0.7
26
27
  Requires-Dist: langchain-google-vertexai==2.0.27
27
28
  Requires-Dist: langchain-groq==0.3.5
@@ -1,8 +1,8 @@
1
1
  ws_bom_robot_app/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
2
  ws_bom_robot_app/auth.py,sha256=84nIbmJsMrNs0sxIQGEHbjsjc2P6ZrZZGSn8dkiL6is,895
3
- ws_bom_robot_app/config.py,sha256=JFO4HrFnzUjFfv5MH0Tzwda0krllEqmTufHZ6J-BgEI,4147
3
+ ws_bom_robot_app/config.py,sha256=izfyxYJE4GHNFNsi3UWDluyJySDwoVx1QMQhMzQIQCw,4260
4
4
  ws_bom_robot_app/cron_manager.py,sha256=pFHV7SZtp6GRmmLD9K1Mb1TE9Ev9n5mIiFScrc7tpCo,9221
5
- ws_bom_robot_app/main.py,sha256=zO3B-v-v9ESASvw8IaQj9Y9hNvNmOxohFmA0R82EybQ,6518
5
+ ws_bom_robot_app/main.py,sha256=1vx0k2fEcE53IC5zcE2EUCwQPcUHM4pvuKSun_E0a9I,6501
6
6
  ws_bom_robot_app/task_manager.py,sha256=Q3Il2TtkP0FoG9zHEBu48pZGXzimTtvWQsoH6wdvQs0,16077
7
7
  ws_bom_robot_app/util.py,sha256=RjVD6B9sHje788Lndqq5DHy6TJM0KLs9qx3JYt81Wyk,4834
8
8
  ws_bom_robot_app/llm/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -12,8 +12,8 @@ ws_bom_robot_app/llm/agent_handler.py,sha256=-9ia0bpNXgqLGFCSmAiU5ogdoJo30yl-XUN
12
12
  ws_bom_robot_app/llm/agent_lcel.py,sha256=e1ZELfUEpqMXJwLWxyOtgiUmVwoO3Aw-ua4u05XociA,2297
13
13
  ws_bom_robot_app/llm/api.py,sha256=2bF-UFczY9LuBqPxKObM0TOWYbZgVztX1RiIz5MSorU,5042
14
14
  ws_bom_robot_app/llm/defaut_prompt.py,sha256=D9dn8yPveu0bVwGM1wQWLYftmBs5O76o0R_caLLll8w,1121
15
- ws_bom_robot_app/llm/main.py,sha256=je8-Q-WtzQMtwEGzsUqHpLjVtMq8IObLi8VFIa6tbeo,5204
16
- ws_bom_robot_app/llm/nebuly_handler.py,sha256=w895twhPgtRUH_jZz1pbX4W2leq8A3O_9gUwp_ridoY,8033
15
+ ws_bom_robot_app/llm/main.py,sha256=pnMoBz9XniuJbTxlOpHdjm_0nd87EUD37sNzRbV2uqc,5328
16
+ ws_bom_robot_app/llm/nebuly_handler.py,sha256=MV4IqFcKv9lrBEAHYZsMkrYH8gpLNpujRcDji_GsnE8,8081
17
17
  ws_bom_robot_app/llm/settings.py,sha256=DCLaGZwxlw0xE46LpfUgin_FHD8_XJIthCgI6r2UDlM,121
18
18
  ws_bom_robot_app/llm/feedbacks/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
19
19
  ws_bom_robot_app/llm/feedbacks/feedback_manager.py,sha256=vNcZLG9IKhurAk7hjBqyFgQTjnh3Cd4GnxeYsX7ZdiA,2922
@@ -23,7 +23,7 @@ ws_bom_robot_app/llm/models/base.py,sha256=1TqxuTK3rjJEALn7lvgoen_1ba3R2brAgGx6E
23
23
  ws_bom_robot_app/llm/models/feedback.py,sha256=pYNQGxNOBgeAAfdJLI95l7ePLBI5tVdsgnyjp5oMOQU,1722
24
24
  ws_bom_robot_app/llm/models/kb.py,sha256=oVSw6_dmNxikAHrPqcfxDXz9M0ezLIYuxpgvzfs_Now,9514
25
25
  ws_bom_robot_app/llm/providers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
26
- ws_bom_robot_app/llm/providers/llm_manager.py,sha256=zIkxgTLYQCcup2Ixf4eWap4mNinuJH2YmkjLjZGDyJM,8371
26
+ ws_bom_robot_app/llm/providers/llm_manager.py,sha256=8lScD-tG1o2g_tM04Ju96j2JyLIAa5Z8Gm5ttQfDOFQ,10750
27
27
  ws_bom_robot_app/llm/tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
28
28
  ws_bom_robot_app/llm/tools/tool_builder.py,sha256=vQ8BX3MFd3WX2WlYAibbC4PpzxevdrdqKGk0SpKPrPs,3265
29
29
  ws_bom_robot_app/llm/tools/tool_manager.py,sha256=I8CHAdXx5KO1aw1NkDEQjCls9a-E8K6JrCQ-rzfImWY,14390
@@ -66,7 +66,7 @@ ws_bom_robot_app/llm/vector_store/loader/__init__.py,sha256=47DEQpj8HBSa-_TImW-5
66
66
  ws_bom_robot_app/llm/vector_store/loader/base.py,sha256=L_ugekNuAq0N9O-24wtlHSNHkqSeD-KsJrfGt_FX9Oc,5340
67
67
  ws_bom_robot_app/llm/vector_store/loader/docling.py,sha256=yP0zgXLeFAlByaYuj-6cYariuknckrFds0dxdRcnVz8,3456
68
68
  ws_bom_robot_app/llm/vector_store/loader/json_loader.py,sha256=LDppW0ZATo4_1hh-KlsAM3TLawBvwBxva_a7k5Oz1sc,858
69
- ws_bom_robot_app-0.0.63.dist-info/METADATA,sha256=X2pbeuERrYrwt-8VhjEK19qE027RIRkSu3L5zbeQsaY,8459
70
- ws_bom_robot_app-0.0.63.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
71
- ws_bom_robot_app-0.0.63.dist-info/top_level.txt,sha256=Yl0akyHVbynsBX_N7wx3H3ZTkcMLjYyLJs5zBMDAKcM,17
72
- ws_bom_robot_app-0.0.63.dist-info/RECORD,,
69
+ ws_bom_robot_app-0.0.65.dist-info/METADATA,sha256=DumFXAK22DQzbsnRsw0xJI61LDjRMnc117x5j9N0vqM,8497
70
+ ws_bom_robot_app-0.0.65.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
71
+ ws_bom_robot_app-0.0.65.dist-info/top_level.txt,sha256=Yl0akyHVbynsBX_N7wx3H3ZTkcMLjYyLJs5zBMDAKcM,17
72
+ ws_bom_robot_app-0.0.65.dist-info/RECORD,,