dm-aioaiagent 0.3.4__py3-none-any.whl → 0.3.6__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.
dm_aioaiagent/__init__.py CHANGED
@@ -2,5 +2,5 @@ from dotenv import load_dotenv
2
2
  load_dotenv()
3
3
  from .ai_agent import DMAIAgent
4
4
  from .async_ai_agent import DMAioAIAgent
5
- from .image_message_content_builder import ImageMessageContentBuilder
5
+ from .openai_image_message_content import OpenAIImageMessageContent
6
6
  from .types import Message
dm_aioaiagent/ai_agent.py CHANGED
@@ -2,7 +2,6 @@ import os
2
2
  from pydantic import SecretStr
3
3
  from itertools import dropwhile
4
4
  from threading import Thread
5
- from langchain_openai import ChatOpenAI
6
5
  from langchain_core.tools import BaseTool
7
6
  from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
8
7
  from langchain_core.messages import SystemMessage, HumanMessage, AIMessage, ToolMessage
@@ -15,11 +14,11 @@ __all__ = ["DMAIAgent"]
15
14
 
16
15
 
17
16
  class DMAIAgent:
18
- agent_name = "AIAgent"
19
- _allowed_roles = ("user", "ai")
20
- _response_if_request_fail = "I can't provide a response right now. Please try again later."
21
- _response_if_invalid_image = "The image is unavailable or the link is incorrect."
17
+ AGENT_NAME = "AIAgent"
22
18
  MAX_MEMORY_MESSAGES = 20 # Only INT greater than 0
19
+ RESPONSE_IF_REQUEST_FAIL = "I can't provide a response right now. Please try again later."
20
+ RESPONSE_IF_INVALID_IMAGE = "The image is unavailable or the link is incorrect."
21
+ _ALLOWED_ROLES = ("user", "ai")
23
22
 
24
23
  def __init__(
25
24
  self,
@@ -28,52 +27,35 @@ class DMAIAgent:
28
27
  *,
29
28
  model: str = "gpt-4o-mini",
30
29
  temperature: int = 1,
30
+ parallel_tool_calls: bool = True,
31
31
  agent_name: str = None,
32
32
  input_output_logging: bool = True,
33
33
  is_memory_enabled: bool = True,
34
34
  save_tools_responses_in_memory: bool = True,
35
35
  max_memory_messages: int = None,
36
+ llm_provider_api_key: str = "",
36
37
  response_if_request_fail: str = None,
37
- response_if_invalid_image: str = None,
38
- openai_api_key: str = None
38
+ response_if_invalid_image: str = None
39
39
  ):
40
- if openai_api_key is None and not os.getenv("OPENAI_API_KEY"):
41
- raise EnvironmentError("'OPENAI_API_KEY' environment variable is not set!")
40
+ self._logger = DMLogger(agent_name or self.AGENT_NAME)
41
+ self._input_output_logging = bool(input_output_logging)
42
42
 
43
- self._logger = DMLogger(agent_name or self.agent_name)
43
+ self._system_message = str(system_message)
44
+ self._tools = tools or []
44
45
  self._is_tools_exists = bool(tools)
45
- self._input_output_logging = bool(input_output_logging)
46
+ self._model = str(model)
47
+ self._temperature = int(temperature)
48
+ self._parallel_tool_calls = bool(parallel_tool_calls)
49
+ self._llm_provider_api_key = str(llm_provider_api_key)
50
+
46
51
  self._is_memory_enabled = bool(is_memory_enabled)
47
52
  self._save_tools_responses_in_memory = bool(save_tools_responses_in_memory)
48
53
  self._max_memory_messages = self._validate_max_memory_messages(max_memory_messages)
49
- self._response_if_request_fail = str(response_if_request_fail or self._response_if_request_fail)
50
- self._response_if_invalid_image = str(response_if_invalid_image or self._response_if_invalid_image)
54
+ self._response_if_request_fail = str(response_if_request_fail or self.RESPONSE_IF_REQUEST_FAIL)
55
+ self._response_if_invalid_image = str(response_if_invalid_image or self.RESPONSE_IF_INVALID_IMAGE)
51
56
 
