Skip to content

Commit ad24ecf

Browse files
committed
added oxy base bank.
1 parent 3449d49 commit ad24ecf

27 files changed

+731
-23
lines changed

CHANGELOG_zh.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
### Added
1515
- 新增Prompt管理界面,支持在线修改Prompt
1616
- 支持本地大模型 LocalLLM类
17+
- 新增oxy.BaseBank,用于标准化智能体输入信息
1718

1819
### Changed
1920
- 修改es包,由elasticsearch[async] 改为 elasticsearch
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
import uvicorn
2+
from fastapi import APIRouter, Body, FastAPI
3+
from fastapi.routing import APIRoute
4+
5+
app = FastAPI()
6+
router = APIRouter(tags=["bank"])
7+
8+
9+
@router.get("/user_profile_retrieve", description="A tool for querying user profile")
10+
def user_profile_retrieve(
11+
query: str = Body(description="query"),
12+
user_pin: str = Body(description="SystemArg.agent_pin"),
13+
agent_pin: str = Body(description="SystemArg.user_pin"),
14+
):
15+
user_profile_dict = {
16+
"001": "Arlen, a student, likes music",
17+
"002": "Tom, a programmer, likes sports",
18+
}
19+
portrait = user_profile_dict.get(user_pin, "Nothing")
20+
return f"The current user profile is: {portrait}"
21+
22+
23+
@router.post("/user_profile_deposit", description="A tool for updating user profile")
24+
def user_profile_deposit(
25+
content: str = Body(description="content"),
26+
user_pin: str = Body(description="SystemArg.agent_pin"),
27+
agent_pin: str = Body(description="SystemArg.user_pin"),
28+
) -> str:
29+
print(agent_pin, user_pin, content)
30+
return "updated user_profile"
31+
32+
33+
app.include_router(router)
34+
35+
36+
@app.get("/list_banks")
37+
def list_banks():
38+
return get_banks_from_router(router)
39+
40+
41+
def get_banks_from_router(router: APIRouter):
42+
banks = []
43+
for route in router.routes:
44+
if isinstance(route, APIRoute) and "bank" in getattr(route, "tags", []):
45+
description = route.description
46+
input_schema = {"type": "object", "properties": {}, "required": []}
47+
for param in route.dependant.query_params + route.dependant.body_params:
48+
param_type = param.type_
49+
# Type conversion (simple implementation)
50+
if param_type is str:
51+
t = "string"
52+
elif param_type is int:
53+
t = "integer"
54+
elif param_type is float:
55+
t = "number"
56+
elif param_type is bool:
57+
t = "boolean"
58+
else:
59+
t = "string"
60+
input_schema["properties"][param.name] = {
61+
"type": t,
62+
"description": param.field_info.description or "",
63+
}
64+
if param.required:
65+
input_schema["required"].append(param.name)
66+
banks.append(
67+
{
68+
"name": route.endpoint.__name__,
69+
"endpoint": route.path,
70+
"methods": route.methods,
71+
"description": description,
72+
"inputSchema": input_schema,
73+
}
74+
)
75+
return banks
76+
77+
78+
if __name__ == "__main__":
79+
uvicorn.run(app, host="127.0.0.1", port=8090)
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
import asyncio
2+
import os
3+
4+
from fastapi import Body
5+
6+
from oxygent import MAS, BankRouter, Config, oxy
7+
8+
Config.set_server_port(8090)
9+
10+
11+
router = BankRouter()
12+
13+
user_profile_dict = {
14+
"001": "Arlen, a student, likes music",
15+
"002": "Tom, a programmer, likes sports",
16+
}
17+
18+
19+
@router.post("/user_profile_retrieve", description="A tool for querying user profile")
20+
def user_profile_retrieve(
21+
query: str = Body(description="query"),
22+
user_pin: str = Body(description="SystemArg.agent_pin"),
23+
agent_pin: str = Body(description="SystemArg.user_pin"),
24+
):
25+
global user_profile_dict
26+
portrait = user_profile_dict.get(user_pin, "Nothing")
27+
return f"The current user profile is: {portrait}"
28+
29+
30+
@router.post("/user_profile_deposit", description="A tool for updating user profile")
31+
async def user_profile_deposit(
32+
content: str = Body(description="content"),
33+
user_pin: str = Body(description="SystemArg.agent_pin"),
34+
agent_pin: str = Body(description="SystemArg.user_pin"),
35+
):
36+
global user_profile_dict
37+
output = await router.mas.call(
38+
callee="bank_manager",
39+
arguments={
40+
"query": "Please update the user profile.",
41+
"chat": content,
42+
"profile": user_profile_dict.get(user_pin, "Nothing"),
43+
},
44+
)
45+
user_profile_dict[user_pin] = output
46+
return output
47+
48+
49+
oxy_space = [
50+
oxy.HttpLLM(
51+
name="default_llm",
52+
api_key=os.getenv("DEFAULT_LLM_API_KEY"),
53+
base_url=os.getenv("DEFAULT_LLM_BASE_URL"),
54+
model_name=os.getenv("DEFAULT_LLM_MODEL_NAME"),
55+
),
56+
oxy.ChatAgent(
57+
name="bank_manager",
58+
llm_model="default_llm",
59+
prompt="You are an expert in user profiling. Please update and refine the current user profile by integrating our previous conversation:\n${chat}\nAnd the current user profile:\n${profile}",
60+
),
61+
]
62+
63+
64+
async def main():
65+
async with MAS(oxy_space=oxy_space, routers=[router]) as mas:
66+
await mas.start_web_service()
67+
68+
69+
if __name__ == "__main__":
70+
asyncio.run(main())
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
import uvicorn
2+
from fastapi import APIRouter, FastAPI
3+
from pydantic import BaseModel
4+
5+
app = FastAPI()
6+
7+
router = APIRouter()
8+
9+
10+
class RetrievalRequest(BaseModel):
11+
query: str
12+
agent_pin: str
13+
user_pin: str
14+
15+
16+
@router.post("/user_profile_retrieve")
17+
def user_profile_retrieve(request: RetrievalRequest):
18+
user_profile_dict = {
19+
"001": "Arlen, a student, likes music",
20+
"002": "Tom, a programmer, likes sports",
21+
}
22+
portrait = user_profile_dict.get(request.user_pin, "Nothing")
23+
return f"The current user profile is: {portrait}"
24+
25+
26+
class DepositRequest(BaseModel):
27+
content: str
28+
agent_pin: str
29+
user_pin: str
30+
31+
32+
@router.post("/user_profile_deposit")
33+
def user_profile_deposit(request: DepositRequest):
34+
print(request.content)
35+
return "updated user_profile"
36+
37+
38+
@router.get("/list_banks")
39+
def list_banks():
40+
return [
41+
{
42+
"name": "user_profile_retrieve",
43+
"endpoint": "/user_profile_retrieve",
44+
"type": "retrieve",
45+
"description": "A tool for querying user profile",
46+
"inputSchema": {
47+
"properties": {
48+
"query": {"description": "query", "type": "str"},
49+
"agent_pin": {"description": "SystemArg.agent_pin", "type": "str"},
50+
"user_pin": {"description": "SystemArg.user_pin", "type": "str"},
51+
},
52+
"required": ["query", "agent_pin", "user_pin"],
53+
"type": "object",
54+
},
55+
},
56+
{
57+
"name": "user_profile_deposit",
58+
"endpoint": "/user_profile_deposit",
59+
"type": "deposit",
60+
"description": "A tool for updating user profile",
61+
"inputSchema": {
62+
"properties": {
63+
"content": {"description": "content", "type": "str"},
64+
"agent_pin": {"description": "SystemArg.agent_pin", "type": "str"},
65+
"user_pin": {"description": "SystemArg.user_pin", "type": "str"},
66+
},
67+
"required": ["content", "agent_pin", "user_pin"],
68+
"type": "object",
69+
},
70+
},
71+
]
72+
73+
74+
if __name__ == "__main__":
75+
uvicorn.run(app, host="127.0.0.1", port=8090)

