agently 4.0.5.4__tar.gz → 4.0.5.6__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 (76) hide show
  1. {agently-4.0.5.4 → agently-4.0.5.6}/PKG-INFO +1 -1
  2. {agently-4.0.5.4 → agently-4.0.5.6}/agently/builtins/plugins/ModelRequester/OpenAICompatible.py +89 -34
  3. {agently-4.0.5.4 → agently-4.0.5.6}/agently/builtins/plugins/ResponseParser/AgentlyResponseParser.py +14 -7
  4. agently-4.0.5.6/agently/integrations/chromadb.py +86 -0
  5. {agently-4.0.5.4 → agently-4.0.5.6}/pyproject.toml +1 -1
  6. {agently-4.0.5.4 → agently-4.0.5.6}/LICENSE +0 -0
  7. {agently-4.0.5.4 → agently-4.0.5.6}/README.md +0 -0
  8. {agently-4.0.5.4 → agently-4.0.5.6}/agently/__init__.py +0 -0
  9. {agently-4.0.5.4 → agently-4.0.5.6}/agently/_default_init.py +0 -0
  10. {agently-4.0.5.4 → agently-4.0.5.6}/agently/_default_settings.yaml +0 -0
  11. {agently-4.0.5.4 → agently-4.0.5.6}/agently/base.py +0 -0
  12. {agently-4.0.5.4 → agently-4.0.5.6}/agently/builtins/agent_extensions/AutoFuncExtension.py +0 -0
  13. {agently-4.0.5.4 → agently-4.0.5.6}/agently/builtins/agent_extensions/ChatSessionExtension.py +0 -0
  14. {agently-4.0.5.4 → agently-4.0.5.6}/agently/builtins/agent_extensions/ConfigurePromptExtension.py +0 -0
  15. {agently-4.0.5.4 → agently-4.0.5.6}/agently/builtins/agent_extensions/KeyWaiterExtension.py +0 -0
  16. {agently-4.0.5.4 → agently-4.0.5.6}/agently/builtins/agent_extensions/ToolExtension.py +0 -0
  17. {agently-4.0.5.4 → agently-4.0.5.6}/agently/builtins/agent_extensions/__init__.py +0 -0
  18. {agently-4.0.5.4 → agently-4.0.5.6}/agently/builtins/hookers/ConsoleHooker.py +0 -0
  19. {agently-4.0.5.4 → agently-4.0.5.6}/agently/builtins/hookers/PureLoggerHooker.py +0 -0
  20. {agently-4.0.5.4 → agently-4.0.5.6}/agently/builtins/hookers/SystemMessageHooker.py +0 -0
  21. {agently-4.0.5.4 → agently-4.0.5.6}/agently/builtins/plugins/PromptGenerator/AgentlyPromptGenerator.py +0 -0
  22. {agently-4.0.5.4 → agently-4.0.5.6}/agently/builtins/plugins/ToolManager/AgentlyToolManager.py +0 -0
  23. {agently-4.0.5.4 → agently-4.0.5.6}/agently/builtins/plugins/__init__.py +0 -0
  24. {agently-4.0.5.4 → agently-4.0.5.6}/agently/builtins/tools/Browse.py +0 -0
  25. {agently-4.0.5.4 → agently-4.0.5.6}/agently/builtins/tools/Search.py +0 -0
  26. {agently-4.0.5.4 → agently-4.0.5.6}/agently/builtins/tools/__init__.py +0 -0
  27. {agently-4.0.5.4 → agently-4.0.5.6}/agently/core/Agent.py +0 -0
  28. {agently-4.0.5.4 → agently-4.0.5.6}/agently/core/EventCenter.py +0 -0
  29. {agently-4.0.5.4 → agently-4.0.5.6}/agently/core/ExtensionHandlers.py +0 -0
  30. {agently-4.0.5.4 → agently-4.0.5.6}/agently/core/ModelRequest.py +0 -0
  31. {agently-4.0.5.4 → agently-4.0.5.6}/agently/core/PluginManager.py +0 -0
  32. {agently-4.0.5.4 → agently-4.0.5.6}/agently/core/Prompt.py +0 -0
  33. {agently-4.0.5.4 → agently-4.0.5.6}/agently/core/Tool.py +0 -0
  34. {agently-4.0.5.4 → agently-4.0.5.6}/agently/core/TriggerFlow/BluePrint.py +0 -0
  35. {agently-4.0.5.4 → agently-4.0.5.6}/agently/core/TriggerFlow/Chunk.py +0 -0
  36. {agently-4.0.5.4 → agently-4.0.5.6}/agently/core/TriggerFlow/Execution.py +0 -0
  37. {agently-4.0.5.4 → agently-4.0.5.6}/agently/core/TriggerFlow/Process.py +0 -0
  38. {agently-4.0.5.4 → agently-4.0.5.6}/agently/core/TriggerFlow/TriggerFlow.py +0 -0
  39. {agently-4.0.5.4 → agently-4.0.5.6}/agently/core/TriggerFlow/__init__.py +0 -0
  40. {agently-4.0.5.4 → agently-4.0.5.6}/agently/core/TriggerFlow/process/BaseProcess.py +0 -0
  41. {agently-4.0.5.4 → agently-4.0.5.6}/agently/core/TriggerFlow/process/ForEachProcess.py +0 -0
  42. {agently-4.0.5.4 → agently-4.0.5.6}/agently/core/TriggerFlow/process/MatchCaseProcess.py +0 -0
  43. {agently-4.0.5.4 → agently-4.0.5.6}/agently/core/TriggerFlow/process/__init__.py +0 -0
  44. {agently-4.0.5.4 → agently-4.0.5.6}/agently/core/__init__.py +0 -0
  45. {agently-4.0.5.4 → agently-4.0.5.6}/agently/types/__init__.py +0 -0
  46. {agently-4.0.5.4 → agently-4.0.5.6}/agently/types/data/__init__.py +0 -0
  47. {agently-4.0.5.4 → agently-4.0.5.6}/agently/types/data/event.py +0 -0
  48. {agently-4.0.5.4 → agently-4.0.5.6}/agently/types/data/prompt.py +0 -0
  49. {agently-4.0.5.4 → agently-4.0.5.6}/agently/types/data/request.py +0 -0
  50. {agently-4.0.5.4 → agently-4.0.5.6}/agently/types/data/response.py +0 -0
  51. {agently-4.0.5.4 → agently-4.0.5.6}/agently/types/data/serializable.py +0 -0
  52. {agently-4.0.5.4 → agently-4.0.5.6}/agently/types/data/tool.py +0 -0
  53. {agently-4.0.5.4 → agently-4.0.5.6}/agently/types/plugins/EventHooker.py +0 -0
  54. {agently-4.0.5.4 → agently-4.0.5.6}/agently/types/plugins/ModelRequester.py +0 -0
  55. {agently-4.0.5.4 → agently-4.0.5.6}/agently/types/plugins/PromptGenerator.py +0 -0
  56. {agently-4.0.5.4 → agently-4.0.5.6}/agently/types/plugins/ResponseParser.py +0 -0
  57. {agently-4.0.5.4 → agently-4.0.5.6}/agently/types/plugins/ToolManager.py +0 -0
  58. {agently-4.0.5.4 → agently-4.0.5.6}/agently/types/plugins/__init__.py +0 -0
  59. {agently-4.0.5.4 → agently-4.0.5.6}/agently/types/plugins/base.py +0 -0
  60. {agently-4.0.5.4 → agently-4.0.5.6}/agently/types/trigger_flow/__init__.py +0 -0
  61. {agently-4.0.5.4 → agently-4.0.5.6}/agently/types/trigger_flow/trigger_flow.py +0 -0
  62. {agently-4.0.5.4 → agently-4.0.5.6}/agently/utils/DataFormatter.py +0 -0
  63. {agently-4.0.5.4 → agently-4.0.5.6}/agently/utils/DataLocator.py +0 -0
  64. {agently-4.0.5.4 → agently-4.0.5.6}/agently/utils/DataPathBuilder.py +0 -0
  65. {agently-4.0.5.4 → agently-4.0.5.6}/agently/utils/FunctionShifter.py +0 -0
  66. {agently-4.0.5.4 → agently-4.0.5.6}/agently/utils/GeneratorConsumer.py +0 -0
  67. {agently-4.0.5.4 → agently-4.0.5.6}/agently/utils/LazyImport.py +0 -0
  68. {agently-4.0.5.4 → agently-4.0.5.6}/agently/utils/Logger.py +0 -0
  69. {agently-4.0.5.4 → agently-4.0.5.6}/agently/utils/Messenger.py +0 -0
  70. {agently-4.0.5.4 → agently-4.0.5.6}/agently/utils/RuntimeData.py +0 -0
  71. {agently-4.0.5.4 → agently-4.0.5.6}/agently/utils/SerializableRuntimeData.py +0 -0
  72. {agently-4.0.5.4 → agently-4.0.5.6}/agently/utils/Settings.py +0 -0
  73. {agently-4.0.5.4 → agently-4.0.5.6}/agently/utils/Storage.py +0 -0
  74. {agently-4.0.5.4 → agently-4.0.5.6}/agently/utils/StreamingJSONCompleter.py +0 -0
  75. {agently-4.0.5.4 → agently-4.0.5.6}/agently/utils/StreamingJSONParser.py +0 -0
  76. {agently-4.0.5.4 → agently-4.0.5.6}/agently/utils/__init__.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: agently
