dm-aioaiagent 0.2.0__tar.gz → 0.3.1__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: dm-aioaiagent
3
- Version: 0.2.0
3
+ Version: 0.3.1
4
4
  Summary: This is my custom aioaiagent client
5
5
  Home-page: https://pypi.org/project/dm-aioaiagent
6
6
  Author: dimka4621
@@ -12,14 +12,14 @@ Classifier: License :: OSI Approved :: MIT License
12
12
  Classifier: Operating System :: OS Independent
13
13
  Requires-Python: >=3.9
14
14
  Description-Content-Type: text/markdown
15
- Requires-Dist: dm-logger==0.5.2
16
- Requires-Dist: python-dotenv==1.0.1
17
- Requires-Dist: pydantic==2.9.2
18
- Requires-Dist: langchain==0.3.0
19
- Requires-Dist: langchain-core==0.3.5
20
- Requires-Dist: langgraph==0.2.23
21
- Requires-Dist: langchain-community==0.3.0
22
- Requires-Dist: langchain-openai==0.2.0
15
+ Requires-Dist: dm-logger~=0.5.2
16
+ Requires-Dist: python-dotenv>=1.0.0
17
+ Requires-Dist: pydantic<3.0.0,>=2.9.2
18
+ Requires-Dist: langchain~=0.3.0
19
+ Requires-Dist: langchain-core~=0.3.5
20
+ Requires-Dist: langgraph~=0.2.23
21
+ Requires-Dist: langchain-community~=0.3.0
22
+ Requires-Dist: langchain-openai~=0.2.0
23
23
 
24
24
  # DM-aioaiagent
25
25
 
@@ -34,6 +34,12 @@ Requires-Dist: langchain-openai==0.2.0
34
34
 
35
35
  Analogue to `DMAioAIAgent` is the synchronous client `DMAIAgent`.
36
36
 
37
+ ### Use agent *with* inner memory
38
+
39
+ By default, agent use inner memory to store the conversation history.
40
+
41
+ (You can set *max count messages in memory* by `max_memory_messages` init argument)
42
+
37
43
  ```python
38
44
  import asyncio
39
45
  from dm_aioaiagent import DMAioAIAgent
@@ -52,24 +58,40 @@ async def main():
52
58
  # create an agent
53
59
  ai_agent = DMAioAIAgent(system_message, tools, model=model_name)
54
60
  # if you don't want to see the input and output messages from agent
55
- # you can set input_output_logging=False
61
+ # you can set `input_output_logging=False` init argument
56
62
 
57
- # define the conversation messages
58
- messages = [
59
- {"role": "user", "content": "Hello!"},
60
- {"role": "ai", "content": "How can I help you?"},
61
- {"role": "user", "content": "I want to know the weather in Kyiv"},
63
+ # define the conversation message
64
+ input_messages = [
65
+ {"role": "user", "content": "Hello!"},
66
+ ]
67
+
68
+ # call an agent
69
+ # specify `memory_id` argument to store the conversation history by your custom id
70
+ answer = await ai_agent.run(input_messages)
71
+
72
+ # define the next conversation message
73
+ input_messages = [
74
+ {"role": "user", "content": "I want to know the weather in Kyiv"}
62
75
  ]
63
76
 
64
77
  # call an agent
65
- answer = await ai_agent.run(messages)
78
+ answer = await ai_agent.run(input_messages)
79
+
80
+ # get full conversation history
81
+ conversation_history = ai_agent.get_memory_messages()
82
+
83
+ # clear conversation history
84
+ ai_agent.clear_memory()
66
85
 
67
86
 
68
87
  if __name__ == "__main__":
69
88
  asyncio.run(main())
70
89
  ```
71
90
 
