rootdriver 0.1.0__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.
rootdriver/__init__.py ADDED
@@ -0,0 +1,32 @@
1
+ __version__ = "0.1.0"
2
+ __author__ = "zimvir"
3
+ __email__ = "zimvir@qq.com"
4
+
5
+
6
+
7
+
8
+
9
+ from .agent import Agent
10
+ from .engine import Engine
11
+ from .conversation import Conversation
12
+ from .llm import LLM
13
+ from .llm.base_adapter import BaseAdapter
14
+ from .llm.adapter import OpenAIAdapter
15
+ from .tool import tool, Tool
16
+ from .types.agent import AgentLLM
17
+ from .types import Message, ToolDefinition, ToolCall
18
+
19
+ __all__ = [
20
+ "Agent",
21
+ "Engine",
22
+ "Conversation",
23
+ "LLM",
24
+ "BaseAdapter",
25
+ "OpenAIAdapter",
26
+ "tool",
27
+ "Tool",
28
+ "AgentLLM",
29
+ "Message",
30
+ "ToolDefinition",
31
+ "ToolCall",
32
+ ]
rootdriver/agent.py ADDED
@@ -0,0 +1,48 @@
1
+ from pathlib import Path
2
+ from uuid import uuid4
3
+
4
+ from .engine import Engine
5
+ from .llm import LLM
6
+ from .conversation import Conversation
7
+ from .tool import Tool, BaseTool
8
+ from .types.agent import AgentLLM
9
+ from .types import ToolDefinition
10
+ from .utils import build_system_message, build_message, build_tool_message, build_user_message, build_assistant_message
11
+
12
+ class Agent:
13
+
14
+ def __init__(
15
+ self,
16
+ agent_llm: AgentLLM,
17
+ *,
18
+ tools: list[BaseTool] | None = None,
19
+ system_prompt: str | None = None,
20
+ id: str | None = None,
21
+ # save_path: str | Path | None = None,
22
+ # max_retries: int = 3,
23
+ timeout: float | None = None,
24
+ ):
25
+ self.conversation = Conversation(system_prompt)
26
+ self.tool = Tool(tools if tools else [])
27
+ self.id = id if id else uuid4().hex
28
+ # self.save_path = save_path
29
+
30
+ self.engine = Engine(
31
+ model=agent_llm.model,
32
+ llm=LLM(agent_llm.adapter),
33
+ conversation=self.conversation,
34
+ tool=self.tool,
35
+ )
36
+
37
+
38
+ def react(self, input_prompt:str) -> "str":
39
+ """一次 react 循环"""
40
+ response = self.engine.run(build_user_message(input_prompt))
41
+ return response.content
42
+
43
+ def talk(self, input_prompt:str) -> "str":
44
+ """一次 agent 调用"""
45
+ return self.engine.invoke(build_user_message(input_prompt)).content
46
+
47
+
48
+
@@ -0,0 +1,2 @@
1
+ ROLE_ENUM = ("system", "user", "assistant", "tool")
2
+
@@ -0,0 +1,72 @@
1
+ from .types import Message
2
+ from .utils import get_iso_timestamp, build_system_message
3
+
4
+
5
+ class Conversation:
6
+ def __init__(self, system_prompt: str = None):
7
+ self.messages: list[Message] = []
8
+ self.system_prompt = system_prompt
9
+ if self.system_prompt:
10
+ self.append(build_system_message(system_prompt))
11
+
12
+ def append(self, message: Message) -> "Conversation":
13
+ self.messages.append(message)
14
+ return self
15
+
16
+ def append_many(self, messages: list[Message]) -> "Conversation":
17
+ self.messages.extend(messages)
18
+ return self
19
+
20
+ # def append_user(self, content: str) -> "Conversation":
21
+ # self.messages.append(Message(role="user", content=content, created_at=get_iso_timestamp()))
22
+ # return self
23
+ #
24
+ # def append_assistant(self, content: str | None = None, tool_calls: list | None = None) -> "Conversation":
25
+ # msg = Message(role="assistant", content=content, created_at=get_iso_timestamp())
26
+ # if tool_calls:
27
+ # msg.tool_calls = tool_calls
28
+ # self.messages.append(msg)
29
+ # return self
30
+ #
31
+ # def append_tool(self, tool_call_id: str, content: str) -> "Conversation":
32
+ # self.messages.append(Message(
33
+ # role="tool",
34
+ # tool_call_id=tool_call_id,
35
+ # content=content,
36
+ # created_at=get_iso_timestamp()
37
+ # ))
38
+ # return self
39
+
40
+ def append_system(self, content: str) -> "Conversation":
41
+ self.messages.append(Message(role="system", content=content, created_at=get_iso_timestamp()))
42
+ return self
43
+
44
+ def delete(self, index: int=-1) -> "Conversation":
45
+ self.messages.pop(index)
46
+ return self
47
+
48
+ def get_messages(self) -> list[Message]:
49
+ '''返回 list[message<obj>]'''
50
+ return self.messages
51
+
52
+ def get_messages_in_list(self) -> list[dict]:
53
+ '''返回 字典加列表组成的message(可转成json用于网络、跨语言传输) 组成的列表'''
54
+ return [m.model_dump(exclude_none=True) for m in self.messages]
55
+
56
+
57
+ @classmethod
58
+ def from_dict_list(cls, messages: list[dict]) -> "Conversation":
59
+ conv = cls()
60
+ conv.messages = [Message.model_validate(m) for m in messages]
61
+ return conv
62
+
63
+ @classmethod
64
+ def from_list(cls, messages: list[Message]) -> "Conversation":
65
+ conv = cls()
66
+ conv.messages = list(messages)
67
+ return conv
68
+
69
+ def clear(self) -> "Conversation":
70
+ self.messages = []
71
+ return self
72
+
rootdriver/engine.py ADDED
@@ -0,0 +1,108 @@
1
+
2
+
3
+ from .llm import LLM
4
+ from .conversation import Conversation
5
+ from .tool import Tool
6
+ from .types import LLMRequest, Message
7
+ from .utils import get_iso_timestamp,build_tool_message, build_message
8
+
9
+ class Engine:
10
+ def __init__(self, model:str, llm:LLM, conversation:Conversation, tool:Tool, ):
11
+ self.llm = llm
12
+ self.conversation = conversation
13
+ self.tool = tool
14
+ self.model = model
15
+
16
+ def invoke(self, input_message:Message) -> Message:
17
+ self.conversation.append(input_message)
18
+ message = self.chat()
19
+ return message
20
+
21
+ def chat(self) -> Message:
22
+ """
23
+
24
+ 1. 读会话消息
25
+ 2. 大模型交流
26
+ 3. 追加会话消息
27
+ 4. 判断 是否调用工具
28
+ 5. 是: tool 返回结果并追加,否: 追加并返回
29
+ """
30
+ # 1. 读会话消息
31
+ message = self.conversation.get_messages()
32
+
33
+ # 2. llm交互
34
+ response = self.llm.invoke(self.messages_to_llm_request(message))
35
+
36
+ # 3. 追加会话消息
37
+ response_message = self.llm_response_to_message(response)
38
+ self.conversation.append(response_message)
39
+
40
+ return response_message
41
+
42
+ def deal_tool_or_output(self, response_message:Message) -> Message|None:
43
+ """
44
+ 1. 追加输入
45
+ 2. 读会话消息
46
+ 3. 大模型交流
47
+ 4. 追加会话消息
48
+ 5. 判断 是否调用工具
49
+ 6. 是: tool 返回结果并追加,否: 追加并返回
50
+
51
+
52
+ Returns:
53
+
54
+ """
55
+
56
+ # 5. 判断 是否调用工具
57
+ if response_message.tool_calls:
58
+ # 6. 是: tool 返回结果追加
59
+ for tool_call in response_message.tool_calls:
60
+ tool_result = self.tool.invoke(tool_call)
61
+ self.conversation.append(build_tool_message(tool_result.tool_call_id, tool_result.content))
62
+ return None
63
+ else:
64
+ # 6. 否: 追加并返回
65
+ return response_message
66
+
67
+
68
+ def run(self, input_message:Message) ->Message:
69
+ """
70
+ 1. 追加输入
71
+ 2. 读会话消息
72
+ 3. 大模型交流
73
+ 4. 追加会话消息
74
+ 5. 判断 是否调用工具
75
+ 6. 是: tool 返回结果并追加,否: 追加并返回
76
+
77
+
78
+ Returns:
79
+
80
+ """
81
+ self.conversation.append(input_message)
82
+ while True:
83
+
84
+ response_message = self.chat()
85
+ result = self.deal_tool_or_output(response_message)
86
+ if result is None:
87
+ continue
88
+ elif isinstance(result, Message):
89
+ return result
90
+
91
+
92
+
93
+
94
+
95
+
96
+
97
+
98
+ def messages_to_llm_request(self,messages:list[Message]) -> LLMRequest:
99
+ return LLMRequest(
100
+ model=self.model,
101
+ messages=messages,
102
+ tools=self.tool.to_definitions(),
103
+ )
104
+
105
+ def llm_response_to_message(self, response) -> Message:
106
+ """把 LLM 响应转成 Message 。"""
107
+ return response.message
108
+
@@ -0,0 +1 @@
1
+
@@ -0,0 +1,102 @@
1
+ Metadata-Version: 2.4
2
+ Name: rootdriver
3
+ Version: 0.1.0
4
+ Summary: Rooted in Origin, Driving All Things
5
+ Author-email: zimvir <zimvir@qq.com>
6
+ License: MIT
7
+ Requires-Python: >=3.10
8
+ Description-Content-Type: text/markdown
9
+ Requires-Dist: openai>=1.0.0
10
+ Requires-Dist: pydantic>=2.0.0
11
+ Provides-Extra: dev
12
+ Requires-Dist: pytest>=7.0.0; extra == "dev"
13
+
14
+ # RootDriver
15
+
16
+ 根源出发, 驱动万物
17
+
18
+ 一个轻量级的 Python AI Agent 开发框架。
19
+
20
+ ## 特性
21
+
22
+ - **简洁易用**:装饰器方式定义工具,快速构建 Agent
23
+ - **模块化设计**:LLM 适配器、工具系统、会话管理解耦
24
+ - **工具调用**:支持 function calling,自动执行工具并返回结果
25
+ - **多适配器**:基于适配器模式,方便扩展其他 LLM Provider
26
+
27
+ ## 安装
28
+
29
+ ```bash
30
+ pip install rootdriver
31
+ ```
32
+
33
+ ## 快速开始
34
+
35
+ ### 定义工具
36
+
37
+ ```python
38
+ from rootdriver import tool
39
+
40
+ @tool
41
+ def get_weather(city: str) -> str:
42
+ """获取城市天气"""
43
+ return f"{city} 晴天"
44
+ ```
45
+
46
+ ### 创建 Agent
47
+
48
+ ```python
49
+ from rootdriver import Agent, AgentLLM, OpenAIAdapter
50
+ agent_llm=AgentLLM(
51
+ adapter=OpenAIAdapter(
52
+ api_key="YOUR_API_KEY",
53
+ base_url="BASE_URL"
54
+ ),
55
+ model="gpt-4",
56
+
57
+ ),
58
+ agent = Agent(
59
+ agent_llm=agent_llm,
60
+ tools=[get_weather],
61
+ system_prompt="你是一个有用的助手",
62
+ )
63
+
64
+ # 单次对话
65
+ response = agent.talk("北京天气怎么样?")
66
+ print(response)
67
+ ```
68
+
69
+ ### 使用工具
70
+
71
+ ```python
72
+ # 完整对话循环(包含工具调用)
73
+ response = Agent.react("帮我查下上海天气")
74
+ print(response)
75
+ ```
76
+
77
+ ## 核心组件
78
+
79
+ | 组件 | 说明 |
80
+ |------|------|
81
+ | `Agent` | 智能体入口,整合 LLM、工具、会话 |
82
+ | `Engine` | 核心引擎,处理对话循环和工具调用 |
83
+ | `Conversation` | 会话管理,维护消息历史 |
84
+ | `LLM` | LLM 调用封装 |
85
+ | `Tool` | 工具集合,管理所有可调用工具 |
86
+
87
+ ## 项目结构
88
+
89
+ ```
90
+ rootdriver/
91
+ ├── agent.py # Agent 智能体
92
+ ├── engine.py # 引擎核心
93
+ ├── conversation.py # 对话管理
94
+ ├── llm/ # LLM 适配器
95
+ ├── tool/ # 工具系统
96
+ ├── types/ # 类型定义
97
+ └── utils/ # 工具函数
98
+ ```
99
+
100
+ ## License
101
+
102
+ MIT
@@ -0,0 +1,10 @@
1
+ rootdriver/__init__.py,sha256=E7fG0npdGMr935XTHf0ByQbphNxQTW-nfWx6L0bXXFg,622
2
+ rootdriver/agent.py,sha256=WDj0uc8Xt_KXwhOz3oyQwUSpmaIOrmAqEwHcyhGDiOQ,1454
3
+ rootdriver/constants.py,sha256=btldAAsVhgJwj9zmk0E0WP-q26ydyEYQNSUkrXVfgb0,55
4
+ rootdriver/conversation.py,sha256=_9lpx8K3ay32YI-vEf1ILfOaXgBPMCxRLmspYGbCEZE,2581
5
+ rootdriver/engine.py,sha256=D-6CjvykK8V0Ppo7b3EP2VLIeh3GrtKd9a5ipOABK90,3155
6
+ rootdriver/exception.py,sha256=frcCV1k9oG9oKj3dpUqdJg1PxRT2RSN_XKdLCPjaYaY,2
7
+ rootdriver-0.1.0.dist-info/METADATA,sha256=YryuokUY6_huJ7r5tdhfccd7z8qtswijmSYwli96dow,2333
8
+ rootdriver-0.1.0.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
9
+ rootdriver-0.1.0.dist-info/top_level.txt,sha256=m8YK68IRM5Pzia9feIdOJkfBXPEjVzA_KUTawqeA1us,11
10
+ rootdriver-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (82.0.1)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1 @@
1
+ rootdriver