什么是AI服务中枢
在前面的章节中,我们通过接入 MCP
协议,成功把“工具的定义和执行”从客户端剥离到了服务端。只要在客户端填上 MCP 的 URL,AI 就能拥有各种超能力。
但这对于一家公司或一个团队来说,真的够了吗?
假设你们团队有 50 名员工,如果让他们在各自的电脑上运行我们之前写的“支持 MCP 的 AI 对话框”,你会立刻面临三个MCP无法解决的致命痛点:
为了解决这些问题,我们需要在企业内部再套一层“重服务端,轻客户端”的架构——AI 服务中枢。
核心设计:如何解决共享缓存冲突?
在这个架构中,所有员工的请求都由同一台服务器发出。大模型(如 DeepSeek)的底层有一个强大的上下文缓存机制(Context
Caching),能大幅降低重复前缀(如系统提示词)的费用。
但你可能会有疑问:几个员工同时用,他们的对话缓存会不会互相干扰?甚至泄露隐私?
答案是:如果不做处理,确实会互相挤占和污染。
为了解决这个问题,DeepSeek 官方提供了一个极其关键的参数:user_id。通过在请求体中传入不同的 user_id(比如员工的工号),你可以实现:
DeepSeek关于用户隔离的官方说明:
https://api-docs.deepseek.com/zh-cn/quick_start/rate_limit
简单示例
服务端代码
一、服务端 Foxtable 项目配置:
在项目事件AfterOpenProject中启动 Web 服务:
HttpServer.Prefixes.Add("http://*:18688/")
'
这里指定了端口号,避免和其他服务冲突
HttpServer.Start()
二、在HttpRequest事件中,接收客户端的提问并转发给大模型:
'''Async
If
e.Path =
"ask"
Then
e.AsyncExecute =
True
Await
Functions.ExecuteAsync("HandleAsk",
e)
e.Handled =
True
Else
e.WriteString("AI
Service Hub is running.")
End
If
三、创建自定义函数HandleAsk,这是真正的业务核心,这里不仅负责调用大模型,还负责将
user_id 注入以隔离缓存。同时,如果客户端需要 MCP 工具,中枢甚至可以替客户端去请求 MCP(这就是服务端的优势,客户端无需知晓 MCP 地址)。
Dim
e
As
RequestEventArgs = Args(0)
Dim
apiKey
As
String
=
"sk-a734b83536da45e9aedc3e42605bfb3a"
'请替换为自己的APIKey
' 1. 接收客户端发来的
JSON 数据
Dim
req
As
JObject = JsonConvert.DeserializeObject(e.PlainText)
Dim
userId
As
String
= req("user_id").ToString()
'
员工工号,用于缓存隔离
Dim
question
As
String
= req("question").ToString()
'
员工的问题
Dim
clientMessages
As
JArray = req("messages")
'
可选:客户端同步上来的历史上下文
' 2. 构造
LLMCaller(API
Key 安全地藏在服务端)
Dim
caller
As
New
LLMCaller("https://api.deepseek.com/chat/completions",
"deepseek-flash",
apiKey)
caller.SystemPrompt =
"你是乐于助人的好帮手"
If
clientMessages
IsNot
Nothing
AndAlso
clientMessages.Count > 0
Then
caller.Messages = clientMessages
'
如果客户端传了历史记录,就恢复上下文
Else
caller.Messages =
New
JArray()
'
否则开启新对话
End
If
' 【核心1】:传入
user_id,实现缓存和安全的物理隔离
caller.extra_body.user_id = userId
' 【核心2】:服务端可以统一挂载全公司通用的MCP路由或工具
caller.UserMessage = question
' 4.
调用大模型并返回结果
Dim
respObj
As
New
JObject()
If
caller.GetResult()
Then
respObj("success")
=
True
respObj("answer")
= caller.Result
respObj("messages")
= caller.Messages
'
将最新的完整上下文返回给客户端保存
Else
respObj("success")
=
False
respObj("error")
= caller.Error
End
If
e.WriteString(respObj.ToString(),
"application/json")
客户端代码
员工电脑上的 Foxtable 客户端,极其轻量,完全没有工具定义的代码,只负责收发。
以下代码可在另一个项目的命令窗口执行:
'''Async
Dim
userId
As
String
=
"EMP_1001"
'
当前登录员工的身份标识
Dim
questions()
As
String
= {"8+7=?",
"再除以三呢"}
Dim
messages
As
New
JArray()
'用于保存对话历史的JArray
Dim
hc
As
New
HttpClient("http://127.0.0.1:18688/ask")
hc.SkipError =
True
hc.ContentType =
"application/json"
For
Each
question
As
String
In
questions
hc = hc.Clone()
'HttpClient不能复用,必须克隆
'
构造请求体
Dim
reqObj
As
New
JObject()
reqObj("user_id")
= userId
reqObj("question")
= question
reqObj("messages")
= messages
'开启多轮对话
hc.Content = reqObj.ToString()
Dim
res
As
String
= hc.GetData()
If
hc.StatusCode = 200
Then
Dim
respObj
As
JObject = JsonConvert.DeserializeObject(res)
If
respObj("success").ToObject(Of
Boolean)()
Then
MessageBox.Show(respObj("answer").ToString())
messages = respObj("messages")
'对话历史存入本地,用于下一轮对话继续发送
Else
MessageBox.Show("AI
报错:"
& respObj("error").ToString())
End
If
Else
MessageBox.Show("无法连接到
AI 服务器,请检查网络。")
End
If
Next
这种架构的巨大优势
绝对的安全:大模型的APIKey 和
MCP的具体路由地址以及工具定义和执行细节,全部安全地锁在服务端。员工电脑上抓包也无法获取。
完美的多租户支持:通过
user_id,全公司共享一个大模型账号,但背后的缓存、限流、日志完全按人隔离。如果在服务端记录user_id和每次返回的Token消耗,月底就能直接按部门算账。
更强悍的扩展:因为所有请求都要过服务端,你可以轻易地在服务端加一层“敏感词过滤”,或者在工具调用前加一层“权限校验”,或新增一个“查询公司内网
ERP”的工具,全公司几百个客户端无需任何更新,立刻就能用上这些新能力。
这个“轻客户端”架构,就是真正具备企业级 SaaS 雏形的 AI 解决方案了。
如果是其他模型
在“多用户共享”的场景下,大模型平台对缓存隔离的支持目前并没有统一的行业标准,以本文档经常使用的DeepSeek和智谱为例
其他大模型也各不相同,这也再次印证了“重服务端,轻客户端”架构的必要性。因为所有的多模型差异适配、安全隔离兜底、以及未来的 API
变更,都被收敛在了服务端的一个函数里。对于前端的员工而言,他们只需要在一个统一的对话框里提问,完全不需要关心底层用的是哪家大模型,更不需要懂什么是缓存隔离。
把复杂留给系统,把极简留给用户,这就是企业级
AI 服务中枢的核心价值。