72
- ### Return context of the tools with answer
91
+ ### Use agent *without* inner memory
92
+
93
+ If you want to control the memory of the agent, you can disable it by setting `is_memory_enabled=False`
94
+
73
95
  ```python
74
96
  import asyncio
75
97
  from dm_aioaiagent import DMAioAIAgent
@@ -79,25 +101,36 @@ async def main():
79
101
  # define a system message
80
102
  system_message = "Your custom system message with role, backstory and goal"
81
103
 
82
- # define a list of tools, if you want to use them
104
+ # (optional) define a list of tools, if you want to use them
83
105
  tools = [...]
84
106
 
107
+ # define a openai model, default is "gpt-4o-mini"
108
+ model_name = "gpt-4o"
109
+
85
110
  # create an agent
86
- ai_agent = DMAioAIAgent(system_message, tools, return_context=True)
111
+ ai_agent = DMAioAIAgent(system_message, tools, model=model_name,
112
+ is_memory_enabled=False)
113
+ # if you don't want to see the input and output messages from agent
114
+ # you can set input_output_logging=False
87
115
 
88
- # define the conversation messages
116
+ # define the conversation message
89
117
  messages = [
90
- {"role": "user", "content": "Hello!"},
91
- {"role": "ai", "content": "How can I help you?"},
92
- {"role": "user", "content": "I want to know the weather in Kyiv"},
118
+ {"role": "user", "content": "Hello!"}
93
119
  ]
94
120
 
95
- # start the agent
96
- state = await ai_agent.run(messages)
121
+ # call an agent
122
+ new_messages = await ai_agent.run(messages)
123
+
124
+ # add new_messages to messages
125
+ messages.extend(new_messages)
97
126
 
98
- # if you define tools, you can see the context of the tools
99
- answer = state["answer"]
100
- context = state["context"]
127
+ # define the next conversation message
128
+ messages.append(
129
+ {"role": "user", "content": "I want to know the weather in Kyiv"}
130
+ )
131
+
132
+ # call an agent
133
+ new_messages = await ai_agent.run(messages)
101
134
 
102
135
 
103
136
  if __name__ == "__main__":
@@ -0,0 +1,145 @@
1
+ # DM-aioaiagent
2
+
3
+ ## Urls
4
+
5
+ * [PyPI](https://pypi.org/project/dm-aioaiagent)
6
+ * [GitHub](https://github.com/MykhLibs/dm-aioaiagent)
7
+
8
+ ### * Package contains both `asynchronous` and `synchronous` clients
9
+
10
+ ## Usage
11
+
12
+ Analogue to `DMAioAIAgent` is the synchronous client `DMAIAgent`.
13
+
14
+ ### Use agent *with* inner memory
15
+
16
+ By default, agent use inner memory to store the conversation history.
17
+
18
+ (You can set *max count messages in memory* by `max_memory_messages` init argument)
19
+
20
+ ```python
21
+ import asyncio
22
+ from dm_aioaiagent import DMAioAIAgent
23
+
24
+
25
+ async def main():
26
+ # define a system message
27
+ system_message = "Your custom system message with role, backstory and goal"
28
+
29
+ # (optional) define a list of tools, if you want to use them
30
+ tools = [...]
31
+
32
+ # define a openai model, default is "gpt-4o-mini"
33
+ model_name = "gpt-4o"
34
+
35
+ # create an agent
36
+ ai_agent = DMAioAIAgent(system_message, tools, model=model_name)
37
+ # if you don't want to see the input and output messages from agent
38
+ # you can set `input_output_logging=False` init argument
39
+
40
+ # define the conversation message
41
+ input_messages = [
42
+ {"role": "user", "content": "Hello!"},
43
+ ]
44
+
45
+ # call an agent
46
+ # specify `memory_id` argument to store the conversation history by your custom id
47
+ answer = await ai_agent.run(input_messages)
48
+
49
+ # define the next conversation message
50
+ input_messages = [
51
+ {"role": "user", "content": "I want to know the weather in Kyiv"}
52
+ ]
53
+
54
+ # call an agent
55
+ answer = await ai_agent.run(input_messages)
56
+
57
+ # get full conversation history
58
+ conversation_history = ai_agent.get_memory_messages()
59
+
60
+ # clear conversation history
61
+ ai_agent.clear_memory()
62
+
63
+
64
+ if __name__ == "__main__":
65
+ asyncio.run(main())
66
+ ```
67
+
68
+ ### Use agent *without* inner memory
69
+
70
+ If you want to control the memory of the agent, you can disable it by setting `is_memory_enabled=False`
71
+
72
+ ```python
73
+ import asyncio
74
+ from dm_aioaiagent import DMAioAIAgent
75
+
76
+
77
+ async def main():
78
+ # define a system message
79
+ system_message = "Your custom system message with role, backstory and goal"
80
+
81
+ # (optional) define a list of tools, if you want to use them
82
+ tools = [...]
83
+
84
+ # define a openai model, default is "gpt-4o-mini"
85
+ model_name = "gpt-4o"
86
+
87
+ # create an agent
88
+ ai_agent = DMAioAIAgent(system_message, tools, model=model_name,
89
+ is_memory_enabled=False)
90
+ # if you don't want to see the input and output messages from agent
91
+ # you can set input_output_logging=False
92
+
93
+ # define the conversation message
94
+ messages = [
95
+ {"role": "user", "content": "Hello!"}
96
+ ]
97
+
98
+ # call an agent
99
+ new_messages = await ai_agent.run(messages)
100
+
101
+ # add new_messages to messages
102
+ messages.extend(new_messages)
103
+
104
+ # define the next conversation message
105
+ messages.append(
106
+ {"role": "user", "content": "I want to know the weather in Kyiv"}
107
+ )
108
+
109
+ # call an agent
110
+ new_messages = await ai_agent.run(messages)
111
+
112
+
113
+ if __name__ == "__main__":
114
+ asyncio.run(main())
115
+ ```
116
+
117
+ ### Set custom logger
118
+
119
+ _If you want set up custom logger_
120
+
121
+ ```python
122
+ from dm_aioaiagent import DMAioAIAgent
123
+
124
+
125
+ # create custom logger
126
+ class MyLogger:
127
+ def debug(self, message):
128
+ pass
129
+
130
+ def info(self, message):
131
+ pass
132
+
133
+ def warning(self, message):
134
+ print(message)
135
+
136
+ def error(self, message):
137
+ print(message)
138
+
139
+
140
+ # create an agent
141
+ ai_agent = DMAioAIAgent()
142
+
143
+ # set up custom logger for this agent
144
+ ai_agent.set_logger(MyLogger())
145
+ ```
@@ -2,3 +2,4 @@ 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 .types import Message
@@ -1,42 +1,22 @@
1
- import json
2
1
  import os
3
- from typing import Optional, Literal, Union
4
- from typing_extensions import TypedDict
5
- from pydantic import BaseModel, Field
2
+ from itertools import dropwhile
6
3
  from threading import Thread
7
4
  from langchain_openai import ChatOpenAI
8
5
  from langchain_core.tools import BaseTool
9
6
  from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
10
- from langchain_core.messages import BaseMessage, SystemMessage, HumanMessage, AIMessage, ToolMessage
7
+ from langchain_core.messages import SystemMessage, HumanMessage, AIMessage, ToolMessage
11
8
  from langgraph.graph import StateGraph
12
9
  from dm_logger import DMLogger
13
10
 
14
- __all__ = ["DMAIAgent"]
15
-
16
-
17
- class Message(TypedDict):
18
- role: Literal["user", "ai"]
19
- content: str
20
-
21
-
22
- class InnerState(BaseModel):
23
- messages: list[BaseMessage] = Field(default=[])
24
- context: list[Message] = Field(default=[])
25
-
26
-
27
- class InputState(BaseModel):
28
- messages: list[Message]
29
- inner_state: Optional[InnerState] = Field(default=InnerState())
30
-
11
+ from .types import *
31
12
 
32
- class OutputState(TypedDict):
33
- answer: str
34
- context: list[Message]
13
+ __all__ = ["DMAIAgent"]
35
14
 
36
15
 
37
16
  class DMAIAgent:
38
17
  agent_name = "AIAgent"
39
18
  _allowed_roles = ("user", "ai")
19
+ MAX_MEMORY_MESSAGES = 20 # Only INT greater than 0
40
20
 
41
21
  def __init__(
42
22
  self,
@@ -47,15 +27,17 @@ class DMAIAgent:
47
27
  temperature: int = 1,
48
28
  agent_name: str = None,
49
29
  input_output_logging: bool = True,
50
- return_context: bool = False
30
+ is_memory_enabled: bool = True,
31
+ max_memory_messages: int = None,
51
32
  ):
52
33
  if not os.getenv("OPENAI_API_KEY"):
53
- raise EnvironmentError("OPENAI_API_KEY environment variable is not set!")
34
+ raise EnvironmentError("'OPENAI_API_KEY' environment variable is not set!")
54
35
 
55
36
  self._logger = DMLogger(agent_name or self.agent_name)
56
- self._input_output_logging = input_output_logging
57
- self._return_context = return_context
58
37
  self._is_tools_exists = bool(tools)
38
+ self._input_output_logging = bool(input_output_logging)
39
+ self._is_memory_enabled = bool(is_memory_enabled)
40
+ self._max_memory_messages = self._validate_max_memory_messages(max_memory_messages)
59
41
 
60
42
  prompt = ChatPromptTemplate.from_messages([SystemMessage(content=system_message),
61
43
  MessagesPlaceholder(variable_name="messages")])
@@ -64,8 +46,9 @@ class DMAIAgent:
64
46
  self._tool_map = {t.name: t for t in tools}
65
47
  llm = llm.bind_tools(tools)
66
48
  self._agent = prompt | llm
49
+ self._memory = {}
67
50
 
68
- workflow = StateGraph(input=InputState, output=OutputState)
51
+ workflow = StateGraph(State)
69
52
  workflow.add_node("Prepare messages", self._prepare_messages_node)
70
53
  workflow.add_node("Invoke LLM", self._invoke_llm_node)
71
54
  workflow.add_node("Execute tool", self._execute_tool_node)
@@ -80,40 +63,49 @@ class DMAIAgent:
80
63
  workflow.set_finish_point("Exit")
81
64
  self._graph = workflow.compile()
82
65
 
83
- def run(self, messages: list[Message]) -> Union[str, OutputState]:
84
- state = self._graph.invoke({"messages": messages})
85
- if self._return_context:
86
- return state
87
- return state["answer"]
66
+ def run(self, input_messages: InputMessagesType, memory_id: str = None) -> ResponseType:
67
+ state = self._graph.invoke({"input_messages": input_messages, "memory_id": memory_id})
68
+ return state["response"]
69
+
70
+ def get_memory_messages(self, memory_id: str = None) -> list[BaseMessage]:
71
+ return self._memory.get(self._validate_memory_id(memory_id), [])
72
+
73
+ def clear_memory(self, memory_id: str = None) -> None:
74
+ self._memory[self._validate_memory_id(memory_id)] = []
75
+
76
+ def _prepare_messages_node(self, state: State) -> State:
77
+ state.memory_id = self._validate_memory_id(state.memory_id)
78
+ state.input_messages = state.input_messages or [{"role": "user", "content": ""}]
79
+ for item in state.input_messages:
80
+ if isinstance(item, dict):
81
+ role = item.get("role")
82
+ content = item.get("content")
83
+ if not role or role not in self._allowed_roles or not content:
84
+ continue
85
+ if role == "ai":
86
+ MessageClass = AIMessage
87
+ else:
88
+ MessageClass = HumanMessage
89
+ state.messages.append(MessageClass(content))
90
+ elif isinstance(item, BaseMessage):
91
+ state.messages.append(item)
88
92
 
89
- def _prepare_messages_node(self, state: InputState) -> InputState:
90
- state.messages = state.messages or [{"role": "user", "content": "Привіт"}]
91
- state.inner_state = InnerState()
92
93
  if self._input_output_logging:
93
- self._logger.debug(input_messages=state.messages)
94
-
95
- for item in state.messages:
96
- role = item.get("role")
97
- content = item.get("content")
98
- if not role or role not in self._allowed_roles or not content:
99
- continue
100
- if role == "ai":
101
- MessageClass = AIMessage
102
- else:
103
- MessageClass = HumanMessage
104
- state.inner_state.messages.append(MessageClass(content))
94
+ self._logger.debug(f"Query:\n{state.messages[-1].content}", memory_id=state.memory_id)
95
+ if self._is_memory_enabled:
96
+ state.messages = self.get_memory_messages(state.memory_id) + state.messages
105
97
  return state
106
98
 
107
- def _invoke_llm_node(self, state: InputState) -> InputState:
99
+ def _invoke_llm_node(self, state: State) -> State:
108
100
  self._logger.debug("Run node: Invoke LLM")
109
- ai_response = self._agent.invoke({"messages": state.inner_state.messages})
110
- state.inner_state.messages.append(ai_response)
101
+ ai_response = self._agent.invoke({"messages": state.messages})
102
+ state.messages.append(ai_response)
111
103
  return state
112
104
 
113
- def _execute_tool_node(self, state: InputState) -> InputState:
105
+ def _execute_tool_node(self, state: State) -> State:
114
106
  self._logger.debug("Run node: Execute tool")
115
107
  threads = []
116
- for tool_call in state.inner_state.messages[-1].tool_calls:
108
+ for tool_call in state.messages[-1].tool_calls:
117
109
  tool_id = tool_call["id"]
118
110
  tool_name = tool_call["name"]
119
111
  tool_args = tool_call["args"]
@@ -130,11 +122,8 @@ class DMAIAgent:
130
122
  tool_response = f"Tool not found!"
131
123
  self._logger.debug(f"Tool response:\n{tool_response}", tool_id=tool_id)
132
124
 
133
- state.inner_state.context.append({"tool_name": tool_name,
134
- "tool_args": json.dumps(tool_args, ensure_ascii=False),
135
- "tool_response": tool_response})
136
125
  tool_message = ToolMessage(content=str(tool_response), name=tool_name, tool_call_id=tool_id)
137
- state.inner_state.messages.append(tool_message)
126
+ state.messages.append(tool_message)
138
127
 
139
128
  threads.append(Thread(target=tool_callback, daemon=True))
140
129
 
@@ -145,19 +134,37 @@ class DMAIAgent:
145
134
 
146
135
  return state
147
136
 
148
- def _exit_node(self, state: InputState) -> OutputState:
149
- answer = state.inner_state.messages[-1].content if state.inner_state.messages else ""
137
+ def _exit_node(self, state: State) -> State:
138
+ answer = state.messages[-1].content
150
139
  if self._input_output_logging:
151
- self._logger.debug(f"Answer:\n{answer}")
152
- return OutputState(answer=answer, context=state.inner_state.context)
140
+ self._logger.debug(f"Answer:\n{answer}", memory_id=state.memory_id)
153
141
 
154
- def _messages_router(self, state: InputState) -> str:
155
- if self._is_tools_exists and state.inner_state.messages[-1].tool_calls:
142
+ if self._is_memory_enabled:
143
+ messages_to_memory = state.messages[-self._max_memory_messages:]
144
+ # drop ToolsMessages from start of list
145
+ self._memory[state.memory_id] = list(dropwhile(lambda x: isinstance(x, ToolMessage), messages_to_memory))
146
+ state.response = answer
147
+ else:
148
+ state.response = state.messages[len(state.input_messages):]
149
+ return state
150
+
151
+ def _messages_router(self, state: State) -> str:
152
+ if self._is_tools_exists and state.messages[-1].tool_calls:
156
153
  route = "execute_tool"
157
154
  else:
158
155
  route = "exit"
159
156
  return route
160
157
 
158
+ @staticmethod
159
+ def _validate_memory_id(memory_id: Union[str, None]) -> Union[str, int]:
160
+ return str(memory_id) if memory_id else 0
161
+
162
+ @classmethod
163
+ def _validate_max_memory_messages(cls, max_messages_in_memory: int) -> int:
164
+ if isinstance(max_messages_in_memory, int) and max_messages_in_memory > 0:
165
+ return max_messages_in_memory
166
+ return cls.MAX_MEMORY_MESSAGES
167
+
161
168
  def print_graph(self) -> None:
162
169
  self._graph.get_graph().print_ascii()
163
170
 
@@ -1,10 +1,9 @@
1
- import json
2
1
  import sys
3
2
  import asyncio
4
- from typing import Union
5
3
  from langchain_core.messages import ToolMessage
6
4
 
7
- from .ai_agent import DMAIAgent, InputState, OutputState, Message
5
+ from .ai_agent import DMAIAgent
6
+ from .types import *
8
7
 
9
8
  if sys.platform == "win32":
10
9
  asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
@@ -15,22 +14,20 @@ __all__ = ["DMAioAIAgent"]
15
14
  class DMAioAIAgent(DMAIAgent):
16
15
  agent_name = "AsyncAIAgent"
17
16
 
18
- async def run(self, messages: list[Message]) -> Union[str, OutputState]:
19
- state = await self._graph.ainvoke({"messages": messages})
20
- if self._return_context:
21
- return state
22
- return state["answer"]
17
+ async def run(self, input_messages: InputMessagesType, memory_id: str = None) -> ResponseType:
18
+ state = await self._graph.ainvoke({"input_messages": input_messages, "memory_id": memory_id})
19
+ return state["response"]
23
20
 
24
- async def _invoke_llm_node(self, state: InputState) -> InputState:
21
+ async def _invoke_llm_node(self, state: State) -> State:
25
22
  self._logger.debug("Run node: Invoke LLM")
26
- ai_response = await self._agent.ainvoke({"messages": state.inner_state.messages})
27
- state.inner_state.messages.append(ai_response)
23
+ ai_response = await self._agent.ainvoke({"messages": state.messages})
24
+ state.messages.append(ai_response)
28
25
  return state
29
26
 
30
- async def _execute_tool_node(self, state: InputState) -> InputState:
27
+ async def _execute_tool_node(self, state: State) -> State:
31
28
  self._logger.debug("Run node: Execute tool")
32
29
  tasks = []
33
- for tool_call in state.inner_state.messages[-1].tool_calls:
30
+ for tool_call in state.messages[-1].tool_calls:
34
31
  tool_id = tool_call["id"]
35
32
  tool_name = tool_call["name"]
36
33
  tool_args = tool_call["args"]
@@ -47,11 +44,8 @@ class DMAioAIAgent(DMAIAgent):
47
44
  tool_response = f"Tool '{tool_name}' not found!"
48
45
  self._logger.debug(f"Tool response:\n{tool_response}", tool_id=tool_id)
49
46
 
50
- state.inner_state.context.append({"tool_name": tool_name,
51
- "tool_args": json.dumps(tool_args, ensure_ascii=False),
52
- "tool_response": tool_response})
53
47
  tool_message = ToolMessage(content=str(tool_response), name=tool_name, tool_call_id=tool_id)
54
- state.inner_state.messages.append(tool_message)
48
+ state.messages.append(tool_message)
55
49
 
56
50
  tasks.append(asyncio.create_task(tool_callback()))
57
51
 
@@ -0,0 +1,20 @@
1
+ from typing import Optional, Literal, Union
2
+ from typing_extensions import TypedDict
3
+ from pydantic import BaseModel, Field
4
+ from langchain_core.messages import BaseMessage
5
+
6
+
7
+ class Message(TypedDict):
8
+ role: Literal["user", "ai"]
9
+ content: str
10
+
11
+
12
+ InputMessagesType = list[Union[Message, BaseMessage]]
13
+ ResponseType = Union[str, list[BaseMessage]]
14
+
15
+
16
+ class State(BaseModel):
17
+ input_messages: InputMessagesType
18
+ memory_id: Union[str, int, None] = Field(default=0)
19
+ messages: Optional[list[BaseMessage]] = Field(default_factory=list)
20
+ response: ResponseType = Field(default="")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: dm-aioaiagent
3
- Version: 0.2.0
3
+ Version: 0.3.1
4
4
  Summary: This is my custom aioaiagent client
5
5
  Home-page: https://pypi.org/project/dm-aioaiagent
6
6
  Author: dimka4621
@@ -12,14 +12,14 @@ Classifier: License :: OSI Approved :: MIT License
12
12
  Classifier: Operating System :: OS Independent
13
13
  Requires-Python: >=3.9
14
14
  Description-Content-Type: text/markdown
15
- Requires-Dist: dm-logger==0.5.2
16
- Requires-Dist: python-dotenv==1.0.1
17
- Requires-Dist: pydantic==2.9.2
18
- Requires-Dist: langchain==0.3.0
19
- Requires-Dist: langchain-core==0.3.5
20
- Requires-Dist: langgraph==0.2.23
21
- Requires-Dist: langchain-community==0.3.0
22
- Requires-Dist: langchain-openai==0.2.0
15
+ Requires-Dist: dm-logger~=0.5.2
16
+ Requires-Dist: python-dotenv>=1.0.0
17
+ Requires-Dist: pydantic<3.0.0,>=2.9.2
18
+ Requires-Dist: langchain~=0.3.0
19
+ Requires-Dist: langchain-core~=0.3.5
20
+ Requires-Dist: langgraph~=0.2.23
21
+ Requires-Dist: langchain-community~=0.3.0
22
+ Requires-Dist: langchain-openai~=0.2.0
23
23
 
24
24
  # DM-aioaiagent
25
25
 
@@ -34,6 +34,12 @@ Requires-Dist: langchain-openai==0.2.0
34
34
 
35
35
  Analogue to `DMAioAIAgent` is the synchronous client `DMAIAgent`.
36
36
 
37
+ ### Use agent *with* inner memory
38
+
39
+ By default, agent use inner memory to store the conversation history.
40
+
41
+ (You can set *max count messages in memory* by `max_memory_messages` init argument)
42
+
37
43
  ```python