3
- Version: 4.0.5.4
3
+ Version: 4.0.5.6
4
4
  Summary:
5
5
  License: Apache-2.0
6
6
  License-File: LICENSE
@@ -84,6 +84,8 @@ class OpenAICompatible(ModelRequester):
84
84
  "$mappings": {
85
85
  "path_mappings": {
86
86
  "OpenAICompatible": "plugins.ModelRequester.OpenAICompatible",
87
+ "OpenAI": "plugins.ModelRequester.OpenAICompatible",
88
+ "OAIClient": "plugins.ModelRequester.OpenAICompatible",
87
89
  },
88
90
  },
89
91
  "model_type": "chat",
@@ -98,6 +100,7 @@ class OpenAICompatible(ModelRequester):
98
100
  "proxy": None,
99
101
  "request_options": {},
100
102
  "base_url": "https://api.openai.com/v1",
103
+ "full_url": None,
101
104
  "path_mapping": {
102
105
  "chat": "/chat/completions",
103
106
  "completions": "/completions",
@@ -181,13 +184,25 @@ class OpenAICompatible(ModelRequester):
181
184
  request_data = {"prompt": self.prompt.to_text()}
182
185
  case "embeddings":
183
186
  sanitized_input = DataFormatter.sanitize(self.prompt["input"])
184
- request_data = {
185
- "input": (
186
- str(sanitized_input)
187
- if isinstance(sanitized_input, (str, int, float, bool)) or sanitized_input is None
188
- else yaml.safe_dump(sanitized_input)
189
- )
190
- }
187
+ if isinstance(sanitized_input, list):
188
+ request_data = {
189
+ "input": [
190
+ (
191
+ str(item)
192
+ if isinstance(item, (str, int, float, bool)) or item is None
193
+ else yaml.safe_dump(item)
194
+ )
195
+ for item in sanitized_input
196
+ ],
197
+ }
198
+ else:
199
+ request_data = {
200
+ "input": (
201
+ str(sanitized_input)
202
+ if isinstance(sanitized_input, (str, int, float, bool)) or sanitized_input is None
203
+ else yaml.safe_dump(sanitized_input)
204
+ )
205
+ }
191
206
  case _:
192
207
  self._messenger.error(
193
208
  TypeError(
@@ -261,12 +276,19 @@ class OpenAICompatible(ModelRequester):
261
276
  }
262
277
  )
263
278
  ## !: ensure stream
264
- is_stream = self.plugin_settings.get("stream", True)
279
+ is_stream = self.plugin_settings.get("stream")
280
+ if is_stream is None:
281
+ if self.model_type == "embeddings":
282
+ is_stream = False
283
+ else:
284
+ is_stream = True
265
285
  request_options.update({"stream": is_stream})
266
286
  ## set
267
287
  agently_request_dict["request_options"] = request_options
268
288
 
269
289
  # request url
290
+ ## get full url
291
+ full_url = self.plugin_settings.get("full_url")
270
292
  ## get base url
271
293
  base_url = str(self.plugin_settings.get("base_url"))
272
294
  base_url = base_url[:-1] if base_url[-1] == "/" else base_url
@@ -278,7 +300,10 @@ class OpenAICompatible(ModelRequester):
278
300
  )
