dm-aioaiagent 0.3.2__tar.gz → 0.3.3__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.
- {dm_aioaiagent-0.3.2 → dm_aioaiagent-0.3.3}/PKG-INFO +30 -1
- {dm_aioaiagent-0.3.2 → dm_aioaiagent-0.3.3}/README.md +28 -0
- {dm_aioaiagent-0.3.2 → dm_aioaiagent-0.3.3}/dm_aioaiagent/__init__.py +1 -0
- {dm_aioaiagent-0.3.2 → dm_aioaiagent-0.3.3}/dm_aioaiagent/ai_agent.py +22 -6
- {dm_aioaiagent-0.3.2 → dm_aioaiagent-0.3.3}/dm_aioaiagent/async_ai_agent.py +11 -3
- dm_aioaiagent-0.3.3/dm_aioaiagent/image_message_content_builder.py +15 -0
- {dm_aioaiagent-0.3.2 → dm_aioaiagent-0.3.3}/dm_aioaiagent/types.py +22 -1
- {dm_aioaiagent-0.3.2 → dm_aioaiagent-0.3.3}/dm_aioaiagent.egg-info/PKG-INFO +30 -1
- {dm_aioaiagent-0.3.2 → dm_aioaiagent-0.3.3}/dm_aioaiagent.egg-info/SOURCES.txt +1 -0
- {dm_aioaiagent-0.3.2 → dm_aioaiagent-0.3.3}/dm_aioaiagent.egg-info/requires.txt +1 -0
- {dm_aioaiagent-0.3.2 → dm_aioaiagent-0.3.3}/setup.py +2 -1
- {dm_aioaiagent-0.3.2 → dm_aioaiagent-0.3.3}/dm_aioaiagent.egg-info/dependency_links.txt +0 -0
- {dm_aioaiagent-0.3.2 → dm_aioaiagent-0.3.3}/dm_aioaiagent.egg-info/top_level.txt +0 -0
- {dm_aioaiagent-0.3.2 → dm_aioaiagent-0.3.3}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: dm-aioaiagent
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.3
|
|
4
4
|
Summary: This is my custom aioaiagent client
|
|
5
5
|
Home-page: https://pypi.org/project/dm-aioaiagent
|
|
6
6
|
Author: dimka4621
|
|
@@ -18,6 +18,7 @@ Requires-Dist: pydantic<3.0.0,>=2.9.2
|
|
|
18
18
|
Requires-Dist: langchain~=0.3.0
|
|
19
19
|
Requires-Dist: langchain-core~=0.3.5
|
|
20
20
|
Requires-Dist: langgraph~=0.2.23
|
|
21
|
+
Requires-Dist: grandalf>=0.8
|
|
21
22
|
Requires-Dist: langchain-community~=0.3.0
|
|
22
23
|
Requires-Dist: langchain-openai~=0.2.0
|
|
23
24
|
|
|
@@ -137,6 +138,34 @@ if __name__ == "__main__":
|
|
|
137
138
|
asyncio.run(main())
|
|
138
139
|
```
|
|
139
140
|
|
|
141
|
+
### Image vision
|
|
142
|
+
|
|
143
|
+
```python
|
|
144
|
+
from dm_aioaiagent import DMAIAgent, ImageMessageContentBuilder
|
|
145
|
+
|
|
146
|
+
def main():
|
|
147
|
+
# create an agent
|
|
148
|
+
ai_agent = DMAIAgent(agent_name="image_vision", model="gpt-4o")
|
|
149
|
+
|
|
150
|
+
# create an image message content
|
|
151
|
+
# NOTE: text argument is optional
|
|
152
|
+
img_content = ImageMessageContentBuilder(image_url="https://your.domain/image",
|
|
153
|
+
text="Hello, what is shown in the photo?")
|
|
154
|
+
|
|
155
|
+
# define the conversation message
|
|
156
|
+
messages = [
|
|
157
|
+
{"role": "user", "content": "Hello!"},
|
|
158
|
+
{"role": "user", "content": img_content},
|
|
159
|
+
]
|
|
160
|
+
|
|
161
|
+
# call an agent
|
|
162
|
+
answer = ai_agent.run(messages)
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
if __name__ == "__main__":
|
|
166
|
+
main()
|
|
167
|
+
```
|
|
168
|
+
|
|
140
169
|
### Set custom logger
|
|
141
170
|
|
|
142
171
|
_If you want set up custom logger_
|
|
@@ -114,6 +114,34 @@ if __name__ == "__main__":
|
|
|
114
114
|
asyncio.run(main())
|
|
115
115
|
```
|
|
116
116
|
|
|
117
|
+
### Image vision
|
|
118
|
+
|
|
119
|
+
```python
|
|
120
|
+
from dm_aioaiagent import DMAIAgent, ImageMessageContentBuilder
|
|
121
|
+
|
|
122
|
+
def main():
|
|
123
|
+
# create an agent
|
|
124
|
+
ai_agent = DMAIAgent(agent_name="image_vision", model="gpt-4o")
|
|
125
|
+
|
|
126
|
+
# create an image message content
|
|
127
|
+
# NOTE: text argument is optional
|
|
128
|
+
img_content = ImageMessageContentBuilder(image_url="https://your.domain/image",
|
|
129
|
+
text="Hello, what is shown in the photo?")
|
|
130
|
+
|
|
131
|
+
# define the conversation message
|
|
132
|
+
messages = [
|
|
133
|
+
{"role": "user", "content": "Hello!"},
|
|
134
|
+
{"role": "user", "content": img_content},
|
|
135
|
+
]
|
|
136
|
+
|
|
137
|
+
# call an agent
|
|
138
|
+
answer = ai_agent.run(messages)
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
if __name__ == "__main__":
|
|
142
|
+
main()
|
|
143
|
+
```
|
|
144
|
+
|
|
117
145
|
### Set custom logger
|
|
118
146
|
|
|
119
147
|
_If you want set up custom logger_
|
|
@@ -16,6 +16,8 @@ __all__ = ["DMAIAgent"]
|
|
|
16
16
|
class DMAIAgent:
|
|
17
17
|
agent_name = "AIAgent"
|
|
18
18
|
_allowed_roles = ("user", "ai")
|
|
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."
|
|
19
21
|
MAX_MEMORY_MESSAGES = 20 # Only INT greater than 0
|
|
20
22
|
|
|
21
23
|
def __init__(
|
|
@@ -29,6 +31,8 @@ class DMAIAgent:
|
|
|
29
31
|
input_output_logging: bool = True,
|
|
30
32
|
is_memory_enabled: bool = True,
|
|
31
33
|
max_memory_messages: int = None,
|
|
34
|
+
response_if_request_fail: str = None,
|
|
35
|
+
response_if_invalid_image: str = None
|
|
32
36
|
):
|
|
33
37
|
if not os.getenv("OPENAI_API_KEY"):
|
|
34
38
|
raise EnvironmentError("'OPENAI_API_KEY' environment variable is not set!")
|
|
@@ -38,6 +42,8 @@ class DMAIAgent:
|
|
|
38
42
|
self._input_output_logging = bool(input_output_logging)
|
|
39
43
|
self._is_memory_enabled = bool(is_memory_enabled)
|
|
40
44
|
self._max_memory_messages = self._validate_max_memory_messages(max_memory_messages)
|
|
45
|
+
self._response_if_request_fail = str(response_if_request_fail or self._response_if_request_fail)
|
|
46
|
+
self._response_if_invalid_image = str(response_if_invalid_image or self._response_if_invalid_image)
|
|
41
47
|
|
|
42
48
|
prompt = ChatPromptTemplate.from_messages([SystemMessage(content=system_message),
|
|
43
49
|
MessagesPlaceholder(variable_name="messages")])
|
|
@@ -85,7 +91,6 @@ class DMAIAgent:
|
|
|
85
91
|
self._memory[self._validate_memory_id(memory_id)] = []
|
|
86
92
|
|
|
87
93
|
def _prepare_messages_node(self, state: State) -> State:
|
|
88
|
-
state.memory_id = self._validate_memory_id(state.memory_id)
|
|
89
94
|
state.input_messages = state.input_messages or [{"role": "user", "content": ""}]
|
|
90
95
|
for item in state.input_messages:
|
|
91
96
|
if isinstance(item, dict):
|
|
@@ -102,14 +107,23 @@ class DMAIAgent:
|
|
|
102
107
|
state.messages.append(item)
|
|
103
108
|
|
|
104
109
|
if self._input_output_logging:
|
|
105
|
-
|
|
110
|
+
log_kwargs = {} if state.memory_id is None else {"memory_id": state.memory_id}
|
|
111
|
+
self._logger.debug(f"Query:\n{state.messages[-1].content}", **log_kwargs)
|
|
106
112
|
if self._is_memory_enabled:
|
|
107
113
|
state.messages = self.get_memory_messages(state.memory_id) + state.messages
|
|
108
114
|
return state
|
|
109
115
|
|
|
110
|
-
def _invoke_llm_node(self, state: State) -> State:
|
|
116
|
+
def _invoke_llm_node(self, state: State, second_attempt: bool = False) -> State:
|
|
111
117
|
self._logger.debug("Run node: Invoke LLM")
|
|
112
|
-
|
|
118
|
+
try:
|
|
119
|
+
ai_response = self._agent.invoke({"messages": state.messages})
|
|
120
|
+
except Exception as e:
|
|
121
|
+
self._logger.error(e)
|
|
122
|
+
if second_attempt:
|
|
123
|
+
response = self._response_if_invalid_image if "invalid_image_url" in str(e) else self._response_if_request_fail
|
|
124
|
+
state.messages.append(AIMessage(content=response))
|
|
125
|
+
return state
|
|
126
|
+
return self._invoke_llm_node(state, second_attempt=True)
|
|
113
127
|
state.messages.append(ai_response)
|
|
114
128
|
return state
|
|
115
129
|
|
|
@@ -148,12 +162,14 @@ class DMAIAgent:
|
|
|
148
162
|
def _exit_node(self, state: State) -> State:
|
|
149
163
|
answer = state.messages[-1].content
|
|
150
164
|
if self._input_output_logging:
|
|
151
|
-
|
|
165
|
+
log_kwargs = {} if state.memory_id is None else {"memory_id": state.memory_id}
|
|
166
|
+
self._logger.debug(f"Answer:\n{answer}", **log_kwargs)
|
|
152
167
|
|
|
153
168
|
if self._is_memory_enabled:
|
|
169
|
+
memory_id = self._validate_memory_id(state.memory_id)
|
|
154
170
|
messages_to_memory = state.messages[-self._max_memory_messages:]
|
|
155
171
|
# drop ToolsMessages from start of list
|
|
156
|
-
self._memory[
|
|
172
|
+
self._memory[memory_id] = list(dropwhile(lambda x: isinstance(x, ToolMessage), messages_to_memory))
|
|
157
173
|
state.response = answer
|
|
158
174
|
else:
|
|
159
175
|
state.response = state.messages[len(state.input_messages):]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import sys
|
|
2
2
|
import asyncio
|
|
3
|
-
from langchain_core.messages import ToolMessage
|
|
3
|
+
from langchain_core.messages import AIMessage, ToolMessage
|
|
4
4
|
|
|
5
5
|
from .ai_agent import DMAIAgent
|
|
6
6
|
from .types import *
|
|
@@ -18,9 +18,17 @@ class DMAioAIAgent(DMAIAgent):
|
|
|
18
18
|
state = await self._graph.ainvoke({"input_messages": input_messages, "memory_id": memory_id})
|
|
19
19
|
return state["response"]
|
|
20
20
|
|
|
21
|
-
async def _invoke_llm_node(self, state: State) -> State:
|
|
21
|
+
async def _invoke_llm_node(self, state: State, second_attempt: bool = False) -> State:
|
|
22
22
|
self._logger.debug("Run node: Invoke LLM")
|
|
23
|
-
|
|
23
|
+
try:
|
|
24
|
+
ai_response = await self._agent.ainvoke({"messages": state.messages})
|
|
25
|
+
except Exception as e:
|
|
26
|
+
self._logger.error(e)
|
|
27
|
+
if second_attempt:
|
|
28
|
+
response = self._response_if_invalid_image if "invalid_image_url" in str(e) else self._response_if_request_fail
|
|
29
|
+
state.messages.append(AIMessage(content=response))
|
|
30
|
+
return state
|
|
31
|
+
return await self._invoke_llm_node(state, second_attempt=True)
|
|
24
32
|
state.messages.append(ai_response)
|
|
25
33
|
return state
|
|
26
34
|
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
class ImageMessageContentBuilder(list):
|
|
2
|
+
def __init__(self, image_url: str, text: str = None):
|
|
3
|
+
content = []
|
|
4
|
+
if isinstance(text, str):
|
|
5
|
+
content.append({
|
|
6
|
+
"type": "text",
|
|
7
|
+
"text": text
|
|
8
|
+
})
|
|
9
|
+
content.append({
|
|
10
|
+
"type": "image_url",
|
|
11
|
+
"image_url": {
|
|
12
|
+
"url": image_url
|
|
13
|
+
}
|
|
14
|
+
})
|
|
15
|
+
super().__init__(content)
|
|
@@ -4,12 +4,33 @@ from pydantic import BaseModel, Field
|
|
|
4
4
|
from langchain_core.messages import BaseMessage
|
|
5
5
|
|
|
6
6
|
|
|
7
|
-
class
|
|
7
|
+
class ImageMessageTextMessage(TypedDict):
|
|
8
|
+
type: Literal['text']
|
|
9
|
+
text: str
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class ImageMessageImageItem(TypedDict):
|
|
13
|
+
type: Literal['image_url']
|
|
14
|
+
image_url: dict
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
ImageMessageContent = list[Union[ImageMessageTextMessage, ImageMessageImageItem]]
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class ImageMessage(TypedDict):
|
|
21
|
+
role: Literal["user"]
|
|
22
|
+
content: ImageMessageContent
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class TextMessage(TypedDict):
|
|
8
26
|
role: Literal["user", "ai"]
|
|
9
27
|
content: str
|
|
10
28
|
|
|
11
29
|
|
|
30
|
+
Message = Union[TextMessage, ImageMessage]
|
|
31
|
+
|
|
12
32
|
InputMessagesType = list[Union[Message, BaseMessage]]
|
|
33
|
+
|
|
13
34
|
ResponseType = Union[str, list[BaseMessage]]
|
|
14
35
|
|
|
15
36
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: dm-aioaiagent
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.3
|
|
4
4
|
Summary: This is my custom aioaiagent client
|
|
5
5
|
Home-page: https://pypi.org/project/dm-aioaiagent
|
|
6
6
|
Author: dimka4621
|
|
@@ -18,6 +18,7 @@ Requires-Dist: pydantic<3.0.0,>=2.9.2
|
|
|
18
18
|
Requires-Dist: langchain~=0.3.0
|
|
19
19
|
Requires-Dist: langchain-core~=0.3.5
|
|
20
20
|
Requires-Dist: langgraph~=0.2.23
|
|
21
|
+
Requires-Dist: grandalf>=0.8
|
|
21
22
|
Requires-Dist: langchain-community~=0.3.0
|
|
22
23
|
Requires-Dist: langchain-openai~=0.2.0
|
|
23
24
|
|
|
@@ -137,6 +138,34 @@ if __name__ == "__main__":
|
|
|
137
138
|
asyncio.run(main())
|
|
138
139
|
```
|
|
139
140
|
|
|
141
|
+
### Image vision
|
|
142
|
+
|
|
143
|
+
```python
|
|
144
|
+
from dm_aioaiagent import DMAIAgent, ImageMessageContentBuilder
|
|
145
|
+
|
|
146
|
+
def main():
|
|
147
|
+
# create an agent
|
|
148
|
+
ai_agent = DMAIAgent(agent_name="image_vision", model="gpt-4o")
|
|
149
|
+
|
|
150
|
+
# create an image message content
|
|
151
|
+
# NOTE: text argument is optional
|
|
152
|
+
img_content = ImageMessageContentBuilder(image_url="https://your.domain/image",
|
|
153
|
+
text="Hello, what is shown in the photo?")
|
|
154
|
+
|
|
155
|
+
# define the conversation message
|
|
156
|
+
messages = [
|
|
157
|
+
{"role": "user", "content": "Hello!"},
|
|
158
|
+
{"role": "user", "content": img_content},
|
|
159
|
+
]
|
|
160
|
+
|
|
161
|
+
# call an agent
|
|
162
|
+
answer = ai_agent.run(messages)
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
if __name__ == "__main__":
|
|
166
|
+
main()
|
|
167
|
+
```
|
|
168
|
+
|
|
140
169
|
### Set custom logger
|
|
141
170
|
|
|
142
171
|
_If you want set up custom logger_
|
|
@@ -8,7 +8,7 @@ def readme():
|
|
|
8
8
|
|
|
9
9
|
setup(
|
|
10
10
|
name='dm-aioaiagent',
|
|
11
|
-
version='v0.3.
|
|
11
|
+
version='v0.3.3',
|
|
12
12
|
author='dimka4621',
|
|
13
13
|
author_email='mismartconfig@gmail.com',
|
|
14
14
|
description='This is my custom aioaiagent client',
|
|
@@ -23,6 +23,7 @@ setup(
|
|
|
23
23
|
'langchain~=0.3.0',
|
|
24
24
|
'langchain-core~=0.3.5',
|
|
25
25
|
'langgraph~=0.2.23',
|
|
26
|
+
'grandalf>=0.8',
|
|
26
27
|
'langchain-community~=0.3.0',
|
|
27
28
|
'langchain-openai~=0.2.0',
|
|
28
29
|
],
|
|
File without changes
|
|
File without changes
|
|
File without changes
|