agentrun-inner-test 0.0.46__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.
- agentrun/__init__.py +325 -0
- agentrun/agent_runtime/__client_async_template.py +466 -0
- agentrun/agent_runtime/__endpoint_async_template.py +345 -0
- agentrun/agent_runtime/__init__.py +53 -0
- agentrun/agent_runtime/__runtime_async_template.py +477 -0
- agentrun/agent_runtime/api/__data_async_template.py +58 -0
- agentrun/agent_runtime/api/__init__.py +6 -0
- agentrun/agent_runtime/api/control.py +1362 -0
- agentrun/agent_runtime/api/data.py +98 -0
- agentrun/agent_runtime/client.py +868 -0
- agentrun/agent_runtime/endpoint.py +649 -0
- agentrun/agent_runtime/model.py +362 -0
- agentrun/agent_runtime/runtime.py +904 -0
- agentrun/credential/__client_async_template.py +177 -0
- agentrun/credential/__credential_async_template.py +216 -0
- agentrun/credential/__init__.py +28 -0
- agentrun/credential/api/__init__.py +5 -0
- agentrun/credential/api/control.py +606 -0
- agentrun/credential/client.py +319 -0
- agentrun/credential/credential.py +381 -0
- agentrun/credential/model.py +248 -0
- agentrun/integration/__init__.py +21 -0
- agentrun/integration/agentscope/__init__.py +12 -0
- agentrun/integration/agentscope/adapter.py +17 -0
- agentrun/integration/agentscope/builtin.py +65 -0
- agentrun/integration/agentscope/message_adapter.py +185 -0
- agentrun/integration/agentscope/model_adapter.py +60 -0
- agentrun/integration/agentscope/tool_adapter.py +59 -0
- agentrun/integration/builtin/__init__.py +16 -0
- agentrun/integration/builtin/model.py +93 -0
- agentrun/integration/builtin/sandbox.py +1234 -0
- agentrun/integration/builtin/toolset.py +47 -0
- agentrun/integration/crewai/__init__.py +12 -0
- agentrun/integration/crewai/adapter.py +9 -0
- agentrun/integration/crewai/builtin.py +65 -0
- agentrun/integration/crewai/model_adapter.py +31 -0
- agentrun/integration/crewai/tool_adapter.py +26 -0
- agentrun/integration/google_adk/__init__.py +12 -0
- agentrun/integration/google_adk/adapter.py +15 -0
- agentrun/integration/google_adk/builtin.py +65 -0
- agentrun/integration/google_adk/message_adapter.py +144 -0
- agentrun/integration/google_adk/model_adapter.py +46 -0
- agentrun/integration/google_adk/tool_adapter.py +235 -0
- agentrun/integration/langchain/__init__.py +30 -0
- agentrun/integration/langchain/adapter.py +15 -0
- agentrun/integration/langchain/builtin.py +71 -0
- agentrun/integration/langchain/message_adapter.py +141 -0
- agentrun/integration/langchain/model_adapter.py +37 -0
- agentrun/integration/langchain/tool_adapter.py +50 -0
- agentrun/integration/langgraph/__init__.py +35 -0
- agentrun/integration/langgraph/adapter.py +20 -0
- agentrun/integration/langgraph/agent_converter.py +1073 -0
- agentrun/integration/langgraph/builtin.py +65 -0
- agentrun/integration/pydantic_ai/__init__.py +12 -0
- agentrun/integration/pydantic_ai/adapter.py +13 -0
- agentrun/integration/pydantic_ai/builtin.py +65 -0
- agentrun/integration/pydantic_ai/model_adapter.py +44 -0
- agentrun/integration/pydantic_ai/tool_adapter.py +19 -0
- agentrun/integration/utils/__init__.py +112 -0
- agentrun/integration/utils/adapter.py +560 -0
- agentrun/integration/utils/canonical.py +164 -0
- agentrun/integration/utils/converter.py +134 -0
- agentrun/integration/utils/model.py +110 -0
- agentrun/integration/utils/tool.py +1759 -0
- agentrun/model/__client_async_template.py +357 -0
- agentrun/model/__init__.py +57 -0
- agentrun/model/__model_proxy_async_template.py +270 -0
- agentrun/model/__model_service_async_template.py +267 -0
- agentrun/model/api/__init__.py +6 -0
- agentrun/model/api/control.py +1173 -0
- agentrun/model/api/data.py +196 -0
- agentrun/model/client.py +674 -0
- agentrun/model/model.py +235 -0
- agentrun/model/model_proxy.py +439 -0
- agentrun/model/model_service.py +438 -0
- agentrun/sandbox/__aio_sandbox_async_template.py +523 -0
- agentrun/sandbox/__browser_sandbox_async_template.py +110 -0
- agentrun/sandbox/__client_async_template.py +491 -0
- agentrun/sandbox/__code_interpreter_sandbox_async_template.py +463 -0
- agentrun/sandbox/__init__.py +69 -0
- agentrun/sandbox/__sandbox_async_template.py +463 -0
- agentrun/sandbox/__template_async_template.py +152 -0
- agentrun/sandbox/aio_sandbox.py +905 -0
- agentrun/sandbox/api/__aio_data_async_template.py +335 -0
- agentrun/sandbox/api/__browser_data_async_template.py +140 -0
- agentrun/sandbox/api/__code_interpreter_data_async_template.py +206 -0
- agentrun/sandbox/api/__init__.py +19 -0
- agentrun/sandbox/api/__sandbox_data_async_template.py +107 -0
- agentrun/sandbox/api/aio_data.py +551 -0
- agentrun/sandbox/api/browser_data.py +172 -0
- agentrun/sandbox/api/code_interpreter_data.py +396 -0
- agentrun/sandbox/api/control.py +1051 -0
- agentrun/sandbox/api/playwright_async.py +492 -0
- agentrun/sandbox/api/playwright_sync.py +492 -0
- agentrun/sandbox/api/sandbox_data.py +154 -0
- agentrun/sandbox/browser_sandbox.py +185 -0
- agentrun/sandbox/client.py +925 -0
- agentrun/sandbox/code_interpreter_sandbox.py +823 -0
- agentrun/sandbox/model.py +397 -0
- agentrun/sandbox/sandbox.py +848 -0
- agentrun/sandbox/template.py +217 -0
- agentrun/server/__init__.py +191 -0
- agentrun/server/agui_normalizer.py +180 -0
- agentrun/server/agui_protocol.py +797 -0
- agentrun/server/invoker.py +309 -0
- agentrun/server/model.py +427 -0
- agentrun/server/openai_protocol.py +535 -0
- agentrun/server/protocol.py +140 -0
- agentrun/server/server.py +208 -0
- agentrun/toolset/__client_async_template.py +62 -0
- agentrun/toolset/__init__.py +51 -0
- agentrun/toolset/__toolset_async_template.py +204 -0
- agentrun/toolset/api/__init__.py +17 -0
- agentrun/toolset/api/control.py +262 -0
- agentrun/toolset/api/mcp.py +100 -0
- agentrun/toolset/api/openapi.py +1251 -0
- agentrun/toolset/client.py +102 -0
- agentrun/toolset/model.py +321 -0
- agentrun/toolset/toolset.py +270 -0
- agentrun/utils/__data_api_async_template.py +720 -0
- agentrun/utils/__init__.py +5 -0
- agentrun/utils/__resource_async_template.py +158 -0
- agentrun/utils/config.py +258 -0
- agentrun/utils/control_api.py +78 -0
- agentrun/utils/data_api.py +1120 -0
- agentrun/utils/exception.py +151 -0
- agentrun/utils/helper.py +108 -0
- agentrun/utils/log.py +77 -0
- agentrun/utils/model.py +168 -0
- agentrun/utils/resource.py +291 -0
- agentrun_inner_test-0.0.46.dist-info/METADATA +263 -0
- agentrun_inner_test-0.0.46.dist-info/RECORD +135 -0
- agentrun_inner_test-0.0.46.dist-info/WHEEL +5 -0
- agentrun_inner_test-0.0.46.dist-info/licenses/LICENSE +201 -0
- agentrun_inner_test-0.0.46.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
"""Google ADK 工具适配器 / Google ADK Tool Adapter
|
|
2
|
+
|
|
3
|
+
将标准工具定义转换为 Google ADK 函数格式。"""
|
|
4
|
+
|
|
5
|
+
from typing import Any, Dict, List, Optional
|
|
6
|
+
|
|
7
|
+
from agentrun.integration.utils.adapter import ToolAdapter
|
|
8
|
+
from agentrun.integration.utils.canonical import CanonicalTool
|
|
9
|
+
from agentrun.integration.utils.tool import normalize_tool_name
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def _json_schema_to_google_schema(
|
|
13
|
+
schema: Dict[str, Any],
|
|
14
|
+
root_schema: Optional[Dict[str, Any]] = None,
|
|
15
|
+
) -> Any:
|
|
16
|
+
"""将 JSON Schema 转换为 Google ADK Schema
|
|
17
|
+
|
|
18
|
+
Google ADK 不支持 $ref 和 $defs,所以需要内联所有引用。
|
|
19
|
+
|
|
20
|
+
Args:
|
|
21
|
+
schema: JSON Schema 定义
|
|
22
|
+
root_schema: 根 schema,用于解析 $ref 引用
|
|
23
|
+
|
|
24
|
+
Returns:
|
|
25
|
+
Google ADK types.Schema 对象
|
|
26
|
+
"""
|
|
27
|
+
from google.genai import types
|
|
28
|
+
|
|
29
|
+
if not schema or not isinstance(schema, dict):
|
|
30
|
+
return types.Schema(type=types.Type.OBJECT)
|
|
31
|
+
|
|
32
|
+
if root_schema is None:
|
|
33
|
+
root_schema = schema
|
|
34
|
+
|
|
35
|
+
# 处理 $ref 引用
|
|
36
|
+
if "$ref" in schema:
|
|
37
|
+
ref = schema["$ref"]
|
|
38
|
+
resolved = _resolve_schema_ref(ref, root_schema)
|
|
39
|
+
if resolved:
|
|
40
|
+
return _json_schema_to_google_schema(resolved, root_schema)
|
|
41
|
+
return types.Schema(type=types.Type.OBJECT)
|
|
42
|
+
|
|
43
|
+
schema_type = schema.get("type")
|
|
44
|
+
description = schema.get("description")
|
|
45
|
+
|
|
46
|
+
# 类型映射
|
|
47
|
+
type_mapping = {
|
|
48
|
+
"string": types.Type.STRING,
|
|
49
|
+
"integer": types.Type.INTEGER,
|
|
50
|
+
"number": types.Type.NUMBER,
|
|
51
|
+
"boolean": types.Type.BOOLEAN,
|
|
52
|
+
"array": types.Type.ARRAY,
|
|
53
|
+
"object": types.Type.OBJECT,
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
google_type = type_mapping.get(
|
|
57
|
+
str(schema_type or "object"), types.Type.OBJECT
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
# 处理数组类型
|
|
61
|
+
if schema_type == "array":
|
|
62
|
+
items_schema = schema.get("items")
|
|
63
|
+
items = None
|
|
64
|
+
if items_schema:
|
|
65
|
+
items = _json_schema_to_google_schema(items_schema, root_schema)
|
|
66
|
+
return types.Schema(
|
|
67
|
+
type=google_type,
|
|
68
|
+
description=description,
|
|
69
|
+
items=items,
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
# 处理对象类型
|
|
73
|
+
if schema_type == "object":
|
|
74
|
+
props = schema.get("properties", {})
|
|
75
|
+
required = schema.get("required", [])
|
|
76
|
+
|
|
77
|
+
google_props = {}
|
|
78
|
+
for prop_name, prop_schema in props.items():
|
|
79
|
+
google_props[prop_name] = _json_schema_to_google_schema(
|
|
80
|
+
prop_schema, root_schema
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
return types.Schema(
|
|
84
|
+
type=google_type,
|
|
85
|
+
description=description,
|
|
86
|
+
properties=google_props if google_props else None,
|
|
87
|
+
required=required if required else None,
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
# 基本类型
|
|
91
|
+
return types.Schema(
|
|
92
|
+
type=google_type,
|
|
93
|
+
description=description,
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def _resolve_schema_ref(
|
|
98
|
+
ref: str, root_schema: Dict[str, Any]
|
|
99
|
+
) -> Optional[Dict[str, Any]]:
|
|
100
|
+
"""解析 JSON Schema $ref 引用
|
|
101
|
+
|
|
102
|
+
Args:
|
|
103
|
+
ref: $ref 字符串,如 "#/$defs/MyType" 或 "#/definitions/MyType"
|
|
104
|
+
root_schema: 根 schema,包含 $defs 或 definitions
|
|
105
|
+
|
|
106
|
+
Returns:
|
|
107
|
+
解析后的 schema,如果无法解析则返回 None
|
|
108
|
+
"""
|
|
109
|
+
if not ref or not ref.startswith("#/"):
|
|
110
|
+
return None
|
|
111
|
+
|
|
112
|
+
# 解析路径,如 "#/$defs/MyType" -> ["$defs", "MyType"]
|
|
113
|
+
path_parts = ref[2:].split("/")
|
|
114
|
+
current = root_schema
|
|
115
|
+
|
|
116
|
+
for part in path_parts:
|
|
117
|
+
if not isinstance(current, dict) or part not in current:
|
|
118
|
+
return None
|
|
119
|
+
current = current[part]
|
|
120
|
+
|
|
121
|
+
return current if isinstance(current, dict) else None
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
def _create_custom_function_tool_class():
|
|
125
|
+
"""创建自定义 FunctionTool 类
|
|
126
|
+
|
|
127
|
+
延迟创建以避免在模块导入时依赖 google.adk。
|
|
128
|
+
"""
|
|
129
|
+
from google.adk.tools.base_tool import BaseTool
|
|
130
|
+
|
|
131
|
+
class CustomFunctionTool(BaseTool):
|
|
132
|
+
"""自定义 Google ADK 工具类
|
|
133
|
+
|
|
134
|
+
允许手动指定 FunctionDeclaration,避免 Pydantic 模型的 $ref 问题。
|
|
135
|
+
继承自 google.adk.tools.BaseTool 以确保与 ADK Agent 兼容。
|
|
136
|
+
"""
|
|
137
|
+
|
|
138
|
+
def __init__(
|
|
139
|
+
self,
|
|
140
|
+
func,
|
|
141
|
+
declaration,
|
|
142
|
+
):
|
|
143
|
+
# 调用父类 __init__,传递 name 和 description
|
|
144
|
+
super().__init__(
|
|
145
|
+
name=declaration.name,
|
|
146
|
+
description=declaration.description or "",
|
|
147
|
+
)
|
|
148
|
+
self._func = func
|
|
149
|
+
self._declaration = declaration
|
|
150
|
+
|
|
151
|
+
def _get_declaration(self):
|
|
152
|
+
return self._declaration
|
|
153
|
+
|
|
154
|
+
async def run_async(self, *, args: Dict[str, Any], tool_context):
|
|
155
|
+
"""异步执行工具函数"""
|
|
156
|
+
return self._func(**args)
|
|
157
|
+
|
|
158
|
+
return CustomFunctionTool
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
# 缓存类,避免重复创建
|
|
162
|
+
_CustomFunctionToolClass = None
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
def _get_custom_function_tool_class():
|
|
166
|
+
"""获取 CustomFunctionTool 类(延迟加载)"""
|
|
167
|
+
global _CustomFunctionToolClass
|
|
168
|
+
if _CustomFunctionToolClass is None:
|
|
169
|
+
_CustomFunctionToolClass = _create_custom_function_tool_class()
|
|
170
|
+
return _CustomFunctionToolClass
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
class GoogleADKToolAdapter(ToolAdapter):
|
|
174
|
+
"""Google ADK 工具适配器 / Google ADK Tool Adapter
|
|
175
|
+
|
|
176
|
+
实现 CanonicalTool → Google ADK 函数的转换。
|
|
177
|
+
由于 Google ADK 不支持复杂的 JSON Schema(包含 $ref 和 $defs),
|
|
178
|
+
此适配器会手动构建 FunctionDeclaration 并使用自定义工具类。
|
|
179
|
+
"""
|
|
180
|
+
|
|
181
|
+
def get_registered_tool(self, name: str) -> Optional[CanonicalTool]:
|
|
182
|
+
"""根据名称获取最近注册的工具定义 / Google ADK Tool Adapter"""
|
|
183
|
+
return self._registered_tools.get(normalize_tool_name(name))
|
|
184
|
+
|
|
185
|
+
def from_canonical(self, tools: List[CanonicalTool]):
|
|
186
|
+
"""将标准格式转换为 Google ADK 工具 / Google ADK Tool Adapter
|
|
187
|
+
|
|
188
|
+
为每个工具创建自定义的 FunctionTool,手动指定参数 schema,
|
|
189
|
+
以避免 Pydantic 模型产生的 $ref 问题。
|
|
190
|
+
"""
|
|
191
|
+
from google.genai import types
|
|
192
|
+
|
|
193
|
+
result = []
|
|
194
|
+
|
|
195
|
+
for tool in tools:
|
|
196
|
+
# 记录工具定义
|
|
197
|
+
self._registered_tools[tool.name] = tool
|
|
198
|
+
|
|
199
|
+
# 从 parameters schema 构建 Google ADK Schema
|
|
200
|
+
parameters_schema = tool.parameters or {
|
|
201
|
+
"type": "object",
|
|
202
|
+
"properties": {},
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
google_schema = _json_schema_to_google_schema(
|
|
206
|
+
parameters_schema, parameters_schema
|
|
207
|
+
)
|
|
208
|
+
|
|
209
|
+
# 创建 FunctionDeclaration
|
|
210
|
+
declaration = types.FunctionDeclaration(
|
|
211
|
+
name=normalize_tool_name(tool.name),
|
|
212
|
+
description=tool.description or "",
|
|
213
|
+
parameters=google_schema,
|
|
214
|
+
)
|
|
215
|
+
|
|
216
|
+
# 创建包装函数
|
|
217
|
+
def make_wrapper(canonical_tool: CanonicalTool):
|
|
218
|
+
def wrapper(**kwargs):
|
|
219
|
+
if canonical_tool.func is None:
|
|
220
|
+
raise NotImplementedError(
|
|
221
|
+
f"Tool function for '{canonical_tool.name}' "
|
|
222
|
+
"is not implemented."
|
|
223
|
+
)
|
|
224
|
+
return canonical_tool.func(**kwargs)
|
|
225
|
+
|
|
226
|
+
return wrapper
|
|
227
|
+
|
|
228
|
+
wrapper_func = make_wrapper(tool)
|
|
229
|
+
|
|
230
|
+
# 创建自定义工具
|
|
231
|
+
CustomFunctionTool = _get_custom_function_tool_class()
|
|
232
|
+
custom_tool = CustomFunctionTool(wrapper_func, declaration)
|
|
233
|
+
result.append(custom_tool)
|
|
234
|
+
|
|
235
|
+
return result
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"""LangChain 集成模块
|
|
2
|
+
|
|
3
|
+
使用 AgentRunConverter 将 LangChain 事件转换为 AG-UI 协议事件:
|
|
4
|
+
|
|
5
|
+
>>> from agentrun.integration.langchain import AgentRunConverter
|
|
6
|
+
>>>
|
|
7
|
+
>>> async def invoke_agent(request: AgentRequest):
|
|
8
|
+
... converter = AgentRunConverter()
|
|
9
|
+
... async for event in agent.astream_events(input_data, version="v2"):
|
|
10
|
+
... for item in converter.convert(event):
|
|
11
|
+
... yield item
|
|
12
|
+
|
|
13
|
+
支持多种调用方式:
|
|
14
|
+
- agent.astream_events(input, version="v2") - 支持 token by token
|
|
15
|
+
- agent.stream(input, stream_mode="updates") - 按节点输出
|
|
16
|
+
- agent.astream(input, stream_mode="updates") - 异步按节点输出
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
from agentrun.integration.langgraph.agent_converter import (
|
|
20
|
+
AgentRunConverter,
|
|
21
|
+
) # 向后兼容
|
|
22
|
+
|
|
23
|
+
from .builtin import model, sandbox_toolset, toolset
|
|
24
|
+
|
|
25
|
+
__all__ = [
|
|
26
|
+
"AgentRunConverter",
|
|
27
|
+
"model",
|
|
28
|
+
"toolset",
|
|
29
|
+
"sandbox_toolset",
|
|
30
|
+
]
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"""LangChain 适配器 / LangChain Adapters
|
|
2
|
+
|
|
3
|
+
提供 LangChain 框架的消息、工具和模型适配器。"""
|
|
4
|
+
|
|
5
|
+
from agentrun.integration.langchain.message_adapter import (
|
|
6
|
+
LangChainMessageAdapter,
|
|
7
|
+
)
|
|
8
|
+
from agentrun.integration.langchain.model_adapter import LangChainModelAdapter
|
|
9
|
+
from agentrun.integration.langchain.tool_adapter import LangChainToolAdapter
|
|
10
|
+
|
|
11
|
+
__all__ = [
|
|
12
|
+
"LangChainMessageAdapter",
|
|
13
|
+
"LangChainToolAdapter",
|
|
14
|
+
"LangChainModelAdapter",
|
|
15
|
+
]
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
"""LangChain 内置集成函数 / LangChain Built-in Integration Functions
|
|
2
|
+
|
|
3
|
+
提供快速创建 LangChain 兼容模型和工具的便捷函数。
|
|
4
|
+
Provides convenient functions for quickly creating LangChain-compatible models and tools.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from typing import Any, Callable, List, Optional, Union
|
|
8
|
+
|
|
9
|
+
from typing_extensions import Unpack
|
|
10
|
+
|
|
11
|
+
from agentrun.integration.builtin import model as _model
|
|
12
|
+
from agentrun.integration.builtin import ModelArgs
|
|
13
|
+
from agentrun.integration.builtin import sandbox_toolset as _sandbox_toolset
|
|
14
|
+
from agentrun.integration.builtin import toolset as _toolset
|
|
15
|
+
from agentrun.integration.utils.tool import Tool
|
|
16
|
+
from agentrun.model import ModelProxy, ModelService
|
|
17
|
+
from agentrun.sandbox import TemplateType
|
|
18
|
+
from agentrun.toolset import ToolSet
|
|
19
|
+
from agentrun.utils.config import Config
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def model(
|
|
23
|
+
name: Union[str, ModelProxy, ModelService],
|
|
24
|
+
**kwargs: Unpack[ModelArgs],
|
|
25
|
+
):
|
|
26
|
+
"""获取 AgentRun 模型并转换为 LangChain ``BaseChatModel``。 / LangChain Built-in Integration Functions"""
|
|
27
|
+
|
|
28
|
+
m = _model(input=name, **kwargs)
|
|
29
|
+
return m.to_langchain()
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def toolset(
|
|
33
|
+
name: Union[str, ToolSet],
|
|
34
|
+
*,
|
|
35
|
+
prefix: Optional[str] = None,
|
|
36
|
+
modify_tool_name: Optional[Callable[[Tool], Tool]] = None,
|
|
37
|
+
filter_tools_by_name: Optional[Callable[[str], bool]] = None,
|
|
38
|
+
config: Optional[Config] = None,
|
|
39
|
+
) -> List[Any]:
|
|
40
|
+
"""将内置工具集封装为 LangChain ``StructuredTool`` 列表。 / LangChain Built-in Integration Functions"""
|
|
41
|
+
|
|
42
|
+
ts = _toolset(input=name, config=config)
|
|
43
|
+
return ts.to_langchain(
|
|
44
|
+
prefix=prefix,
|
|
45
|
+
modify_tool_name=modify_tool_name,
|
|
46
|
+
filter_tools_by_name=filter_tools_by_name,
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def sandbox_toolset(
|
|
51
|
+
template_name: str,
|
|
52
|
+
*,
|
|
53
|
+
template_type: TemplateType = TemplateType.CODE_INTERPRETER,
|
|
54
|
+
sandbox_idle_timeout_seconds: int = 600,
|
|
55
|
+
prefix: Optional[str] = None,
|
|
56
|
+
modify_tool_name: Optional[Callable[[Tool], Tool]] = None,
|
|
57
|
+
filter_tools_by_name: Optional[Callable[[str], bool]] = None,
|
|
58
|
+
config: Optional[Config] = None,
|
|
59
|
+
) -> List[Any]:
|
|
60
|
+
"""将沙箱模板封装为 LangChain ``StructuredTool`` 列表。 / LangChain Built-in Integration Functions"""
|
|
61
|
+
|
|
62
|
+
return _sandbox_toolset(
|
|
63
|
+
template_name=template_name,
|
|
64
|
+
template_type=template_type,
|
|
65
|
+
config=config,
|
|
66
|
+
sandbox_idle_timeout_seconds=sandbox_idle_timeout_seconds,
|
|
67
|
+
).to_langchain(
|
|
68
|
+
prefix=prefix,
|
|
69
|
+
modify_tool_name=modify_tool_name,
|
|
70
|
+
filter_tools_by_name=filter_tools_by_name,
|
|
71
|
+
)
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
"""LangChain 消息适配器 / LangChain Message Adapter
|
|
2
|
+
|
|
3
|
+
将 LangChain BaseMessage 转换为标准格式,供 ModelAdapter 内部使用。
|
|
4
|
+
Converts LangChain BaseMessage to canonical format for internal use by ModelAdapter.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import json
|
|
8
|
+
from typing import Any, List
|
|
9
|
+
|
|
10
|
+
from agentrun.integration.utils.adapter import MessageAdapter
|
|
11
|
+
from agentrun.integration.utils.canonical import (
|
|
12
|
+
CanonicalMessage,
|
|
13
|
+
CanonicalToolCall,
|
|
14
|
+
MessageRole,
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class LangChainMessageAdapter(MessageAdapter):
|
|
19
|
+
"""LangChain 消息适配器 / LangChain Message Adapter
|
|
20
|
+
|
|
21
|
+
实现 LangChain BaseMessage → CanonicalMessage 的转换。
|
|
22
|
+
Implements conversion from LangChain BaseMessage to CanonicalMessage.
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
def to_canonical(self, messages: Any) -> List[CanonicalMessage]:
|
|
26
|
+
"""将 LangChain BaseMessage 转换为标准格式 / LangChain Message Adapter"""
|
|
27
|
+
try:
|
|
28
|
+
from langchain_core.messages import (
|
|
29
|
+
AIMessage,
|
|
30
|
+
HumanMessage,
|
|
31
|
+
SystemMessage,
|
|
32
|
+
ToolMessage,
|
|
33
|
+
)
|
|
34
|
+
except ImportError as e:
|
|
35
|
+
raise ImportError(
|
|
36
|
+
"LangChain is not installed. "
|
|
37
|
+
"Install it with: pip install langchain-core"
|
|
38
|
+
) from e
|
|
39
|
+
|
|
40
|
+
canonical = []
|
|
41
|
+
for msg in messages:
|
|
42
|
+
if isinstance(msg, SystemMessage):
|
|
43
|
+
canonical.append(
|
|
44
|
+
CanonicalMessage(
|
|
45
|
+
role=MessageRole.SYSTEM,
|
|
46
|
+
content=msg.content
|
|
47
|
+
if hasattr(msg, "content")
|
|
48
|
+
else None,
|
|
49
|
+
)
|
|
50
|
+
)
|
|
51
|
+
elif isinstance(msg, HumanMessage):
|
|
52
|
+
canonical.append(
|
|
53
|
+
CanonicalMessage(
|
|
54
|
+
role=MessageRole.USER,
|
|
55
|
+
content=msg.content
|
|
56
|
+
if hasattr(msg, "content")
|
|
57
|
+
else None,
|
|
58
|
+
)
|
|
59
|
+
)
|
|
60
|
+
elif isinstance(msg, AIMessage):
|
|
61
|
+
tool_calls = None
|
|
62
|
+
if hasattr(msg, "tool_calls") and msg.tool_calls:
|
|
63
|
+
tool_calls = []
|
|
64
|
+
for call in msg.tool_calls:
|
|
65
|
+
# LangChain tool_calls: {"id": ..., "name": ..., "args": ...}
|
|
66
|
+
call_id = (
|
|
67
|
+
call.get("id")
|
|
68
|
+
if isinstance(call, dict)
|
|
69
|
+
else getattr(call, "id", "")
|
|
70
|
+
)
|
|
71
|
+
call_name = (
|
|
72
|
+
call.get("name")
|
|
73
|
+
if isinstance(call, dict)
|
|
74
|
+
else getattr(call, "name", "")
|
|
75
|
+
)
|
|
76
|
+
call_args = (
|
|
77
|
+
call.get("args")
|
|
78
|
+
if isinstance(call, dict)
|
|
79
|
+
else getattr(call, "args", {})
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
# 如果 args 是字符串,尝试解析
|
|
83
|
+
if isinstance(call_args, str):
|
|
84
|
+
try:
|
|
85
|
+
call_args = json.loads(call_args)
|
|
86
|
+
except json.JSONDecodeError:
|
|
87
|
+
call_args = {}
|
|
88
|
+
|
|
89
|
+
tool_calls.append(
|
|
90
|
+
CanonicalToolCall(
|
|
91
|
+
id=str(call_id),
|
|
92
|
+
name=str(call_name),
|
|
93
|
+
arguments=(
|
|
94
|
+
call_args
|
|
95
|
+
if isinstance(call_args, dict)
|
|
96
|
+
else {}
|
|
97
|
+
),
|
|
98
|
+
)
|
|
99
|
+
)
|
|
100
|
+
|
|
101
|
+
canonical.append(
|
|
102
|
+
CanonicalMessage(
|
|
103
|
+
role=MessageRole.ASSISTANT,
|
|
104
|
+
content=msg.content
|
|
105
|
+
if hasattr(msg, "content")
|
|
106
|
+
else None,
|
|
107
|
+
tool_calls=tool_calls,
|
|
108
|
+
)
|
|
109
|
+
)
|
|
110
|
+
elif isinstance(msg, ToolMessage):
|
|
111
|
+
content = msg.content
|
|
112
|
+
if type(content) is not str:
|
|
113
|
+
content = str(content)
|
|
114
|
+
|
|
115
|
+
canonical.append(
|
|
116
|
+
CanonicalMessage(
|
|
117
|
+
role=MessageRole.TOOL,
|
|
118
|
+
content=content,
|
|
119
|
+
tool_call_id=(
|
|
120
|
+
msg.tool_call_id
|
|
121
|
+
if hasattr(msg, "tool_call_id")
|
|
122
|
+
else None
|
|
123
|
+
),
|
|
124
|
+
)
|
|
125
|
+
)
|
|
126
|
+
else:
|
|
127
|
+
# 未知消息类型,尝试提取基本信息
|
|
128
|
+
role_str = getattr(msg, "type", "user").lower()
|
|
129
|
+
if "system" in role_str:
|
|
130
|
+
role = MessageRole.SYSTEM
|
|
131
|
+
elif "assistant" in role_str or "ai" in role_str:
|
|
132
|
+
role = MessageRole.ASSISTANT
|
|
133
|
+
elif "tool" in role_str:
|
|
134
|
+
role = MessageRole.TOOL
|
|
135
|
+
else:
|
|
136
|
+
role = MessageRole.USER
|
|
137
|
+
|
|
138
|
+
content = getattr(msg, "content", None)
|
|
139
|
+
canonical.append(CanonicalMessage(role=role, content=content))
|
|
140
|
+
|
|
141
|
+
return canonical
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"""LangChain 模型适配器 / LangChain Model Adapter
|
|
2
|
+
|
|
3
|
+
将 CommonModel 包装为 LangChain BaseChatModel。"""
|
|
4
|
+
|
|
5
|
+
import inspect
|
|
6
|
+
import json
|
|
7
|
+
from typing import Any, List, Optional
|
|
8
|
+
|
|
9
|
+
from agentrun.integration.langchain.message_adapter import (
|
|
10
|
+
LangChainMessageAdapter,
|
|
11
|
+
)
|
|
12
|
+
from agentrun.integration.utils.adapter import ModelAdapter
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class LangChainModelAdapter(ModelAdapter):
|
|
16
|
+
"""LangChain 模型适配器 / LangChain Model Adapter
|
|
17
|
+
|
|
18
|
+
将 CommonModel 包装为 LangChain BaseChatModel。"""
|
|
19
|
+
|
|
20
|
+
def __init__(self):
|
|
21
|
+
"""初始化适配器,创建内部的消息适配器 / LangChain Message Adapter"""
|
|
22
|
+
self._message_adapter = LangChainMessageAdapter()
|
|
23
|
+
|
|
24
|
+
def wrap_model(self, common_model: Any) -> Any:
|
|
25
|
+
"""包装 CommonModel 为 LangChain BaseChatModel / LangChain Model Adapter"""
|
|
26
|
+
from langchain_openai import ChatOpenAI
|
|
27
|
+
|
|
28
|
+
info = common_model.get_model_info() # 确保模型可用
|
|
29
|
+
return ChatOpenAI(
|
|
30
|
+
name=info.model,
|
|
31
|
+
api_key=info.api_key,
|
|
32
|
+
model=info.model,
|
|
33
|
+
base_url=info.base_url,
|
|
34
|
+
default_headers=info.headers,
|
|
35
|
+
stream_usage=True,
|
|
36
|
+
streaming=True, # 启用流式输出以支持 token by token
|
|
37
|
+
)
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"""LangChain 工具适配器 / LangChain Tool Adapter
|
|
2
|
+
|
|
3
|
+
将标准工具定义转换为 LangChain StructuredTool 格式。"""
|
|
4
|
+
|
|
5
|
+
from typing import Any, List
|
|
6
|
+
|
|
7
|
+
from agentrun.integration.utils.adapter import ToolAdapter
|
|
8
|
+
from agentrun.integration.utils.canonical import CanonicalTool
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class LangChainToolAdapter(ToolAdapter):
|
|
12
|
+
"""LangChain 工具适配器 / LangChain Tool Adapter
|
|
13
|
+
|
|
14
|
+
实现 CanonicalTool → LangChain StructuredTool 的转换。"""
|
|
15
|
+
|
|
16
|
+
def from_canonical(self, tools: List[CanonicalTool]) -> Any:
|
|
17
|
+
"""将标准格式转换为 LangChain StructuredTool / LangChain Tool Adapter"""
|
|
18
|
+
try:
|
|
19
|
+
from langchain_core.tools import StructuredTool
|
|
20
|
+
except ImportError as e:
|
|
21
|
+
raise ImportError(
|
|
22
|
+
"LangChain is not installed. "
|
|
23
|
+
"Install it with: pip install langchain-core"
|
|
24
|
+
) from e
|
|
25
|
+
|
|
26
|
+
from agentrun.integration.utils.tool import _json_schema_to_pydantic
|
|
27
|
+
|
|
28
|
+
result = []
|
|
29
|
+
for tool in tools:
|
|
30
|
+
# 从 JSON Schema 创建 Pydantic 模型
|
|
31
|
+
args_schema = _json_schema_to_pydantic(
|
|
32
|
+
f"{tool.name}_Args", tool.parameters
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
if args_schema is None:
|
|
36
|
+
# 如果无法创建 schema,使用空模型
|
|
37
|
+
from pydantic import create_model
|
|
38
|
+
|
|
39
|
+
args_schema = create_model(f"{tool.name}_Args")
|
|
40
|
+
|
|
41
|
+
result.append(
|
|
42
|
+
StructuredTool.from_function(
|
|
43
|
+
func=tool.func,
|
|
44
|
+
name=tool.name,
|
|
45
|
+
description=tool.description,
|
|
46
|
+
args_schema=args_schema,
|
|
47
|
+
)
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
return result
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"""LangGraph 集成模块
|
|
2
|
+
|
|
3
|
+
使用 AgentRunConverter 将 LangGraph 事件转换为 AG-UI 协议事件:
|
|
4
|
+
|
|
5
|
+
>>> from agentrun.integration.langgraph import AgentRunConverter
|
|
6
|
+
>>>
|
|
7
|
+
>>> async def invoke_agent(request: AgentRequest):
|
|
8
|
+
... converter = AgentRunConverter()
|
|
9
|
+
... async for event in agent.astream_events(input_data, version="v2"):
|
|
10
|
+
... for item in converter.convert(event):
|
|
11
|
+
... yield item
|
|
12
|
+
|
|
13
|
+
或使用静态方法(无状态):
|
|
14
|
+
|
|
15
|
+
>>> from agentrun.integration.langgraph import AgentRunConverter
|
|
16
|
+
>>>
|
|
17
|
+
>>> async for event in agent.astream_events(input_data, version="v2"):
|
|
18
|
+
... for item in AgentRunConverter.to_agui_events(event):
|
|
19
|
+
... yield item
|
|
20
|
+
|
|
21
|
+
支持多种调用方式:
|
|
22
|
+
- agent.astream_events(input, version="v2") - 支持 token by token
|
|
23
|
+
- agent.stream(input, stream_mode="updates") - 按节点输出
|
|
24
|
+
- agent.astream(input, stream_mode="updates") - 异步按节点输出
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
from .agent_converter import AgentRunConverter
|
|
28
|
+
from .builtin import model, sandbox_toolset, toolset
|
|
29
|
+
|
|
30
|
+
__all__ = [
|
|
31
|
+
"AgentRunConverter",
|
|
32
|
+
"model",
|
|
33
|
+
"toolset",
|
|
34
|
+
"sandbox_toolset",
|
|
35
|
+
]
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"""LangGraph 适配器 / LangGraph Adapters
|
|
2
|
+
|
|
3
|
+
LangGraph 与 LangChain 完全兼容,因此直接复用 LangChain 的适配器。"""
|
|
4
|
+
|
|
5
|
+
from agentrun.integration.langchain.adapter import (
|
|
6
|
+
LangChainMessageAdapter,
|
|
7
|
+
LangChainModelAdapter,
|
|
8
|
+
LangChainToolAdapter,
|
|
9
|
+
)
|
|
10
|
+
|
|
11
|
+
# LangGraph 使用与 LangChain 相同的适配器
|
|
12
|
+
LangGraphMessageAdapter = LangChainMessageAdapter
|
|
13
|
+
LangGraphToolAdapter = LangChainToolAdapter
|
|
14
|
+
LangGraphModelAdapter = LangChainModelAdapter
|
|
15
|
+
|
|
16
|
+
__all__ = [
|
|
17
|
+
"LangGraphMessageAdapter",
|
|
18
|
+
"LangGraphToolAdapter",
|
|
19
|
+
"LangGraphModelAdapter",
|
|
20
|
+
]
|