docs/development/api/agent/base_oxy.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ This class defines the core execution lifecycle, permission management,message h
3636
| `is_permission_required` | `bool` | `False` | Whether execution needs permission |
3737
| `is_save_data` | `bool` | `True` | Persist execution data to store |
3838
| `permitted_tool_name_list` | `list` | `[]` | Tools the agent/tool may call |
39-
| `extra_permitted_tool_name_list` | `list` | `[]` | Additional tool permissions |
39+
| `permitted_oxy` | `list` | `[]` | Additional tool permissions |
4040
| `is_send_tool_call` | `bool` | `Config.get_message_is_send_tool_call()` | Send *tool\_call* messages |
4141
| `is_send_observation` | `bool` | `Config.get_message_is_send_observation()` | Send *observation* messages |
4242
| `is_send_answer` | `bool` | `Config.get_message_is_send_answer()` | Send *answer* messages |
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
import asyncio
2+
import json
3+
import os
4+
5+
from oxygent import MAS, OxyResponse, oxy
6+
7+
8+
async def dump_memory(oxy_response: OxyResponse) -> OxyResponse:
9+
oxy_request = oxy_response.oxy_request
10+
history = {
11+
"query": oxy_request.get_query(),
12+
"answer": oxy_response.output,
13+
}
14+
15+
await oxy_request.call_async(
16+
callee="user_profile_deposit",
17+
arguments={"content": json.dumps(history, ensure_ascii=False)},
18+
is_send_message=False,
19+
)
20+
return oxy_response
21+
22+
23+
oxy_space = [
24+
oxy.HttpLLM(
25+
name="default_llm",
26+
api_key=os.getenv("DEFAULT_LLM_API_KEY"),
27+
base_url=os.getenv("DEFAULT_LLM_BASE_URL"),
28+
model_name=os.getenv("DEFAULT_LLM_MODEL_NAME"),
29+
llm_params={"temperature": 0.01},
30+
semaphore=4,
31+
),
32+
oxy.ChatAgent(
33+
name="qa_agent",
34+
llm_model="default_llm",
35+
prompt="You can refer to the following information to answer the question:\n${preceding_text}",
36+
banks=["remote_user_profile_banks"],
37+
preceding_oxy=["user_profile_retrieve"],
38+
preceding_placeholder="preceding_text",
39+
func_process_output=dump_memory,
40+
),
41+
oxy.BankClient(
42+
name="remote_user_profile_banks",
43+
server_url="http://127.0.0.1:8090",
44+
),
45+
]
46+
47+
48+
def func_filter(payload):
49+
payload["group_data"] = {"user_pin": "002"}
50+
return payload
51+
52+
53+
async def main():
54+
async with MAS(
55+
oxy_space=oxy_space, func_filter=func_filter, name="temp_app"
56+
) as mas:
57+
await mas.start_web_service(first_query="Who I am")
58+
59+
60+
if __name__ == "__main__":
61+
asyncio.run(main())
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import asyncio
2+
import os
3+
4+
from oxygent import MAS, oxy
5+
6+
oxy_space = [
7+
oxy.HttpLLM(
8+
name="default_llm",
9+
api_key=os.getenv("DEFAULT_LLM_API_KEY"),
10+
base_url=os.getenv("DEFAULT_LLM_BASE_URL"),
11+
model_name=os.getenv("DEFAULT_LLM_MODEL_NAME"),
12+
llm_params={"temperature": 0.01},
13+
semaphore=4,
14+
),
15+
oxy.StdioMCPClient(
16+
name="time_tools",
17+
params={
18+
"command": "uvx",
19+
"args": ["mcp-server-time", "--local-timezone=Asia/Shanghai"],
20+
},
21+
),
22+
oxy.ReActAgent(
23+
name="qa_agent",
24+
llm_model="default_llm",
25+
tools=["time_tools"],
26+
banks=["remote_user_profile_banks"],
27+
),
28+
oxy.BankClient(
29+
name="remote_user_profile_banks",
30+
server_url="http://127.0.0.1:8090",
31+
),
32+
]
33+
34+
35+
def func_filter(payload):
36+
payload["group_data"] = {"user_pin": "002"}
37+
return payload
38+
39+
40+
async def main():
41+
async with MAS(oxy_space=oxy_space, func_filter=func_filter) as mas:
42+
await mas.start_web_service(first_query="Who I am")
43+
44+
45+
if __name__ == "__main__":
46+
asyncio.run(main())
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import asyncio
2+
import os
3+
4+
from oxygent import MAS, oxy
5+
6+
oxy_space = [
7+
oxy.HttpLLM(
8+
name="default_llm",
9+
api_key=os.getenv("DEFAULT_LLM_API_KEY"),
10+
base_url=os.getenv("DEFAULT_LLM_BASE_URL"),
11+
model_name=os.getenv("DEFAULT_LLM_MODEL_NAME"),
12+
llm_params={"temperature": 0.01},
13+
semaphore=4,
14+
),
15+
oxy.StdioMCPClient(
16+
name="time_tools",
17+
params={
18+
"command": "uvx",
19+
"args": ["mcp-server-time", "--local-timezone=Asia/Shanghai"],
20+
},
21+
),
22+
oxy.ReActAgent(
23+
name="qa_agent",
24+
llm_model="default_llm",
25+
tools=["time_tools", "remote_user_profile_banks"],
26+
),
27+
oxy.SSEMCPClient(
28+
name="remote_user_profile_banks",
29+
sse_url="http://127.0.0.1:8000/sse",
30+
),
31+
]
32+
33+
34+
def func_filter(payload):
35+
payload["group_data"] = {"user_pin": "002"}
36+
return payload
37+
38+
39+
async def main():
40+
async with MAS(oxy_space=oxy_space, func_filter=func_filter) as mas:
41+
await mas.start_web_service(first_query="Who I am")
42+
43+
44+
if __name__ == "__main__":
45+
asyncio.run(main())

0 commit comments

Comments
 (0)