什么是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 服务中枢的核心价值。


本页地址:http://www.foxtable.com/webhelp/topics/7235.htm