52
- prompt = ChatPromptTemplate.from_messages([SystemMessage(content=system_message),
53
- MessagesPlaceholder(variable_name="messages")])
54
- if openai_api_key:
55
- openai_api_key = SecretStr(openai_api_key)
56
- llm = ChatOpenAI(model_name=str(model), temperature=int(temperature), openai_api_key=openai_api_key)
57
- if self._is_tools_exists:
58
- self._tool_map = {t.name: t for t in tools}
59
- llm = llm.bind_tools(tools)
60
- self._agent = prompt | llm
61
- self._memory = {}
62
-
63
- workflow = StateGraph(State)
64
- workflow.add_node("Prepare messages", self._prepare_messages_node)
65
- workflow.add_node("Invoke LLM", self._invoke_llm_node)
66
- workflow.add_node("Execute tool", self._execute_tool_node)
67
- workflow.add_node("Exit", self._exit_node)
68
-
69
- workflow.add_edge("Prepare messages", "Invoke LLM")
70
- workflow.add_conditional_edges(source="Invoke LLM",
71
- path=self._messages_router,
72
- path_map={"execute_tool": "Execute tool", "exit": "Exit"})
73
- workflow.add_edge("Execute tool", "Invoke LLM")
74
- workflow.set_entry_point("Prepare messages")
75
- workflow.set_finish_point("Exit")
76
- self._graph = workflow.compile()
57
+ self._init_agent()
58
+ self._init_graph()
77
59
 
78
60
  def run(self, input_messages: InputMessagesType, memory_id: str = None) -> ResponseType:
79
61
  state = self._graph.invoke({"input_messages": input_messages, "memory_id": memory_id})
@@ -102,7 +84,7 @@ class DMAIAgent:
102
84
  if isinstance(item, dict):
103
85
  role = item.get("role")
104
86
  content = item.get("content")
105
- if not role or role not in self._allowed_roles or not content:
87
+ if not role or role not in self._ALLOWED_ROLES or not content:
106
88
  continue
107
89
  if role == "ai":
108
90
  MessageClass = AIMessage
@@ -195,6 +177,49 @@ class DMAIAgent:
195
177
  route = "exit"
196
178
  return route
197
179
 
180
+ def _init_agent(self) -> None:
181
+ if self._llm_provider_api_key:
182
+ self._llm_provider_api_key = SecretStr(self._llm_provider_api_key)
183
+
184
+ if self._model.startswith("gpt"):
185
+ from langchain_openai import ChatOpenAI
186
+
187
+ api_key = SecretStr(self._llm_provider_api_key or os.getenv("OPENAI_API_KEY"))
188
+ llm = ChatOpenAI(model_name=self._model, temperature=self._temperature, openai_api_key=api_key)
189
+ elif self._model.startswith("claude"):
190
+ from langchain_anthropic import ChatAnthropic
191
+
192
+ api_key = SecretStr(self._llm_provider_api_key or os.getenv("ANTHROPIC_API_KEY"))
193
+ llm = ChatAnthropic(model=self._model, temperature=self._temperature, anthropic_api_key=api_key)
194
+ else:
195
+ raise ValueError(f"{self.__class__.__name__} not support this model: '{self._model}'")
196
+
197
+ if self._is_tools_exists:
198
+ self._tool_map = {t.name: t for t in self._tools}
199
+ llm = llm.bind_tools(self._tools, parallel_tool_calls=self._parallel_tool_calls)
200
+
201
+ prompt = ChatPromptTemplate.from_messages([SystemMessage(content=self._system_message),
202
+ MessagesPlaceholder(variable_name="messages")])
203
+
204
+ self._agent = prompt | llm
205
+ self._memory = {}
206
+
207
+ def _init_graph(self) -> None:
208
+ workflow = StateGraph(State)
209
+ workflow.add_node("Prepare messages", self._prepare_messages_node)
210
+ workflow.add_node("Invoke LLM", self._invoke_llm_node)
211
+ workflow.add_node("Execute tool", self._execute_tool_node)
212
+ workflow.add_node("Exit", self._exit_node)
213
+
214
+ workflow.add_edge("Prepare messages", "Invoke LLM")
215
+ workflow.add_conditional_edges(source="Invoke LLM",
216
+ path=self._messages_router,
217
+ path_map={"execute_tool": "Execute tool", "exit": "Exit"})
218
+ workflow.add_edge("Execute tool", "Invoke LLM")
219
+ workflow.set_entry_point("Prepare messages")
220
+ workflow.set_finish_point("Exit")
221
+ self._graph = workflow.compile()
222
+
198
223
  @staticmethod
199
224
  def _validate_memory_id(memory_id: Union[str, None]) -> Union[str, int]:
200
225
  return str(memory_id) if memory_id else 0