38
44
  import asyncio
39
45
  from dm_aioaiagent import DMAioAIAgent
@@ -52,24 +58,40 @@ async def main():
52
58
  # create an agent
53
59
  ai_agent = DMAioAIAgent(system_message, tools, model=model_name)
54
60
  # if you don't want to see the input and output messages from agent
55
- # you can set input_output_logging=False
61
+ # you can set `input_output_logging=False` init argument
56
62
 
57
- # define the conversation messages
58
- messages = [
59
- {"role": "user", "content": "Hello!"},
60
- {"role": "ai", "content": "How can I help you?"},
61
- {"role": "user", "content": "I want to know the weather in Kyiv"},
63
+ # define the conversation message
64
+ input_messages = [
65
+ {"role": "user", "content": "Hello!"},
66
+ ]
67
+
68
+ # call an agent
69
+ # specify `memory_id` argument to store the conversation history by your custom id
70
+ answer = await ai_agent.run(input_messages)
71
+
72
+ # define the next conversation message
73
+ input_messages = [
74
+ {"role": "user", "content": "I want to know the weather in Kyiv"}
62
75
  ]
63
76
 
64
77
  # call an agent
65
- answer = await ai_agent.run(messages)
78
+ answer = await ai_agent.run(input_messages)
79
+
80
+ # get full conversation history
81
+ conversation_history = ai_agent.get_memory_messages()
82
+
83
+ # clear conversation history
84
+ ai_agent.clear_memory()
66
85
 
67
86
 
68
87
  if __name__ == "__main__":
69
88
  asyncio.run(main())
70
89
  ```
71
90
 
72
- ### Return context of the tools with answer
91
+ ### Use agent *without* inner memory
92
+
93
+ If you want to control the memory of the agent, you can disable it by setting `is_memory_enabled=False`
94
+
73
95
  ```python
74
96
  import asyncio
75
97
  from dm_aioaiagent import DMAioAIAgent
@@ -79,25 +101,36 @@ async def main():
79
101
  # define a system message
80
102
  system_message = "Your custom system message with role, backstory and goal"
81
103
 
82
- # define a list of tools, if you want to use them
104
+ # (optional) define a list of tools, if you want to use them
83
105
  tools = [...]
84
106
 
107
+ # define a openai model, default is "gpt-4o-mini"
108
+ model_name = "gpt-4o"
109
+
85
110
  # create an agent
86
- ai_agent = DMAioAIAgent(system_message, tools, return_context=True)
111
+ ai_agent = DMAioAIAgent(system_message, tools, model=model_name,
112
+ is_memory_enabled=False)
113
+ # if you don't want to see the input and output messages from agent
114
+ # you can set input_output_logging=False
87
115
 
88
- # define the conversation messages
116
+ # define the conversation message
89
117
  messages = [
90
- {"role": "user", "content": "Hello!"},
91
- {"role": "ai", "content": "How can I help you?"},
92
- {"role": "user", "content": "I want to know the weather in Kyiv"},
118
+ {"role": "user", "content": "Hello!"}
93
119
  ]
94
120
 
95
- # start the agent
96
- state = await ai_agent.run(messages)
121
+ # call an agent
122
+ new_messages = await ai_agent.run(messages)
123
+
124
+ # add new_messages to messages
125
+ messages.extend(new_messages)
97
126
 
98
- # if you define tools, you can see the context of the tools
99
- answer = state["answer"]
100
- context = state["context"]
127
+ # define the next conversation message
128
+ messages.append(
129
+ {"role": "user", "content": "I want to know the weather in Kyiv"}
130
+ )
131
+
132
+ # call an agent
133
+ new_messages = await ai_agent.run(messages)
101
134
 
102
135
 
103
136
  if __name__ == "__main__":
@@ -4,6 +4,7 @@ setup.py
4
4
  dm_aioaiagent/__init__.py
5
5
  dm_aioaiagent/ai_agent.py
6
6
  dm_aioaiagent/async_ai_agent.py
7
+ dm_aioaiagent/types.py
7
8
  dm_aioaiagent.egg-info/PKG-INFO
8
9
  dm_aioaiagent.egg-info/SOURCES.txt
9
10
  dm_aioaiagent.egg-info/dependency_links.txt
@@ -0,0 +1,8 @@
1
+ dm-logger~=0.5.2
2
+ python-dotenv>=1.0.0
3
+ pydantic<3.0.0,>=2.9.2
4
+ langchain~=0.3.0
5
+ langchain-core~=0.3.5
6
+ langgraph~=0.2.23
7
+ langchain-community~=0.3.0
8
+ langchain-openai~=0.2.0
@@ -8,7 +8,7 @@ def readme():
8
8
 
9
9
  setup(
10
10
  name='dm-aioaiagent',
11
- version='v0.2.0',
11
+ version='v0.3.1',
12
12
  author='dimka4621',
13
13
  author_email='mismartconfig@gmail.com',
14
14
  description='This is my custom aioaiagent client',
@@ -17,14 +17,14 @@ setup(
17
17
  url='https://pypi.org/project/dm-aioaiagent',
18
18
  packages=find_packages(),
19
19
  install_requires=[
20
- 'dm-logger==0.5.2',
21
- 'python-dotenv==1.0.1',
22
- 'pydantic==2.9.2',
23
- 'langchain==0.3.0',
24
- 'langchain-core==0.3.5',
25
- 'langgraph==0.2.23',
26
- 'langchain-community==0.3.0',
27
- 'langchain-openai==0.2.0',
20
+ 'dm-logger~=0.5.2',
21
+ 'python-dotenv>=1.0.0',
22
+ 'pydantic>=2.9.2, < 3.0.0',
23
+ 'langchain~=0.3.0',
24
+ 'langchain-core~=0.3.5',
25
+ 'langgraph~=0.2.23',
26
+ 'langchain-community~=0.3.0',
27
+ 'langchain-openai~=0.2.0',
28
28
  ],
29
29
  classifiers=[
30
30
  'Programming Language :: Python :: 3.8',
@@ -1,112 +0,0 @@
1
- # DM-aioaiagent
2
-
3
- ## Urls
4
-
5
- * [PyPI](https://pypi.org/project/dm-aioaiagent)
6
- * [GitHub](https://github.com/MykhLibs/dm-aioaiagent)
7
-
8
- ### * Package contains both `asynchronous` and `synchronous` clients
9
-
10
- ## Usage
11
-
12
- Analogue to `DMAioAIAgent` is the synchronous client `DMAIAgent`.
13
-
14
- ```python
15
- import asyncio
16
- from dm_aioaiagent import DMAioAIAgent
17
-
18
-
19
- async def main():
20
- # define a system message
21
- system_message = "Your custom system message with role, backstory and goal"
22
-
23
- # (optional) define a list of tools, if you want to use them
24
- tools = [...]
25
-
26
- # define a openai model, default is "gpt-4o-mini"
27
- model_name = "gpt-4o"
28
-
29
- # create an agent
30
- ai_agent = DMAioAIAgent(system_message, tools, model=model_name)
31
- # if you don't want to see the input and output messages from agent
32
- # you can set input_output_logging=False
33
-
34
- # define the conversation messages
35
- messages = [
36
- {"role": "user", "content": "Hello!"},
37
- {"role": "ai", "content": "How can I help you?"},
38
- {"role": "user", "content": "I want to know the weather in Kyiv"},
39
- ]
40
-
41
- # call an agent
42
- answer = await ai_agent.run(messages)
43
-
44
-
45
- if __name__ == "__main__":
46
- asyncio.run(main())
47
- ```
48
-
49
- ### Return context of the tools with answer
50
- ```python
51
- import asyncio
52
- from dm_aioaiagent import DMAioAIAgent
53
-
54
-
55
- async def main():
56
- # define a system message
57
- system_message = "Your custom system message with role, backstory and goal"
58
-
59
- # define a list of tools, if you want to use them
60
- tools = [...]
61
-
62
- # create an agent
63
- ai_agent = DMAioAIAgent(system_message, tools, return_context=True)
64
-
65
- # define the conversation messages
66
- messages = [
67
- {"role": "user", "content": "Hello!"},
68
- {"role": "ai", "content": "How can I help you?"},
69
- {"role": "user", "content": "I want to know the weather in Kyiv"},
70
- ]
71
-
72
- # start the agent
73
- state = await ai_agent.run(messages)
74
-
75
- # if you define tools, you can see the context of the tools
76
- answer = state["answer"]
77
- context = state["context"]
78
-
79
-
80
- if __name__ == "__main__":
81
- asyncio.run(main())
82
- ```
83
-
84
- ### Set custom logger
85
-
86
- _If you want set up custom logger_
87
-
88
- ```python
89
- from dm_aioaiagent import DMAioAIAgent
90
-
91
-
92
- # create custom logger
93
- class MyLogger:
94
- def debug(self, message):
95
- pass
96
-
97
- def info(self, message):
98
- pass
99
-
100
- def warning(self, message):
101
- print(message)
102
-
103
- def error(self, message):
104
- print(message)
105
-
106
-
107
- # create an agent
108
- ai_agent = DMAioAIAgent()
109
-
110
- # set up custom logger for this agent
111
- ai_agent.set_logger(MyLogger())
112
- ```
@@ -1,8 +0,0 @@
1
- dm-logger==0.5.2
2
- python-dotenv==1.0.1
3
- pydantic==2.9.2
4
- langchain==0.3.0
5
- langchain-core==0.3.5
6
- langgraph==0.2.23
7
- langchain-community==0.3.0
8
- langchain-openai==0.2.0
File without changes