279
301
  path_mapping = {k: v if v[0] == "/" else f"/{ v }" for k, v in path_mapping.items()}
280
302
  ## set
281
- request_url = f"{ base_url }{ path_mapping[self.model_type] }"
303
+ if isinstance(full_url, str):
304
+ request_url = full_url
305
+ else:
306
+ request_url = f"{ base_url }{ path_mapping[self.model_type] }"
282
307
  agently_request_dict["request_url"] = request_url
283
308
 
284
309
  return AgentlyRequestData(**agently_request_dict)
@@ -357,22 +382,34 @@ class OpenAICompatible(ModelRequester):
357
382
  json=full_request_data,
358
383
  headers=headers_with_auth,
359
384
  )
360
- content_type = response.headers.get("Content-Type", "")
361
- if content_type.startswith("application/json"):
362
- try:
363
- error_json = response.json()
364
- except Exception:
365
- error_json = await response.aread()
366
- error_json = json.loads(error_json.decode())
367
- error = error_json["error"]
368
- error_title = f"{ error['code'] if 'code' in error else 'unknown_code' } - { error['type'] if 'type' in error else 'unknown_type' }"
369
- error_detail = error["message"] if "message" in error else ""
370
- yield "error", error_detail
371
- else:
385
+ # Raise status code >= 400
386
+ if response.status_code >= 400:
387
+ e = RequestError(
388
+ f"Status Code: { response.status_code }\n" f"Request Data: {full_request_data}"
389
+ )
372
390
  self._messenger.error(
373
- "Error: SSE Error\n" f"Detail: {e}\n" f"Request Data: {full_request_data}", status="FAILED"
391
+ e,
392
+ status="FAILED",
374
393
  )
