试想一下,在未来 llm agent 在端侧全面铺开,但是目前调用大模型的方式通过了是一个拿到了就可以随便使用的 api-key?那用户岂不是从端侧的模型拿到了 api-key 就可以刷爆你的账单?!!!如果每个人的手机都跑着几个 agent,你还有一堆用户,那你服务器岂不是比被 ddos 了还惨,因为 ddos 是不让你提供服务,而这种情况下相当于正常业务还在运行而你被打爆了!
所以,我们提出了缄密 Dynaseal,一个面向未来端侧 agent 模型调用的服务端框架,通过一个类似于 oss 的动态 token,限制端侧 agent 可调用的模型和参数以及 token 存活时间,支持端侧直接和大模型服务商通信并在响应结束后通过回调告知你的业务后端。欢迎各位大佬批评指正 star。
请注意,本项目只是一个 demo,实现了我们对于动态分发 api key 从端侧请求大模型相应的设计,大模型部分被设计成一个 openai api 格式的大模型服务器的 warper。对于端侧的请求,我们只做了简单的密钥完整性校验和参数校验。请求结束的回调只实现了在终端的打印。
架构分为 llm 服务端,后端和客户端三部分。
sequenceDiagram
participant 后端 as 后端
participant 客户端 as 客户端
participant LLM服务端 as LLM服务端
Note over 后端: 初始化
后端->>LLM服务端: 请求大模型api-key
LLM服务端-->>后端: 返回api-key
Note over 客户端: 初始化
客户端->>后端: 请求业务鉴权
后端-->>客户端: 返回动态key, 包括可调用的模型, token等
客户端->>LLM服务端: 使用动态key请求模型
LLM服务端->>LLM服务端: 解包动态key, 确定身份
LLM服务端-->>客户端: 返回响应
LLM服务端->>后端: 通知客户端的请求和响应
动态 key 被设计为一个 jwt token,即header.payload.secret
1234567 | { "api-key": 111, // 后端在llm服务端注册的用户的id,请注意,是id而非llm server给出的key "model": "deepseek-chat", // 端侧可调用的模型名 "max_tokens": 100, // 最多可以调用的token数量 "expiring": 111, // 过期时间,使用unix时间戳 "event_id": 111 // 时间id,用于表示此token,llm服务端响应完请求会在调用中带上此enent_id} |
---|
在User
表下面创建用户如下,该用户账号密码是user1:user1
123456789101112131415161718 | { "_id": { "$oid": "671249a93f1cf2f8bf9b2b82" }, "api_keys": [ { "_id": null, "revision_id": null, "api_key": "4d72c063-881f-45fa-85ab-3375c84f5dd7", "last_used": 0 } ], "email": "[email protected]", "password": "$2b$12$QFk6uHDBM5s69uSXrchivOC5SbpTUGV4tjmWz0nRvPSiMt.WAZVhC", "total_tokens": 0, "username": "user1", "callback_url": "http://127.0.0.1:9000/v1/callback/usage"} |
---|
在User
表下面创建用户如下,该用户账号密码是client1:client1
123456789 | { "_id": { "$oid": "671247fadb2faa4fec2c6f39" }, "api_keys": [], "email": "[email protected]", "password": "$2b$12$fWy.Yjs9x5zSRirRibjliO4GX66GSO/.GuG7he9lIatuiNDoPPb9a", "username": "client1"} |
---|
123456789 | SECRET_KEY //jwt密钥ALGORITHM //jwt加密算法ACCESS_TOKEN_EXPIRE_MINUTES //jwt access token过期时间REFRESH_TOKEN_EXPIRE_MINUTES //jwt refersh token过期时间MONGODB_URL // mongo数据库地址MONGODB_DB // mongo数据库名ADMIN_USER_PASSWORD // 管理员密码OPENAI_BASE_URL // warp的openai base urlOPENAI_API_KEY // warp的openai api key |
---|
LLM_USER_ID 是业务后端在 llm 服务端注册的用户的 id,LLM_KEY 是业务后端在 llm 服务端注册的用户申请到的密钥
123456789 | SECRET_KEY //jwt密钥ALGORITHM //jwt加密算法ACCESS_TOKEN_EXPIRE_MINUTES //jwt access token过期时间REFRESH_TOKEN_EXPIRE_MINUTES //jwt refersh token过期时间MONGODB_URL // mongo数据库地址MONGODB_DB // mongo数据库名ADMIN_USER_PASSWORD // 管理员密码LLM_KEY = "4d72c063-881f-45fa-85ab-3375c84f5dd7"LLM_USER_ID = "671249a93f1cf2f8bf9b2b82" |
---|
llm_server_url
: http://127.0.0.1:8000backend_url
: http://127.0.0.1:9000backend_url/user/login
: 用户登陆
backend/key/create
: 生成动态 key
llm_server_url/chat/completions
: 请求大模型,这个请求会校验端侧的请求,对于不合适的请求会抛出错误
backend_url/callback/usage
: 回调接口,在 llm 服务端响应端侧请求结束后,llm 服务端会发送请求告知业务后端该次请求的内容和 token 数量
12 | cd llm-serverpython main.py |
---|
12 | cd backendpython main.py |
---|
12 | cd clientpython request_side.py |
---|
运行成功后 client 的终端可以流式输出,backend 的终端打印出evnet_id
,content
和tokens
client 终端
backend 终端