@@ -1,4 +1,4 @@
1
- class ImageMessageContentBuilder(list):
1
+ class OpenAIImageMessageContent(list):
2
2
  def __init__(self, image_url: str, text: str = None):
3
3
  content = []
4
4
  if isinstance(text, str):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: dm-aioaiagent
3
- Version: 0.3.4
3
+ Version: 0.3.6
4
4
  Summary: This is my custom aioaiagent client
5
5
  Home-page: https://pypi.org/project/dm-aioaiagent
6
6
  Author: dimka4621
@@ -141,7 +141,8 @@ if __name__ == "__main__":
141
141
  ### Image vision
142
142
 
143
143
  ```python
144
- from dm_aioaiagent import DMAIAgent, ImageMessageContentBuilder
144
+ from dm_aioaiagent import DMAIAgent, OpenAIImageMessageContent
145
+
145
146
 
146
147
  def main():
147
148
  # create an agent
@@ -149,8 +150,8 @@ def main():
149
150
 
150
151
  # create an image message content
151
152
  # NOTE: text argument is optional
152
- img_content = ImageMessageContentBuilder(image_url="https://your.domain/image",
153
- text="Hello, what is shown in the photo?")
153
+ img_content = OpenAIImageMessageContent(image_url="https://your.domain/image",
154
+ text="Hello, what is shown in the photo?")
154
155
 
155
156
  # define the conversation message
156
157
  messages = [
@@ -163,7 +164,7 @@ def main():
163
164
 
164
165
 
165
166
  if __name__ == "__main__":
166
- main()
167
+ main()
167
168
  ```
168
169
 
169
170
  ### Set custom logger
@@ -0,0 +1,9 @@
1
+ dm_aioaiagent/__init__.py,sha256=ffLO0jGxiY40VYptRjJXCh7t0XKAccGtBXW5FafbFgA,213
2
+ dm_aioaiagent/ai_agent.py,sha256=dZUKlXkVftHKl_KmpMWnWp3ot-GJ3xBO_srz-d3_U-4,10966
3
+ dm_aioaiagent/async_ai_agent.py,sha256=qg7LZRxC7MSzjjburEX09T5EF15ZXAWAd_9RB8vA0oE,2599
4
+ dm_aioaiagent/openai_image_message_content.py,sha256=EP_i0ERCz7c4KOM8UXp2-AI91ntGC7PGQBc5MMNspcs,434
5
+ dm_aioaiagent/types.py,sha256=H2_iICmWr6u9d1-6BtSxdt6qV6Jm8v7Zh8das5kV6I4,989
6
+ dm_aioaiagent-0.3.6.dist-info/METADATA,sha256=qMm8tQs-CBLju_4Q0cB7Lz874P0oL-mPFgoAlyj9d94,5031
7
+ dm_aioaiagent-0.3.6.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
8
+ dm_aioaiagent-0.3.6.dist-info/top_level.txt,sha256=CbasLH0KI7zA77XwT6JDCnmRascxKNGvUVV9MgYjHAU,14
9
+ dm_aioaiagent-0.3.6.dist-info/RECORD,,
@@ -1,9 +0,0 @@
1
- dm_aioaiagent/__init__.py,sha256=pq9gL6E1VN4Tkx9PD83AIW9e_-N5REqJeC0TE8bZua4,215
2
- dm_aioaiagent/ai_agent.py,sha256=DY4SVdexuCSeS3P2iCm3dmi7UsZ5dEZ0ufd38jam03Q,9997
3
- dm_aioaiagent/async_ai_agent.py,sha256=qg7LZRxC7MSzjjburEX09T5EF15ZXAWAd_9RB8vA0oE,2599
4
- dm_aioaiagent/image_message_content_builder.py,sha256=mAJnsWdnpYpaFAdcCsVwgWH480Q4WfVEpM-Y6KdjyEc,435
5
- dm_aioaiagent/types.py,sha256=H2_iICmWr6u9d1-6BtSxdt6qV6Jm8v7Zh8das5kV6I4,989
6
- dm_aioaiagent-0.3.4.dist-info/METADATA,sha256=F_yZ1zenPup4UqUmDJD4cnE-I7U8MoI9z90gNO2Kces,5032
7
- dm_aioaiagent-0.3.4.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
8
- dm_aioaiagent-0.3.4.dist-info/top_level.txt,sha256=CbasLH0KI7zA77XwT6JDCnmRascxKNGvUVV9MgYjHAU,14
9
- dm_aioaiagent-0.3.4.dist-info/RECORD,,