375
394
  yield "error", e
395
+ else:
396
+ content_type = response.headers.get("Content-Type", "")
397
+ if content_type.startswith("application/json"):
398
+ try:
399
+ error_json = response.json()
400
+ except Exception:
401
+ error_json = await response.aread()
402
+ error_json = json.loads(error_json.decode())
403
+ error = error_json["error"]
404
+ error_title = f"{ error['code'] if 'code' in error else 'unknown_code' } - { error['type'] if 'type' in error else 'unknown_type' }"
405
+ error_detail = error["message"] if "message" in error else ""
406
+ yield "error", error_detail
407
+ else:
408
+ self._messenger.error(
409
+ "Error: SSE Error\n" f"Detail: {e}\n" f"Request Data: {full_request_data}",
410
+ status="FAILED",
411
+ )
412
+ yield "error", e
376
413
  except HTTPStatusError as e:
377
414
  self._messenger.error(
378
415
  "Error: HTTP Status Error\n"
@@ -410,8 +447,18 @@ class OpenAICompatible(ModelRequester):
410
447
  request_data.request_url,
411
448
  json=full_request_data,
412
449
  )
413
- yield "message", response.content.decode()
414
- yield "message", "[DONE]"
450
+ if response.status_code >= 400:
451
+ e = RequestError(
452
+ f"Status Code: { response.status_code }\n" f"Request Data: {full_request_data}"
453
+ )
454
+ self._messenger.error(
455
+ e,
456
+ status="FAILED",
457
+ )
458
+ yield "error", e
459
+ else:
460
+ yield "message", response.content.decode()
461
+ yield "message", "[DONE]"
415
462
  except HTTPStatusError as e:
