computenest-agent-integrations 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.
- computenest/agents/__init__.py +1 -0
- computenest/agents/adk/__init__.py +7 -0
- computenest/agents/adk/mcp_helpers.py +8 -0
- computenest/agents/adk/memory/__init__.py +5 -0
- computenest/agents/adk/memory/bailian_long_term_memory.py +194 -0
- computenest/agents/adk/tools/__init__.py +0 -0
- computenest/agents/adk/tools/bailian_mcp.py +50 -0
- computenest/agents/adk/tools/bailian_rag.py +128 -0
- computenest/agents/common/__init__.py +1 -0
- computenest_agent_integrations-0.1.0.dist-info/METADATA +113 -0
- computenest_agent_integrations-0.1.0.dist-info/RECORD +13 -0
- computenest_agent_integrations-0.1.0.dist-info/WHEEL +5 -0
- computenest_agent_integrations-0.1.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""ComputeNest Agent Integrations – reusable helpers for building agents."""
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
"""ADK (Agent Development Kit) integration helpers."""
|
|
2
|
+
|
|
3
|
+
from .memory import BailianLongTermMemoryService
|
|
4
|
+
from .tools.bailian_mcp import BailianMcpTool
|
|
5
|
+
from .tools.bailian_rag import BailianRagTool
|
|
6
|
+
|
|
7
|
+
__all__ = ["BailianLongTermMemoryService", "BailianRagTool", "BailianMcpTool"]
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
"""Alibaba Cloud Model Studio long-term memory service for ADK."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from datetime import datetime
|
|
6
|
+
from datetime import timezone
|
|
7
|
+
import logging
|
|
8
|
+
from typing import Any
|
|
9
|
+
|
|
10
|
+
import aiohttp
|
|
11
|
+
from google.adk.memory.base_memory_service import BaseMemoryService
|
|
12
|
+
from google.adk.memory.base_memory_service import SearchMemoryResponse
|
|
13
|
+
from google.adk.memory.memory_entry import MemoryEntry
|
|
14
|
+
from google.adk.sessions.session import Session
|
|
15
|
+
from google.genai import types
|
|
16
|
+
from typing_extensions import override
|
|
17
|
+
|
|
18
|
+
DEFAULT_ENDPOINT = "https://dashscope.aliyuncs.com/api/v2/apps/memory"
|
|
19
|
+
|
|
20
|
+
logger = logging.getLogger(__name__)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class BailianLongTermMemoryService(BaseMemoryService):
|
|
24
|
+
"""Store and retrieve ADK conversation memory through Bailian."""
|
|
25
|
+
|
|
26
|
+
def __init__(
|
|
27
|
+
self,
|
|
28
|
+
*,
|
|
29
|
+
api_key: str,
|
|
30
|
+
memory_library_id: str,
|
|
31
|
+
add_project_id: str | None = None,
|
|
32
|
+
search_project_ids: list[str] | None = None,
|
|
33
|
+
top_k: int = 5,
|
|
34
|
+
min_score: float = 0.3,
|
|
35
|
+
endpoint: str = DEFAULT_ENDPOINT,
|
|
36
|
+
timeout: float = 30.0,
|
|
37
|
+
) -> None:
|
|
38
|
+
if not api_key:
|
|
39
|
+
raise ValueError("api_key must not be empty")
|
|
40
|
+
if not memory_library_id:
|
|
41
|
+
raise ValueError("memory_library_id must not be empty")
|
|
42
|
+
|
|
43
|
+
self._api_key = api_key
|
|
44
|
+
self._memory_library_id = memory_library_id
|
|
45
|
+
self._add_project_id = add_project_id
|
|
46
|
+
self._search_project_ids = search_project_ids
|
|
47
|
+
self._top_k = top_k
|
|
48
|
+
self._min_score = min_score
|
|
49
|
+
self._endpoint = endpoint.rstrip("/")
|
|
50
|
+
self._timeout = timeout
|
|
51
|
+
|
|
52
|
+
@override
|
|
53
|
+
async def add_session_to_memory(self, session: Session) -> None:
|
|
54
|
+
"""Extract memories from the user and model messages in a session."""
|
|
55
|
+
try:
|
|
56
|
+
messages = _events_to_messages(session.events)
|
|
57
|
+
if not messages:
|
|
58
|
+
logger.debug(
|
|
59
|
+
"No messages to store for session %s",
|
|
60
|
+
session.id,
|
|
61
|
+
)
|
|
62
|
+
return
|
|
63
|
+
|
|
64
|
+
payload: dict[str, Any] = {
|
|
65
|
+
"user_id": session.user_id,
|
|
66
|
+
"messages": messages,
|
|
67
|
+
"memory_library_id": self._memory_library_id,
|
|
68
|
+
"meta_data": {
|
|
69
|
+
"app_name": session.app_name,
|
|
70
|
+
"session_id": session.id,
|
|
71
|
+
},
|
|
72
|
+
}
|
|
73
|
+
if self._add_project_id:
|
|
74
|
+
payload["project_id"] = self._add_project_id
|
|
75
|
+
|
|
76
|
+
result = await self._request("/add", payload)
|
|
77
|
+
logger.info(
|
|
78
|
+
"Stored %d messages for session %s "
|
|
79
|
+
"(created %d memory nodes, request_id=%s)",
|
|
80
|
+
len(messages),
|
|
81
|
+
session.id,
|
|
82
|
+
len(result.get("memory_nodes", [])),
|
|
83
|
+
result.get("request_id", ""),
|
|
84
|
+
)
|
|
85
|
+
except Exception:
|
|
86
|
+
logger.exception(
|
|
87
|
+
"Failed to add session %s to Bailian memory",
|
|
88
|
+
session.id,
|
|
89
|
+
)
|
|
90
|
+
raise
|
|
91
|
+
|
|
92
|
+
@override
|
|
93
|
+
async def search_memory(
|
|
94
|
+
self,
|
|
95
|
+
*,
|
|
96
|
+
app_name: str,
|
|
97
|
+
user_id: str,
|
|
98
|
+
query: str,
|
|
99
|
+
) -> SearchMemoryResponse:
|
|
100
|
+
"""Search the configured Bailian memory library for one ADK user."""
|
|
101
|
+
try:
|
|
102
|
+
payload: dict[str, Any] = {
|
|
103
|
+
"user_id": user_id,
|
|
104
|
+
"messages": [{"role": "user", "content": query}],
|
|
105
|
+
"memory_library_id": self._memory_library_id,
|
|
106
|
+
"top_k": self._top_k,
|
|
107
|
+
"min_score": self._min_score,
|
|
108
|
+
}
|
|
109
|
+
if self._search_project_ids:
|
|
110
|
+
payload["project_ids"] = self._search_project_ids
|
|
111
|
+
|
|
112
|
+
result = await self._request(
|
|
113
|
+
"/memory_nodes/search",
|
|
114
|
+
payload,
|
|
115
|
+
)
|
|
116
|
+
memories = [
|
|
117
|
+
MemoryEntry(
|
|
118
|
+
id=node.get("memory_node_id"),
|
|
119
|
+
content=types.Content(
|
|
120
|
+
role="user",
|
|
121
|
+
parts=[
|
|
122
|
+
types.Part.from_text(
|
|
123
|
+
text=str(node.get("content", ""))
|
|
124
|
+
)
|
|
125
|
+
],
|
|
126
|
+
),
|
|
127
|
+
author="memory",
|
|
128
|
+
timestamp=_format_timestamp(node.get("created_at")),
|
|
129
|
+
custom_metadata=node.get("meta_data") or {},
|
|
130
|
+
)
|
|
131
|
+
for node in result.get("memory_nodes", [])
|
|
132
|
+
if node.get("content")
|
|
133
|
+
]
|
|
134
|
+
|
|
135
|
+
logger.info(
|
|
136
|
+
"Found %d memories for query '%s' (app=%s, user=%s)",
|
|
137
|
+
len(memories),
|
|
138
|
+
query[:50],
|
|
139
|
+
app_name,
|
|
140
|
+
user_id,
|
|
141
|
+
)
|
|
142
|
+
return SearchMemoryResponse(memories=memories)
|
|
143
|
+
except Exception:
|
|
144
|
+
logger.exception(
|
|
145
|
+
"Failed to search Bailian memories "
|
|
146
|
+
"(app=%s, user=%s)",
|
|
147
|
+
app_name,
|
|
148
|
+
user_id,
|
|
149
|
+
)
|
|
150
|
+
return SearchMemoryResponse(memories=[])
|
|
151
|
+
|
|
152
|
+
async def _request(
|
|
153
|
+
self,
|
|
154
|
+
path: str,
|
|
155
|
+
payload: dict[str, Any],
|
|
156
|
+
) -> dict[str, Any]:
|
|
157
|
+
headers = {
|
|
158
|
+
"Authorization": f"Bearer {self._api_key}",
|
|
159
|
+
"Content-Type": "application/json",
|
|
160
|
+
}
|
|
161
|
+
timeout = aiohttp.ClientTimeout(total=self._timeout)
|
|
162
|
+
async with aiohttp.ClientSession(timeout=timeout) as session:
|
|
163
|
+
async with session.post(
|
|
164
|
+
f"{self._endpoint}{path}",
|
|
165
|
+
headers=headers,
|
|
166
|
+
json=payload,
|
|
167
|
+
) as response:
|
|
168
|
+
response.raise_for_status()
|
|
169
|
+
return await response.json()
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
def _events_to_messages(events: list[Any]) -> list[dict[str, str]]:
|
|
173
|
+
messages: list[dict[str, str]] = []
|
|
174
|
+
for event in events:
|
|
175
|
+
content = getattr(event, "content", None)
|
|
176
|
+
if not content or not content.parts:
|
|
177
|
+
continue
|
|
178
|
+
|
|
179
|
+
role = "assistant" if content.role == "model" else content.role
|
|
180
|
+
if role not in ("user", "assistant"):
|
|
181
|
+
continue
|
|
182
|
+
|
|
183
|
+
text = "\n".join(
|
|
184
|
+
part.text for part in content.parts if part.text
|
|
185
|
+
).strip()
|
|
186
|
+
if text:
|
|
187
|
+
messages.append({"role": role, "content": text})
|
|
188
|
+
return messages
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
def _format_timestamp(timestamp: int | None) -> str | None:
|
|
192
|
+
if timestamp is None:
|
|
193
|
+
return None
|
|
194
|
+
return datetime.fromtimestamp(timestamp, tz=timezone.utc).isoformat()
|
|
File without changes
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"""Build ADK McpToolsets from Bailian MCP configuration."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from collections.abc import Iterator
|
|
6
|
+
from typing import Any
|
|
7
|
+
|
|
8
|
+
from google.adk.tools.mcp_tool import McpToolset
|
|
9
|
+
from google.adk.tools.mcp_tool import StreamableHTTPConnectionParams
|
|
10
|
+
|
|
11
|
+
_DASHSCOPE_API_KEY = "${DASHSCOPE_API_KEY}"
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class BailianMcpTool:
|
|
15
|
+
"""Build ADK McpToolsets from Bailian MCP JSON configuration."""
|
|
16
|
+
|
|
17
|
+
def __init__(
|
|
18
|
+
self,
|
|
19
|
+
mcp_config: dict[str, Any],
|
|
20
|
+
*,
|
|
21
|
+
dashscope_api_key: str,
|
|
22
|
+
**mcp_toolset_kwargs: Any,
|
|
23
|
+
) -> None:
|
|
24
|
+
"""Create toolsets from Bailian MCP JSON configuration.
|
|
25
|
+
|
|
26
|
+
``mcp_config`` may be the full JSON (with ``mcpServers``) or just the
|
|
27
|
+
``mcpServers`` object.
|
|
28
|
+
"""
|
|
29
|
+
api_key = dashscope_api_key.strip()
|
|
30
|
+
servers = mcp_config.get("mcpServers", mcp_config)
|
|
31
|
+
|
|
32
|
+
self._toolsets = [
|
|
33
|
+
McpToolset(
|
|
34
|
+
connection_params=StreamableHTTPConnectionParams(
|
|
35
|
+
url=cfg["baseUrl"],
|
|
36
|
+
headers={
|
|
37
|
+
key: value.replace(_DASHSCOPE_API_KEY, api_key)
|
|
38
|
+
for key, value in (cfg.get("headers") or {}).items()
|
|
39
|
+
} or None,
|
|
40
|
+
),
|
|
41
|
+
**mcp_toolset_kwargs,
|
|
42
|
+
)
|
|
43
|
+
for cfg in servers.values()
|
|
44
|
+
]
|
|
45
|
+
|
|
46
|
+
def __iter__(self) -> Iterator[McpToolset]:
|
|
47
|
+
return iter(self._toolsets)
|
|
48
|
+
|
|
49
|
+
def __len__(self) -> int:
|
|
50
|
+
return len(self._toolsets)
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
"""Alibaba Cloud Model Studio knowledge-base retrieval tool for ADK."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import logging
|
|
6
|
+
from typing import Any
|
|
7
|
+
|
|
8
|
+
from alibabacloud_bailian20231229 import models as bailian_models
|
|
9
|
+
from alibabacloud_bailian20231229.client import Client as BailianClient
|
|
10
|
+
from alibabacloud_tea_openapi.utils_models import Config
|
|
11
|
+
from google.adk.tools.base_tool import BaseTool
|
|
12
|
+
from google.adk.tools.tool_context import ToolContext
|
|
13
|
+
from google.genai import types
|
|
14
|
+
from typing_extensions import override
|
|
15
|
+
|
|
16
|
+
logger = logging.getLogger(__name__)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class BailianRagTool(BaseTool):
|
|
20
|
+
"""Retrieve relevant document chunks from a Bailian knowledge base."""
|
|
21
|
+
|
|
22
|
+
def __init__(
|
|
23
|
+
self,
|
|
24
|
+
*,
|
|
25
|
+
access_key_id: str,
|
|
26
|
+
access_key_secret: str,
|
|
27
|
+
workspace_id: str,
|
|
28
|
+
index_id: str,
|
|
29
|
+
region_id: str = "cn-beijing",
|
|
30
|
+
) -> None:
|
|
31
|
+
super().__init__(
|
|
32
|
+
name="retrieve_from_knowledge_base",
|
|
33
|
+
description=(
|
|
34
|
+
"Retrieve document chunks from the configured Bailian "
|
|
35
|
+
"knowledge base that are relevant to the user's query."
|
|
36
|
+
),
|
|
37
|
+
)
|
|
38
|
+
self._workspace_id = workspace_id
|
|
39
|
+
self._index_id = index_id
|
|
40
|
+
self._client = BailianClient(
|
|
41
|
+
Config(
|
|
42
|
+
access_key_id=access_key_id,
|
|
43
|
+
access_key_secret=access_key_secret,
|
|
44
|
+
endpoint=f"bailian.{region_id}.aliyuncs.com",
|
|
45
|
+
)
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
@override
|
|
49
|
+
def _get_declaration(self) -> types.FunctionDeclaration:
|
|
50
|
+
return types.FunctionDeclaration(
|
|
51
|
+
name=self.name,
|
|
52
|
+
description=self.description,
|
|
53
|
+
parameters=types.Schema(
|
|
54
|
+
type=types.Type.OBJECT,
|
|
55
|
+
properties={
|
|
56
|
+
"query": types.Schema(
|
|
57
|
+
type=types.Type.STRING,
|
|
58
|
+
description="The knowledge-base search query.",
|
|
59
|
+
),
|
|
60
|
+
},
|
|
61
|
+
required=["query"],
|
|
62
|
+
),
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
@override
|
|
66
|
+
async def run_async(
|
|
67
|
+
self,
|
|
68
|
+
*,
|
|
69
|
+
args: dict[str, Any],
|
|
70
|
+
tool_context: ToolContext,
|
|
71
|
+
) -> dict[str, Any]:
|
|
72
|
+
del tool_context
|
|
73
|
+
|
|
74
|
+
query = args.get("query")
|
|
75
|
+
if not isinstance(query, str) or not query.strip():
|
|
76
|
+
return {
|
|
77
|
+
"success": False,
|
|
78
|
+
"error_code": "INVALID_QUERY",
|
|
79
|
+
"message": "The query must be a non-empty string.",
|
|
80
|
+
"query": query if isinstance(query, str) else None,
|
|
81
|
+
"chunks": [],
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
normalized_query = query.strip()
|
|
85
|
+
try:
|
|
86
|
+
response = await self._client.retrieve_async(
|
|
87
|
+
self._workspace_id,
|
|
88
|
+
bailian_models.RetrieveRequest(
|
|
89
|
+
index_id=self._index_id,
|
|
90
|
+
query=normalized_query,
|
|
91
|
+
),
|
|
92
|
+
)
|
|
93
|
+
except Exception:
|
|
94
|
+
logger.exception("Bailian knowledge-base request failed.")
|
|
95
|
+
return {
|
|
96
|
+
"success": False,
|
|
97
|
+
"error_code": "BAILIAN_REQUEST_ERROR",
|
|
98
|
+
"message": "Unable to access the Bailian knowledge base.",
|
|
99
|
+
"query": normalized_query,
|
|
100
|
+
"chunks": [],
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
if not response.body or not response.body.success:
|
|
104
|
+
return {
|
|
105
|
+
"success": False,
|
|
106
|
+
"error_code": "BAILIAN_API_ERROR",
|
|
107
|
+
"message": "Bailian knowledge-base retrieval failed.",
|
|
108
|
+
"query": normalized_query,
|
|
109
|
+
"chunks": [],
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
nodes = response.body.data.nodes if response.body.data else []
|
|
113
|
+
return {
|
|
114
|
+
"success": True,
|
|
115
|
+
"message": (
|
|
116
|
+
f"Retrieved {len(nodes)} knowledge-base chunk(s)."
|
|
117
|
+
if nodes
|
|
118
|
+
else "No relevant knowledge-base content was found."
|
|
119
|
+
),
|
|
120
|
+
"query": normalized_query,
|
|
121
|
+
"chunks": [
|
|
122
|
+
{
|
|
123
|
+
"text": node.text,
|
|
124
|
+
"score": node.score,
|
|
125
|
+
}
|
|
126
|
+
for node in nodes
|
|
127
|
+
],
|
|
128
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Common utilities shared across agent integrations."""
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: computenest-agent-integrations
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: ComputeNest agent integrations for Google ADK with Alibaba Cloud Bailian
|
|
5
|
+
Author-email: Bali <zhaoyu.zhaoyu@alibaba-inc.com>, Yunyao <ziqiao.lzq@alibaba-inc.com>, Zhongsi <zhongsi.lz@alibaba-inc.com>
|
|
6
|
+
Project-URL: Homepage, https://computenest.console.aliyun.com/welcome
|
|
7
|
+
Requires-Python: >=3.12
|
|
8
|
+
Description-Content-Type: text/markdown
|
|
9
|
+
Requires-Dist: aiohttp>=3.9.0
|
|
10
|
+
Requires-Dist: alibabacloud-bailian20231229>=1.0.0
|
|
11
|
+
Requires-Dist: google-adk>=2.0.0
|
|
12
|
+
Requires-Dist: mcp<2.0.0,>=1.24.0
|
|
13
|
+
Requires-Dist: typing-extensions>=4.12.0
|
|
14
|
+
Provides-Extra: app
|
|
15
|
+
Requires-Dist: circus==0.19.0; extra == "app"
|
|
16
|
+
Requires-Dist: uvicorn[standard]==0.34.3; extra == "app"
|
|
17
|
+
Requires-Dist: python-dotenv==1.0.1; extra == "app"
|
|
18
|
+
Requires-Dist: fastapi==0.115.13; extra == "app"
|
|
19
|
+
Requires-Dist: sse-starlette==2.1.3; extra == "app"
|
|
20
|
+
Requires-Dist: pydantic-settings<3.0.0,>=2.2.1; extra == "app"
|
|
21
|
+
|
|
22
|
+
# 详细指南
|
|
23
|
+
Python部署请参考ATA文档:https://ata.atatech.org/articles/11020487205
|
|
24
|
+
如有疑问,可加入“Aone Python应用部署答疑群”群 钉钉群号: 109775038267
|
|
25
|
+
# 项目结构
|
|
26
|
+
```tree
|
|
27
|
+
├── APP-META (构建用到的文件)
|
|
28
|
+
│ └── docker-config (构建镜像时的工作目录)
|
|
29
|
+
│ ├── Dockerfile
|
|
30
|
+
│ └── environment
|
|
31
|
+
│ └── common
|
|
32
|
+
│ ├── base (要使用aone启动应用,必须包含的脚本/配置)
|
|
33
|
+
│ │ ├── app
|
|
34
|
+
│ │ │ └── bin
|
|
35
|
+
│ │ │ ├── appctl.sh
|
|
36
|
+
│ │ │ ├── health.sh
|
|
37
|
+
│ │ │ ├── setenv.sh
|
|
38
|
+
│ │ │ ├── start.sh
|
|
39
|
+
│ │ │ └── stop.sh
|
|
40
|
+
│ │ └── cai
|
|
41
|
+
│ │ ├── bin
|
|
42
|
+
│ │ │ └── nginxctl
|
|
43
|
+
│ │ └── conf
|
|
44
|
+
│ │ ├── mime.types
|
|
45
|
+
│ │ └── nginx-proxy.conf
|
|
46
|
+
│ └── custom (项目自定义的脚本/配置)
|
|
47
|
+
│ └── app
|
|
48
|
+
│ └── bin
|
|
49
|
+
│ ├── health.sh
|
|
50
|
+
│ ├── setenv.sh
|
|
51
|
+
│ ├── start.sh
|
|
52
|
+
│ └── stop.sh
|
|
53
|
+
├── README.md
|
|
54
|
+
├── app
|
|
55
|
+
│ ├── __init__.py
|
|
56
|
+
│ ├── api (对外暴露的后端API)
|
|
57
|
+
│ │ ├── __init__.py
|
|
58
|
+
│ │ ├── main.py
|
|
59
|
+
│ │ └── routes
|
|
60
|
+
│ │ ├── __init__.py
|
|
61
|
+
│ │ ├── health.py
|
|
62
|
+
│ │ └── hello.py
|
|
63
|
+
│ ├── config (应用配置相关)
|
|
64
|
+
│ │ ├── __init__.py
|
|
65
|
+
│ │ ├── env.py
|
|
66
|
+
│ │ ├── diamond.py
|
|
67
|
+
│ ├── lifecycle (应用生命周期相关)
|
|
68
|
+
│ │ ├── __init__.py
|
|
69
|
+
│ │ └── manager.py
|
|
70
|
+
│ └──main.py (主文件,初始化FastAPI,设置路由并启动)
|
|
71
|
+
│
|
|
72
|
+
├── conf (配置文件)
|
|
73
|
+
│ └── circus.ini (circus用于进程管理,Python应用的启动在此定义)
|
|
74
|
+
│
|
|
75
|
+
└── computenest-agent-integrations.release (构建文件)
|
|
76
|
+
```
|
|
77
|
+
# 自定义启动脚本
|
|
78
|
+
|
|
79
|
+
## 定制启动脚本请写到APP-META/.../common/custom目录下
|
|
80
|
+
|
|
81
|
+
APP-META/.../common/custom目录中存储了健康检查(health.sh)、环境变量(setenv.sh)、启动(start.sh)、停止(stop.sh)等脚本,这些脚本会在容器启动时被执行。如果项目有特殊需求,可以在custom目录下修改对应的脚本,最好不要直接修改base目录下的脚本,否则可能导致项目无法正常启动,如遇项目启动问题,请联系源码模板负责人。
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
# 本地启动
|
|
85
|
+
|
|
86
|
+
### 1. 安装依赖
|
|
87
|
+
- 首先安装uv,最简单的是`pip install uv`,其它方法:https://docs.astral.sh/uv/getting-started/installation/
|
|
88
|
+
- uv安装依赖:uv sync
|
|
89
|
+
- 如果不使用uv,可以手动pip安装pyproject.toml中的依赖
|
|
90
|
+
|
|
91
|
+
### 2. 启动命令
|
|
92
|
+
`uv run python -m app.main`
|
|
93
|
+
|
|
94
|
+
注意uv run自动激活了.venv虚拟环境,如果要直接运行python -m app.main,首先需要激活虚拟环境: `source .venv/bin/activate`
|
|
95
|
+
|
|
96
|
+
注意由于main.py被放置在app目录下,所以需要使用`python -m`模块启动,这是Python工程推荐做法,如果你希望直接使用`python main.py`启动,可以将main.py移出app目录,在根目录启动。
|
|
97
|
+
|
|
98
|
+
### 3. FastAPI 交互式API文档页
|
|
99
|
+
[http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs)
|
|
100
|
+
|
|
101
|
+
### 4. VSCode调试
|
|
102
|
+
创建launch.json时,选择Python调试程序->模块->输入app.main即可
|
|
103
|
+
|
|
104
|
+
# Aone部署
|
|
105
|
+
|
|
106
|
+
### 1. 部署
|
|
107
|
+
|
|
108
|
+
### 2. FastAPI 交互式API文档页
|
|
109
|
+
http://{host}/docs
|
|
110
|
+
|
|
111
|
+
# 脚手架介绍
|
|
112
|
+
|
|
113
|
+
该脚手架用于快速搭建并在Aone部署基于FastAPI的Python后端应用,也可以用于自定义部署参考,如果你希望部署其它框架或开源产品,只需删除app目录,并修改conf/circus.ini中的启动命令,但必须参考app/api/routes/health.py提供/status.taobao健康检查接口,如果你不需要VIPServer的优雅上下线,直接在/status.taobao中返回"success"即可。
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
computenest/agents/__init__.py,sha256=2VdnwimZsqhNzzkpDh8TZvOLdHhzmceZDubAE1eZ5JA,79
|
|
2
|
+
computenest/agents/adk/__init__.py,sha256=m47DjvuNGpBbwUdUW-gr1Cv5tC8XXXyuFhRRA5Ul7Kg,277
|
|
3
|
+
computenest/agents/adk/mcp_helpers.py,sha256=Vesddn1-290bLOJFUDPPB0o8htEoEeFT6JuUp2ImAJc,260
|
|
4
|
+
computenest/agents/adk/memory/__init__.py,sha256=TDFHm7FVCK7T7L3Cjq4ILKAgwuaKpQw4KDX_tMv-2S8,151
|
|
5
|
+
computenest/agents/adk/memory/bailian_long_term_memory.py,sha256=RzhzAj0YiNQ0f-EqQTe8eZB8rflhGyuEf3Os5VuIr58,6495
|
|
6
|
+
computenest/agents/adk/tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
7
|
+
computenest/agents/adk/tools/bailian_mcp.py,sha256=wxVYaHeO7eWPLdN-VIQNZYIQjle62SgxWxDmPlYbby4,1505
|
|
8
|
+
computenest/agents/adk/tools/bailian_rag.py,sha256=bbtomRRYXdDCdQcC_JGrSO1pDDF7ZQ_cbEYY8gsTvf4,4144
|
|
9
|
+
computenest/agents/common/__init__.py,sha256=OCQY0h32BorokX2fIwa7FyVlmllo_-LSmQZKh1uxDoQ,57
|
|
10
|
+
computenest_agent_integrations-0.1.0.dist-info/METADATA,sha256=j-dYfBQAxh07s_2qHA0z5R0UeO9JjeK6mjrqAkk3fqI,5196
|
|
11
|
+
computenest_agent_integrations-0.1.0.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
|
|
12
|
+
computenest_agent_integrations-0.1.0.dist-info/top_level.txt,sha256=YC9gq6Rtqnrt-MbnbaqEUTXYFGEC2__8Ro3t3uKrrUw,12
|
|
13
|
+
computenest_agent_integrations-0.1.0.dist-info/RECORD,,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
computenest
|