416
463
  self._messenger.error(
417
464
  "Error: HTTP Status Error\n"
@@ -480,6 +527,7 @@ class OpenAICompatible(ModelRequester):
480
527
  loaded_message,
481
528
  role_mapping,
482
529
  style=content_mapping_style,
530
+ default="assistant",
483
531
  )
484
532
  if role:
485
533
  meta.update({"role": role})
@@ -503,6 +551,9 @@ class OpenAICompatible(ModelRequester):
503
551
  yield "extra", {extra_key: extra_value}
504
552
  else:
505
553
  done_content = None
554
+ if self.model_type == "embeddings" and done_mapping is None:
555
+ done_mapping = "data"
556
+ content_mapping_style = "dot"
506
557
  if done_mapping:
507
558
  done_content = DataLocator.locate_path_in_dict(
508
559
  message_record,
@@ -513,16 +564,20 @@ class OpenAICompatible(ModelRequester):
513
564
  yield "done", done_content
514
565
  else:
515
566
  yield "done", content_buffer
516
- done_message = message_record
517
- if "message" not in done_message["choices"][0]:
518
- done_message["choices"][0].update({"message": {}})
519
- done_message["choices"][0]["message"].update(
520
- {
521
- "role": meta["role"] if "role" in meta else "assistant",
522
- "content": done_content if done_content else content_buffer,
523
- }
524
- )
525
- yield "original_done", done_message
567
+ match self.model_type:
568
+ case "embeddings":
569
+ yield "original_done", message_record
570
+ case "_":
571
+ done_message = message_record
572
+ if "message" not in done_message["choices"][0]:
573
+ done_message["choices"][0].update({"message": {}})
574
+ done_message["choices"][0]["message"].update(
575
+ {
576
+ "role": meta["role"] if "role" in meta else "assistant",
577
+ "content": done_content if done_content else content_buffer,
578
+ }
579
+ )
580
+ yield "original_done", done_message
526
581
  if finish_reason_mapping:
527
582
  meta.update(
528
583
  {
@@ -153,12 +153,12 @@ class AgentlyResponseParser(ResponseParser):
153
153
  self.full_result_data["original_done"] = data
154
154
  case "done":
155
155
  self.full_result_data["text_result"] = str(data)
156
- if buffer != self.full_result_data["text_result"]:
157
- warnings.warn(
158
- "Buffered streaming result is not exactly the same as final result.\n"
159
- f"Buffered Result: { buffer }\n"
160
- f"Final Result: { self.full_result_data['text_result'] }\n"
161
- )
156
+ # if buffer != self.full_result_data["text_result"]:
157
+ # warnings.warn(
158
+ # "Buffered streaming result is not exactly the same as final result.\n"
159
+ # f"Buffered Result: { buffer }\n"
160
+ # f"Final Result: { self.full_result_data['text_result'] }\n"
161
+ # )
162
162
  if self._prompt_object.output_format == "json":
163
163
  cleaned_json = DataLocator.locate_output_json(str(data), self._prompt_object.output)
164
164
  if cleaned_json:
@@ -204,7 +204,14 @@ class AgentlyResponseParser(ResponseParser):
204
204
  self.settings,
205
205
  )
206
206
  else:
207
- self.full_result_data["parsed_result"] = str(data)
207
+ if (
208
+ isinstance(data, list)
209
+ and isinstance(data[0], dict)
210
+ and "object" in data[0]
211
+ and data[0]["object"] == "embedding"
212
+ ):
213
+ data = [item["embedding"] for item in data]
214
+ self.full_result_data["parsed_result"] = data
208
215
  if self.settings.get("$log.cancel_logs") is not True:
209
216
  await async_system_message(
210
217
  "MODEL_REQUEST",
@@ -0,0 +1,86 @@
1
+ from agently.utils import LazyImport
2
+
3
+ LazyImport.import_package("chromadb")
4
+
5
+ import json
6
+
7
+ from chromadb.api.types import EmbeddingFunction, Documents, Embedding, Embeddings
8
+
9
+ from typing import Callable, TypedDict, Any, cast
10
+ from agently.core import BaseAgent
11
+
12
+
13
+ class ChromaDataDictOptional(TypedDict, total=False):
14
+ metadata: dict[Any, Any]
15
+ id: Any
16
+ embedding: Embedding
17
+
18
+
19
+ class ChromaDataDict(ChromaDataDictOptional):
20
+ document: str
21
+
22
+
23
+ class ChromaData:
24
+ def __init__(
25
+ self,
26
+ original_data: ChromaDataDict | list[ChromaDataDict],
27
+ *,
28
+ embedding_function: Callable[[str | list[str]], Embeddings] | None = None,
29
+ agent: BaseAgent | None = None,
30
+ ):
31
+ self._original_data = original_data if isinstance(original_data, list) else [original_data]
32
+ if embedding_function:
33
+ self._embedding_function = embedding_function
34
+ elif agent:
35
+
36
+ def embedding_function_by_agent(texts: str | list[str]) -> Embeddings:
37
+ return agent.input(texts).start()
38
+
39
+ self._embedding_function = embedding_function_by_agent
40
+ else:
41
+ self._embedding_function = None
42
+ self._chroma_data = {
43
+ "documents": [],
44
+ "metadatas": [],
45
+ "ids": [],
46
+ "embeddings": [],
47
+ }
48
+ if self._embedding_function is not None:
49
+ documents = [data["document"] for data in self._original_data]
50
+ embeddings = self._embedding_function(documents)
51
+ self._chroma_data["embeddings"] = embeddings
52
+ for index, data in enumerate(self._original_data):
53
+ data["embedding"] = embeddings[index]
54
+ else:
55
+ del self._chroma_data["embeddings"]
56
+ for index, data in enumerate(self._original_data):
57
+ self._chroma_data["documents"].append(data["document"])
58
+ self._chroma_data["metadatas"].append(data["metadata"] if "metadata" in data else None)
59
+ self._chroma_data["ids"].append(data["id"] if "id" in data else str(index))
60
+
61
+ def get_kwargs(self):
62
+ return self._chroma_data
63
+
64
+ def get_original_data(self):
65
+ return self._original_data
66
+
67
+
68
+ class ChromaEmbeddingFunction(EmbeddingFunction):
69
+ def __init__(
70
+ self, *, embedding_function: Callable[[list[str]], Embeddings] | None = None, agent: BaseAgent | None = None
71
+ ):
72
+ if embedding_function:
73
+ self.embedding_function = embedding_function
74
+ elif agent:
75
+
76
+ def embedding_function_by_agent(texts: list[str]) -> Embeddings:
77
+ return agent.input(texts).start()
78
+
79
+ self.embedding_function = embedding_function_by_agent
80
+ else:
81
+ raise ValueError(
82
+ f"ChromaEmbeddingFunction() requires at least one definition for 'embedding_function' or 'agent'."
83
+ )
84
+
85
+ def __call__(self, documents: Documents) -> Embeddings:
86
+ return self.embedding_function([document for document in documents])
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "agently"
3
- version = "4.0.5.4"
3
+ version = "4.0.5.6"
4
4
  description = ""
5
5
  authors = [
6
6
  {name = "Agently Team",email = "developer@agently.tech"},
File without changes
File without changes
File without changes
File without changes