萬(wàn)字長(zhǎng)文:說(shuō)清MCP的前世今生+RAGFlow整合應(yīng)用示例
上篇文章給大家預(yù)告了我在研究些 RAG+MCP(大模型上下文協(xié)議)的事,前后斷斷續(xù)續(xù)寫(xiě)了四天,終于完成了這篇稿子,這篇試圖說(shuō)清楚兩個(gè)事情:
1、從復(fù)雜提示詞引導(dǎo)模型調(diào)用工具開(kāi)始,到 MCP 作為統(tǒng)一協(xié)議標(biāo)準(zhǔn)的變化過(guò)程;
2、小試牛刀的演示下在傳統(tǒng) RAG 基礎(chǔ)上,針對(duì)機(jī)械加工場(chǎng)景結(jié)合 MCP 的一些功能延展示例。
以下,enjoy:
1、先說(shuō)說(shuō)大模型 API 調(diào)用
先簡(jiǎn)單回顧下最簡(jiǎn)單的大模型基礎(chǔ)聊天應(yīng)用開(kāi)發(fā),也就是直接按照目標(biāo) LLM 的官方 API 文檔進(jìn)行請(qǐng)求的做法。例如,如果我們要通過(guò) Python 調(diào)用 DeepSeek-R1 模型進(jìn)行問(wèn)答,按照官方文檔說(shuō)明示例如下:
from openai import OpenAI
client = OpenAI(api_key="<DeepSeek API Key>", base_url="https://api.deepseek.com")
response = client.chat.completions.create(
model="deepseek-chat",
messages=[
{"role": "system", "content": "You are a helpful assistant"},
{"role": "user", "content": "Hello"},
],
stream=False
)
print(response.choices[0].message.content)
因?yàn)榇蠖鄶?shù)模型廠(chǎng)商都是兼容 OpenAI 規(guī)范的,也就是說(shuō)在使用 OpenAI SDK 請(qǐng)求方式下,直接替換上述的 base_url 換成其他模型地址,都是可以實(shí)現(xiàn)請(qǐng)求響應(yīng)的。比如如果要請(qǐng)求Qwen 系列模型,那base_url 就替換成: https://dashscope.aliyuncs.com/compatible-mode/v1 。進(jìn)一步說(shuō),如果要想實(shí)現(xiàn)多輪對(duì)話(huà),讓大模型“擁有記憶”滿(mǎn)足追問(wèn),以阿里的 QWQ 模型為例,可以把content字段通過(guò){'role': 'assistant', 'content':拼接后的流式輸出 content}添加到上下文。(注:無(wú)需添加reasoning_content字段)
2、復(fù)雜提示詞工程的緣起
上面提到的聊天應(yīng)用,只是基于 LLM 的已有知識(shí),回答效果在有些場(chǎng)景下不符合預(yù)期。畢竟,LLM 在訓(xùn)練完成的那一刻,它所掌握的知識(shí)就凍結(jié)了。這顯然是回答不了具有時(shí)效性或者準(zhǔn)確來(lái)說(shuō)是超出 LLM 訓(xùn)練截止完成以前時(shí)間的問(wèn)題,當(dāng)然還包括私有化的信息等。
簡(jiǎn)而言之,通過(guò)引入外部工具,可以讓 LLM 和外部世界進(jìn)行交互。OpenAI 在 23年6月正式推出了 Function Calling 功能,最初在 GPT-3.5和 GPT-4 模型上實(shí)現(xiàn)。不過(guò),在正式介紹這個(gè) Fucntion Calling 功能之前,先來(lái)聊下在此之前通過(guò)復(fù)雜提示詞引導(dǎo)模型調(diào)用工具的嘗試。
以 get_current_weather 和 get_current_weather 兩個(gè) tool 為例,下文進(jìn)行相關(guān)實(shí)現(xiàn)方式的對(duì)比說(shuō)明。
# 系統(tǒng)提示詞設(shè)計(jì)
SYSTEM_PROMPT = """
你是一個(gè)智能助手,具有以下工具:
1. 時(shí)間工具 (TIME)
- 格式:TIME: 獲取當(dāng)前時(shí)間
- 功能:返回當(dāng)前的完整日期和時(shí)間
2. 天氣工具 (WEATHER)
- 格式:WEATHER: 城市名稱(chēng)
- 功能:獲取指定城市的當(dāng)前天氣情況
3. 計(jì)算工具 (CALCULATE)
- 格式:CALCULATE: 數(shù)學(xué)表達(dá)式
- 功能:執(zhí)行數(shù)學(xué)計(jì)算
重要規(guī)則:
- 必須嚴(yán)格遵循上述格式
- 只有在確實(shí)需要使用工具時(shí)才使用
- 工具調(diào)用應(yīng)該是輸出的唯一內(nèi)容
- 使用工具后,還需要對(duì)結(jié)果進(jìn)行自然語(yǔ)言解釋
示例:
用戶(hù): 北京今天幾點(diǎn)了?
助手: TIME: 獲取當(dāng)前時(shí)間
用戶(hù): 我想知道北京的天氣
助手: WEATHER: 北京
用戶(hù): 幫我計(jì)算15乘以23
助手: CALCULATE: 15 * 23
"""
# 模擬工具實(shí)現(xiàn)
def mock_tool_execution(tool_call):
import datetime
if tool_call.startswith("TIME:"):
return datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
elif tool_call.startswith("WEATHER:"):
city = tool_call.split("WEATHER:")[1].strip()
# 模擬天氣API
return f"{city}:晴,溫度22°C,濕度45%"
elif tool_call.startswith("CALCULATE:"):
expression = tool_call.split("CALCULATE:")[1].strip()
try:
return str(eval(expression))
except Exception as e:
return f"計(jì)算錯(cuò)誤:{str(e)}"
return "未識(shí)別的工具調(diào)用"
# 對(duì)話(huà)交互模擬
def chat_interaction():
print("智能助手已啟動(dòng)。輸入'退出'結(jié)束對(duì)話(huà)。")
while True:
user_input = input("用戶(hù): ")
if user_input == '退出':
break
# 模擬模型處理
# 實(shí)際場(chǎng)景中這里會(huì)是大語(yǔ)言模型的處理
tool_match = None
# 簡(jiǎn)單的規(guī)則匹配
if "時(shí)間" in user_input:
tool_match = "TIME: 獲取當(dāng)前時(shí)間"
elif "天氣" in user_input:
city_match = user_input.replace("天氣", "").strip()
tool_match = f"WEATHER: {city_match}" if city_match else None
elif "計(jì)算" in user_input or "*" in user_input or "+" in user_input:
# 嘗試提取計(jì)算表達(dá)式
import re
match = re.search(r'(\d+\s*[\+\-\*\/]\s*\d+)', user_input)
if match:
tool_match = f"CALCULATE: {match.group(1)}"
if tool_match:
print("助手:", tool_match)
result = mock_tool_execution(tool_match)
print(f"工具執(zhí)行結(jié)果: {result}")
else:
print("助手: 很抱歉,我沒(méi)有找到合適的工具來(lái)處理您的請(qǐng)求。")
# 運(yùn)行交互
if __name__ == "__main__":
chat_interaction()
示例運(yùn)行展示效果如下:
智能助手已啟動(dòng)。輸入'退出'結(jié)束對(duì)話(huà)。
用戶(hù): 現(xiàn)在幾點(diǎn)了
助手: TIME: 獲取當(dāng)前時(shí)間
工具執(zhí)行結(jié)果: 2024-03-18 16:45:30
用戶(hù): 北京天氣怎么樣
助手: WEATHER: 北京
工具執(zhí)行結(jié)果: 北京:晴,溫度22°C,濕度45%
用戶(hù): 計(jì)算15乘以23
助手: CALCULATE: 15 * 23
工具執(zhí)行結(jié)果: 345
用戶(hù): 退出
總結(jié)來(lái)說(shuō),這種復(fù)雜提示詞的做法,主要包括以下四個(gè)特征:
- 在系統(tǒng)提示中詳細(xì)說(shuō)明輸出格式
- 使用特定的分隔符和標(biāo)記(如 XML 標(biāo)簽)
- 通過(guò)正則表達(dá)式解析模型輸出提取"函數(shù)調(diào)用"
- 在對(duì)話(huà)歷史中包含工具使用示例
這種做法的局限性首先就是表現(xiàn)為格式不可靠,大模型可能不一致地遵循指令。畢竟 Transformer 的底層邏輯還是 Next token prediction。其次,對(duì)于復(fù)雜參數(shù)結(jié)構(gòu)就更加不靠譜。當(dāng)然還有例如參數(shù)驗(yàn)證困難、占用大量提示詞空間等問(wèn)題,就不一一贅述了。
不過(guò),需要給這種做法正名的是,對(duì)于簡(jiǎn)單場(chǎng)景,可以考慮使用此類(lèi)提示詞方法,實(shí)現(xiàn)成本低,也不依賴(lài)特定模型能力,但同時(shí)需要始終警惕模型輸出的不確定性。
3、Function Calling 初露鋒芒
上述提到的通過(guò)提示詞來(lái)引導(dǎo)模型調(diào)用工具的嘗試,OpenAI 將其標(biāo)準(zhǔn)化并作為 API 的一部分提供,也就有了現(xiàn)在大家所說(shuō)的 Function Calling。
3.1創(chuàng)新之處
相比于提示詞引導(dǎo)模型調(diào)用工具的方法,主要?jiǎng)?chuàng)新之處體現(xiàn)在以下幾點(diǎn):
結(jié)構(gòu)化輸出:
確保模型能以預(yù)定義的 JSON 格式輸出函數(shù)調(diào)用參數(shù),提高了可解析性和可靠性
函數(shù)定義明確:
通過(guò)函數(shù)模式(schema)清晰定義名稱(chēng)、描述、參數(shù)類(lèi)型等
降低解析復(fù)雜度:
開(kāi)發(fā)者不需要編寫(xiě)復(fù)雜的文本解析邏輯
提高準(zhǔn)確性:
減少了模型在生成函數(shù)調(diào)用時(shí)的"幻覺(jué)"問(wèn)題
簡(jiǎn)化開(kāi)發(fā)流程:
標(biāo)準(zhǔn)化了大模型與外部工具的交互方式
BTW,并不是所有的 LLM 都支持 Function Calling,因?yàn)槟P鸵С?Function Calling 通常需要專(zhuān)門(mén)的訓(xùn)練或微調(diào)。具體來(lái)說(shuō),需要在預(yù)訓(xùn)練或者微調(diào)階段引入函數(shù)調(diào)用的示例,訓(xùn)練模型理解函數(shù)模式(schema),學(xué)習(xí)如何生成符合預(yù)期格式的 json 輸出,以及理解參數(shù)類(lèi)型和約束條件等。
3.2實(shí)現(xiàn)機(jī)制
那大模型的工具選擇和調(diào)用具體關(guān)鍵機(jī)制是什么樣的呢,這里提供一個(gè) Qwen 模型的簡(jiǎn)單示例,具體實(shí)現(xiàn)上大致分為兩步:
1、意圖推理與工具匹配
- 大模型會(huì)基于用戶(hù)輸入,對(duì)可用工具的描述和參數(shù)進(jìn)行語(yǔ)義理解
- 模型會(huì)通過(guò)自然語(yǔ)言理解和推理,判斷是否需要調(diào)用工具,以及調(diào)用哪個(gè)具體的工具
這個(gè)過(guò)程是自動(dòng)的,不需要開(kāi)發(fā)者手動(dòng)硬編碼每一個(gè)判斷邏輯
2、智能參數(shù)填充
- 模型能夠從對(duì)話(huà)上下文中提取必要的參數(shù)信息
- 對(duì)于需要特定參數(shù)的函數(shù),模型可以智能地填充這些參數(shù)值
import os
from openai import OpenAI
# 初始化OpenAI客戶(hù)端,配置阿里云DashScope服務(wù)
client = OpenAI(
# 若沒(méi)有配置環(huán)境變量,請(qǐng)用百煉API Key將下行替換為:api_key="sk-xxx",
api_key=os.getenv("DASHSCOPE_API_KEY"), # 從環(huán)境變量讀取API密鑰
base_url="https://dashscope.aliyuncs.com/compatible-mode/v1",
)
# 定義可用工具列表
tools = [
# 工具1 獲取當(dāng)前時(shí)刻的時(shí)間
{
"type": "function",
"function": {
"name": "get_current_time",
"description": "當(dāng)你想知道現(xiàn)在的時(shí)間時(shí)非常有用。",
"parameters": {} # 無(wú)需參數(shù)
}
},
# 工具2 獲取指定城市的天氣
{
"type": "function",
"function": {
"name": "get_current_weather",
"description": "當(dāng)你想查詢(xún)指定城市的天氣時(shí)非常有用。",
"parameters": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "城市或縣區(qū),比如北京市、杭州市、余杭區(qū)等。"
}
},
"required": ["location"] # 必填參數(shù)
}
}
}
]
# 節(jié)省篇幅,此處省略后續(xù)代碼
例如,如果用戶(hù)問(wèn):
"現(xiàn)在幾點(diǎn)了?" → 模型可能調(diào)用 get_current_time"
北京今天天氣怎么樣?" → 模型可能調(diào)用 get_current_weather,并自動(dòng)填充 locatinotallow="北京"
總結(jié)來(lái)說(shuō),關(guān)鍵實(shí)現(xiàn)包括:
- 工具描述(description)提供語(yǔ)義線(xiàn)索
- 參數(shù)定義(parameters)指導(dǎo)參數(shù)填充
- 模型的上下文理解和推理能力
盡管看起來(lái)很強(qiáng)大,但 Function Calling 會(huì)比較依賴(lài)模型的理解能力,而且工具描述的質(zhì)量直接影響調(diào)用準(zhǔn)確性,所以也存在誤解或錯(cuò)誤調(diào)用的可能性。
3.3Function Calling vs 傳統(tǒng)硬編碼
看到這里,可能會(huì)有盆友會(huì)疑惑 Function Calling 和傳統(tǒng)手動(dòng)函數(shù)調(diào)用外部工具實(shí)現(xiàn)邏輯的差別是啥。同樣參照上述提到的兩個(gè) tool,附上一個(gè)傳統(tǒng)硬編碼的做法示例:
import datetime
import requests
def get_current_time():
"""manually retrieve current time"""
return datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
def get_current_weather(location):
"""manually fetch weather for a specific location"""
# 模擬天氣API調(diào)用
try:
# 假設(shè)這里是一個(gè)真實(shí)的天氣API調(diào)用
# 實(shí)際場(chǎng)景中,你需要替換為真實(shí)的API端點(diǎn)和處理邏輯
response = requests.get(f"https://weather-api.example.com/current?city={location}")
weather_data = response.json()
return f"{location}的當(dāng)前天氣:{weather_data['temperature']}°C,{weather_data['condition']}"
except Exception as e:
return f"獲取{location}天氣失敗:{str(e)}"
def process_user_query(query):
"""手動(dòng)線(xiàn)性觸發(fā)函數(shù)"""
# 使用硬編碼的條件判斷
if "時(shí)間" in query:
return get_current_time()
elif "天氣" in query:
# 需要額外的參數(shù)提取邏輯
import re
location_match = re.search(r'([\u4e00-\u9fff]+)天氣', query)
if location_match:
location = location_match.group(1)
return get_current_weather(location)
else:
return "請(qǐng)?zhí)峁┚唧w城市名稱(chēng)"
else:
return "無(wú)法理解您的請(qǐng)求"
# 模擬用戶(hù)交互
def main():
while True:
user_input = input("請(qǐng)輸入您的問(wèn)題(輸入'退出'結(jié)束):")
if user_input == '退出':
break
response = process_user_query(user_input)
print("系統(tǒng)回復(fù):", response)
if __name__ == "__main__":
main()
示例運(yùn)行結(jié)果:
# 可能的交互示例
請(qǐng)輸入您的問(wèn)題(輸入'退出'結(jié)束):現(xiàn)在幾點(diǎn)了
系統(tǒng)回復(fù):2024-03-18 15:30:45
請(qǐng)輸入您的問(wèn)題(輸入'退出'結(jié)束):北京天氣怎么樣
系統(tǒng)回復(fù):北京的當(dāng)前天氣:15°C,晴朗
請(qǐng)輸入您的問(wèn)題(輸入'退出'結(jié)束):退出
這個(gè)示例清晰地展示了傳統(tǒng)手動(dòng)觸發(fā)方法的局限性:代碼邏輯復(fù)雜、擴(kuò)展性差、對(duì)用戶(hù)輸入的理解能力有限。相比之下,F(xiàn)unction Calling 提供了一種更智能、更靈活的工具調(diào)用范式。
4、GPTs 的試圖”大一統(tǒng)“
在正式說(shuō)到 MCP 之前,還需要再聊下 GPTs 的故事。上述提到的 Function Calling 固然有很多好處,但是全部自己手動(dòng)寫(xiě)似乎有點(diǎn)太麻煩,于是大聰明 OpenAI 就在 23 年 11 月初的開(kāi)發(fā)者大會(huì)上,首次介紹了 GPTs 的概念,用戶(hù)不需要任何編程知識(shí),只需要通過(guò)自然語(yǔ)言指令和上傳知識(shí)庫(kù),就能夠輕松的定制自己的個(gè)性化 GPT。p.s.此舉還有個(gè)實(shí)際效果是讓全球開(kāi)發(fā)者主動(dòng)的為 ChatGPT 開(kāi)發(fā) Funtion Calling 工具。
此處忽略后來(lái)的狗血宮斗插曲,GPT Store 在 24 年 1 月對(duì)外正式發(fā)布,我查到的數(shù)據(jù)是,截止到 24 年1月份,用戶(hù)自主創(chuàng)建的 GPTs 據(jù)說(shuō)就超過(guò)了 300 萬(wàn)個(gè)。
想起我 23 年 11 月 11 號(hào)發(fā)布第一個(gè)自己的 GPTs 的時(shí)候,當(dāng)時(shí)看到 GPTs 導(dǎo)航站的統(tǒng)計(jì)有 4000+個(gè),當(dāng)時(shí)感慨發(fā)布一周就這么快上新,不曾想后來(lái)會(huì)如此井噴。
下面展示一個(gè)獲取當(dāng)前時(shí)間的 GPTs 示例,并解釋其工作機(jī)制。
# 1. manifest.json
{
"schema_version": "v1",
"name_for_human": "Time Assistant",
"name_for_model": "time_tool_gpt",
"description_for_human": "A GPT that can retrieve current time information across different time zones.",
"description_for_model": "You are a helpful time assistant capable of retrieving current time information precisely and efficiently.",
"auth": {
"type": "none"
},
"api": {
"type": "openapi",
"url": "https://your-domain.com/openapi.yaml"
},
"logo_url": "https://example.com/time-assistant-logo.png",
"contact_email": "support@example.com",
"privacy_policy_url": "https://example.com/privacy"
}
# 2. openapi.yaml
openapi: 3.0.0
info:
title: Time Assistant API
version: 1.0.0
description: API for retrieving current time information
servers:
- url: https://your-domain.com/api/v1
paths:
/current-time:
get:
summary: Get current time
operationId: getCurrentTime
parameters:
- name: timezone
in: query
required: false
schema:
type: string
default: "UTC"
description: Timezone to retrieve current time (e.g., 'UTC', 'America/New_York', 'Asia/Shanghai')
responses:
'200':
description: Successful time retrieval
content:
application/json:
schema:
type: object
properties:
current_time:
type: string
example: "2024-03-18T15:30:45Z"
timezone:
type: string
example: "UTC"
timestamp:
type: integer
example: 1710770445
4.1核心文件解析
1、manifest.json
定義 GPT 的基本元數(shù)據(jù)
指定 API 交互方式
提供人類(lèi)和模型可讀的描述
配置身份驗(yàn)證和 API 接入點(diǎn)
2、 openapi.yaml
定義具體的 API 接口規(guī)范
描述可用的端點(diǎn)、參數(shù)和響應(yīng)結(jié)構(gòu)
提供工具調(diào)用的接口約定
4.2使用場(chǎng)景示例
"現(xiàn)在幾點(diǎn)了?"、"北京現(xiàn)在是什么時(shí)間?"、"告訴我紐約當(dāng)前時(shí)間"
GPT 會(huì)根據(jù)這些問(wèn)題:
識(shí)別時(shí)間查詢(xún)意圖
選擇/current-time接口
傳入相應(yīng)的 timezone 參數(shù)
4.3局限性
GPTs 完全綁定 OpenAI 生態(tài)系統(tǒng),不兼容其他大模型平臺(tái)(Anthropic、Google 等),無(wú)法跨平臺(tái)移植和使用。在功能實(shí)現(xiàn)方面,工具調(diào)用方式高度標(biāo)準(zhǔn)化,缺乏靈活的參數(shù)傳遞機(jī)制,不支持復(fù)雜的狀態(tài)管理,也無(wú)法實(shí)現(xiàn)復(fù)雜的工作流編排。另外從托管方式上看,完全依賴(lài) OpenAI 云平臺(tái),不支持私有化部署,無(wú)法進(jìn)行深度定制和二次開(kāi)發(fā)等。
總結(jié)來(lái)說(shuō),GPTs 本質(zhì)上是一個(gè)封閉、受限的生態(tài)系統(tǒng),適合快速構(gòu)建簡(jiǎn)單的交互工具,但對(duì)于需要高度定制和靈活性的場(chǎng)景,其局限性非常明顯。對(duì)于追求技術(shù)自主可控的企業(yè)和開(kāi)發(fā)者,GPTs 并不是一個(gè)好的選擇。
5、MCP 推出的偶然和必然
模型上下文協(xié)議 (MCP) 24 年 11 月由 Anthropic 發(fā)布,總結(jié)來(lái)說(shuō)就是兩個(gè)要點(diǎn),首先是一個(gè)協(xié)議兼容所有的 AI 應(yīng)用,另外在 Function Calling 基礎(chǔ)上增加了資源和提示詞的功能。
5.1工具調(diào)用示例
先看下 MCP 實(shí)現(xiàn)工具調(diào)用示例, 這里以 get_current_time 的工具為例:
用戶(hù)提問(wèn):現(xiàn)在幾點(diǎn)了?
MCP 執(zhí)行流程:
1、請(qǐng)求階段:
{
"messages": [
{"role": "user", "content": "現(xiàn)在幾點(diǎn)了?"}
],
"context": {
"tools": [
{
"type": "function",
"function": {
"name": "get_current_time",
"description": "當(dāng)你想知道現(xiàn)在的時(shí)間時(shí)非常有用。",
"parameters": {}
}
},
{...} // 另一個(gè)工具定義
]
}
}
2、模型響應(yīng)階段
{
"response": {
"model": "DeepSeek-R1:32b",
"content": [
{
"type": "tool_use",
"id": "call_1",
"tool_use": {
"name": "get_current_time",
"parameters": {}
}
}
]
}
}
3、工具執(zhí)行階段:系統(tǒng)執(zhí)行g(shù)et_current_time函數(shù),返回結(jié)果
{
"messages": [
{"role": "user", "content": "現(xiàn)在幾點(diǎn)了?"},
{
"role": "assistant",
"content": [
{
"type": "tool_use",
"id": "call_1",
"tool_use": {
"name": "get_current_time",
"parameters": {}
}
}
]
},
{
"role": "tool",
"tool_use_id": "call_1",
"content": {"time": "2025-03-18T14:30:00Z"}
}
]
}
4、最終響應(yīng)
{
"response": {
"model": "DeepSeek-R1:32b",
"content": [
{
"type": "text",
"text": "現(xiàn)在的時(shí)間是北京時(shí)間2025年3月18日22:30(世界協(xié)調(diào)時(shí)間14:30)。"
}
]
}
}
5.2執(zhí)行步驟拆解
用戶(hù)查詢(xún)解析:
模型分析用戶(hù)問(wèn)題,確定需要調(diào)用哪個(gè)工具
對(duì)于需要參數(shù)的工具,提取必要參數(shù)(如城市名稱(chēng))
工具調(diào)用請(qǐng)求生成:
模型生成標(biāo)準(zhǔn)化的工具調(diào)用請(qǐng)求,包含工具名稱(chēng)和參數(shù)
每個(gè)工具調(diào)用都有唯一 ID,方便后續(xù)追蹤
工具執(zhí)行:
系統(tǒng)接收工具調(diào)用請(qǐng)求
執(zhí)行相應(yīng)函數(shù)并獲取結(jié)果
將結(jié)果以標(biāo)準(zhǔn)格式返回,關(guān)聯(lián)到對(duì)應(yīng)的工具調(diào)用 ID
結(jié)果整合與回復(fù)生成:
模型接收工具調(diào)用結(jié)果
將結(jié)果整合到上下文中
生成自然語(yǔ)言回復(fù)給用戶(hù)
5.3MCP 資源訪(fǎng)問(wèn)控制
MCP 的資源訪(fǎng)問(wèn)控制功能可以精確定義大模型如何安全地訪(fǎng)問(wèn)企業(yè)內(nèi)部資源。以機(jī)械加工企業(yè)部署 RAG 系統(tǒng)訪(fǎng)問(wèn) MySQL 數(shù)據(jù)庫(kù)為例做個(gè)效果演示:
{
"messages": [
{"role": "user", "content": "查詢(xún)公司圓鋼硬度標(biāo)準(zhǔn)"}
],
"context": {
"resources": [
{
"type": "database",
"id": "materials_db",
"config": {
"engine": "mysql",
"connection": {
"host": "192.168.1.100",
"database": "materials_specs",
"schema": "standards"
},
"permissions": ["read"],
"tables": ["material_standards", "quality_tests"],
"access_level": "restricted"
}
}
],
"tools": [
{
"type": "function",
"function": {
"name": "query_database",
"description": "查詢(xún)企業(yè)材料標(biāo)準(zhǔn)數(shù)據(jù)庫(kù)",
"parameters": {
"type": "object",
"properties": {
"resource_id": {"type": "string"},
"query_type": {"type": "string", "enum": ["standard", "test", "material"]},
"material_category": {"type": "string"},
"standard_type": {"type": "string"}
},
"required": ["resource_id", "query_type"]
}
}
}
]
}
}
執(zhí)行過(guò)程
權(quán)限驗(yàn)證層:系統(tǒng)首先驗(yàn)證當(dāng)前用戶(hù)對(duì)材料數(shù)據(jù)庫(kù)的訪(fǎng)問(wèn)權(quán)限
資源邊界定義:MCP 限制只能訪(fǎng)問(wèn)特定表(材料標(biāo)準(zhǔn)和質(zhì)量測(cè)試)
查詢(xún)限制:只允許讀取操作,禁止寫(xiě)入或修改
數(shù)據(jù)篩選:可設(shè)置只返回非機(jī)密等級(jí)的標(biāo)準(zhǔn)數(shù)據(jù)
5.4實(shí)際應(yīng)用優(yōu)勢(shì)
數(shù)據(jù)隔離:確保 LLM 只能訪(fǎng)問(wèn)授權(quán)表,無(wú)法看到客戶(hù)數(shù)據(jù)、財(cái)務(wù)信息等敏感數(shù)據(jù)
審計(jì)追蹤:記錄所有數(shù)據(jù)庫(kù)查詢(xún),便于合規(guī)審計(jì)
精細(xì)控制:可針對(duì)不同部門(mén)用戶(hù)設(shè)置不同的數(shù)據(jù)訪(fǎng)問(wèn)范圍
防止 SQL 注入:MCP 可以驗(yàn)證和清理查詢(xún)請(qǐng)求,增強(qiáng)安全性
5.5提示詞增強(qiáng)功能
MCP 的提示詞增強(qiáng)功能可以為 LLM 提供額外上下文和專(zhuān)業(yè)指導(dǎo),使其更好地處理專(zhuān)業(yè)領(lǐng)域問(wèn)題,此處同樣以機(jī)械加工企業(yè)為例:
{
"messages": [
{"role": "user", "content": "CNC加工中心出現(xiàn)S-02錯(cuò)誤代碼,如何排查?"}
],
"context": {
"prompts": [
{
"id": "mechanical_expertise",
"content": "你是一名專(zhuān)業(yè)的機(jī)械加工技術(shù)顧問(wèn),熟悉CNC設(shè)備操作和故障排除。總是優(yōu)先考慮安全因素,并遵循ISO 9001質(zhì)量標(biāo)準(zhǔn)流程。在回答前,先確認(rèn)錯(cuò)誤的嚴(yán)重程度,然后按照'初步檢查→可能原因→解決步驟→預(yù)防措施'的順序組織回答。"
},
{
"id": "company_terminology",
"content": "使用公司標(biāo)準(zhǔn)術(shù)語(yǔ):'加工中心'指HAAS VF-2SS設(shè)備,'S系列錯(cuò)誤'表示主軸系統(tǒng)故障,'技術(shù)處理單'指企業(yè)內(nèi)部ERP系統(tǒng)中的故障報(bào)告表單。參考設(shè)備代號(hào)時(shí)使用'HC-'前綴。"
},
{
"id": "safety_guidelines",
"content": "任何設(shè)備維修建議必須包含以下安全提醒:'維修前確保設(shè)備完全斷電并上鎖掛牌,穿戴適當(dāng)?shù)腜PE裝備,遵循公司MP-S-001安全手冊(cè)規(guī)定的維修流程。'"
}
],
"resources": [
{
"type": "vector_database",
"id": "equipment_manual_db",
"config": {
"collection": "equipment_manuals",
"filters": {"equipment_type": "CNC"}
}
}
]
}
}
5.6應(yīng)用場(chǎng)景與優(yōu)勢(shì)
專(zhuān)業(yè)術(shù)語(yǔ)統(tǒng)一
系統(tǒng)能理解并使用企業(yè)內(nèi)部特定術(shù)語(yǔ)(如"HC-1500"指特定型號(hào)的加工中心)
確保回答符合企業(yè)標(biāo)準(zhǔn)規(guī)范和命名習(xí)慣
流程標(biāo)準(zhǔn)化
強(qiáng)制模型按照企業(yè)工藝流程標(biāo)準(zhǔn)回答問(wèn)題
例如:CNC 故障診斷必須先檢查安全狀態(tài),再進(jìn)行電氣和機(jī)械系統(tǒng)排查
知識(shí)融合
結(jié)合行業(yè)通用知識(shí)與企業(yè)特定知識(shí)
例如:將 ISO 標(biāo)準(zhǔn)與企業(yè)內(nèi)部工藝規(guī)范結(jié)合
安全與合規(guī)保障
針對(duì)高風(fēng)險(xiǎn)操作自動(dòng)添加安全警告
例如:加工特殊材料時(shí)提示需要特定防護(hù)措施和環(huán)保要求
5.7具體應(yīng)用實(shí)例
機(jī)械設(shè)備故障診斷
提示詞增強(qiáng):設(shè)備故障回答必須包含:故障代碼解釋、可能原因(按概率排序)、診斷步驟(從簡(jiǎn)單到復(fù)雜)、維修所需工具清單、預(yù)計(jì)維修時(shí)間
工藝參數(shù)推薦
提示詞增強(qiáng):回答材料加工參數(shù)問(wèn)題時(shí),必須考慮企業(yè)現(xiàn)有設(shè)備能力限制,并參考企業(yè)工藝數(shù)據(jù)庫(kù)中的歷史成功案例
質(zhì)量輔助控制
提示詞增強(qiáng):分析質(zhì)量問(wèn)題時(shí),自動(dòng)關(guān)聯(lián)企業(yè)SPC數(shù)據(jù),引用相關(guān)ISO標(biāo)準(zhǔn)條款,并建議適用的企業(yè)標(biāo)準(zhǔn)檢測(cè)方法
6、RAGFlow 與 MCP 整合方案示例
為了實(shí)現(xiàn)企業(yè)多源數(shù)據(jù)的接入,這里演示下最近項(xiàng)目中初步實(shí)踐通過(guò) MCP 將 MySQL、EMS 等系統(tǒng)數(shù)據(jù)整合到 RAGFlow 框架中做法,供參考。
6.1架構(gòu)設(shè)計(jì)
┌─────────────────────────────────────────────────┐
│ RAGFlow + MCP 集成架構(gòu) │
├─────────────────┬───────────────────────────────┤
│ │ LLM調(diào)用層 │
│ ├───────────────────────────────┤
│ 原有RAGFlow │ 向量檢索層 │
│ ├───────────────────────────────┤
│ │ 文檔處理層 │
├─────────────────┼───────────────────────────────┤
│ │ MCP適配器層 ?──────────┼──? MCP協(xié)議定義
│ ├───────────────────────────────┤
│ MCP擴(kuò)展部分 │ 資源訪(fǎng)問(wèn)控制層 │
│ ├───────────────────────────────┤
│ │ 多源數(shù)據(jù)連接層 │
└─────────────────┴───────────────────────────────┘
▲ ▲ ▲
│ │ │
┌────────┘ │ └────────┐
│ │ │
┌────────┐ ┌────────┐ ┌────────┐
│ MySQL │ │ EMS │ │ 其他系統(tǒng)│
└────────┘ └────────┘ └────────┘
6.2參考案例
場(chǎng)景:工程師查詢(xún)?cè)O(shè)備故障和相關(guān)維修歷史
(此處打個(gè)廣告,相關(guān)示例源碼請(qǐng)移步我的知識(shí)星球)
1、用戶(hù)查詢(xún)
"數(shù)控車(chē)床HC-2000最近頻繁報(bào)E-35錯(cuò)誤,是否有相關(guān)的維修記錄?"
2、系統(tǒng)處理流程
MCP 請(qǐng)求生成
{
"response": {
"model": "DeepSeek-R1:32b",
"content": [
{
"type": "tool_use",
"id": "call_1",
"tool_use": {
"name": "query_equipment_status",
"parameters": {
"resource_id": "production_db",
"equipment_id": "HC-2000",
"query_type": "maintenance_history"
}
}
}
]
}
}
數(shù)據(jù)庫(kù)查詢(xún)執(zhí)行:系統(tǒng)從 MySQL 數(shù)據(jù)庫(kù)中查詢(xún) HC-2000 的維修記錄工具執(zhí)行結(jié)果
{
"data": [
{
"date": "2025-02-15",
"issue": "E-35錯(cuò)誤:主軸編碼器信號(hào)異常",
"solution": "更換主軸編碼器,調(diào)整編碼器間隙"
},
{
"date": "2025-01-20",
"issue": "E-35錯(cuò)誤:斷續(xù)出現(xiàn)",
"solution": "清潔線(xiàn)纜接頭,重新固定連接器"
}
]
}
向量檢索補(bǔ)充:同時(shí)系統(tǒng)從向量數(shù)據(jù)庫(kù)檢索與"E-35 錯(cuò)誤"相關(guān)的設(shè)備手冊(cè)和技術(shù)文檔
最終回復(fù)生成:系統(tǒng)綜合數(shù)據(jù)庫(kù)查詢(xún)結(jié)果和向量檢索結(jié)果,生成完整回答
用戶(hù)獲得回答
根據(jù)維修記錄,HC-2000數(shù)控車(chē)床近期兩次出現(xiàn)E-35錯(cuò)誤(主軸編碼器信號(hào)異常):
1. 2025年2月15日:更換了主軸編碼器并調(diào)整了編碼器間隙
2. 2025年1月20日:清潔了線(xiàn)纜接頭并重新固定連接器
從設(shè)備手冊(cè)分析,E-35錯(cuò)誤通常由以下原因?qū)е拢?- 編碼器線(xiàn)纜損壞或接觸不良(占70%的案例)
- 編碼器本身故障(約20%的案例)
- 主軸驅(qū)動(dòng)電路問(wèn)題(約10%的案例)
建議采取以下步驟:
1. 檢查編碼器線(xiàn)纜是否有磨損或松動(dòng)
2. 測(cè)量線(xiàn)纜連接器與編碼器接口電阻值(應(yīng)<0.2Ω)
3. 使用示波器檢查編碼器信號(hào)質(zhì)量
根據(jù)企業(yè)SOP-M1001標(biāo)準(zhǔn),此類(lèi)問(wèn)題需填寫(xiě)《設(shè)備異常跟蹤表》并由維修部門(mén)評(píng)估是否需要調(diào)整預(yù)防性維護(hù)計(jì)劃。
7、整合技術(shù)要點(diǎn)
保持模塊化設(shè)計(jì)
將 MCP 適配器作為獨(dú)立模塊添加,不破壞現(xiàn)有 RAGFlow 核心功能
使用適配器模式連接 RAGFlow 和企業(yè)數(shù)據(jù)源
統(tǒng)一資源訪(fǎng)問(wèn)接口
為所有數(shù)據(jù)源(向量庫(kù)、MySQL、EMS 等)創(chuàng)建統(tǒng)一的資源訪(fǎng)問(wèn)接口
確保權(quán)限控制一致性
查詢(xún)路由機(jī)制
開(kāi)發(fā)智能查詢(xún)路由,自動(dòng)決定是使用向量檢索還是結(jié)構(gòu)化數(shù)據(jù)查詢(xún)
支持混合查詢(xún)模式,綜合多種數(shù)據(jù)源結(jié)果
緩存與性能優(yōu)化
對(duì)頻繁查詢(xún)的數(shù)據(jù)庫(kù)結(jié)果進(jìn)行緩存
使用批處理減少數(shù)據(jù)庫(kù)連接開(kāi)銷(xiāo)
部署考慮
確保數(shù)據(jù)庫(kù)連接器在企業(yè)內(nèi)網(wǎng)環(huán)境正確配置
處理網(wǎng)絡(luò)隔離環(huán)境下的連接問(wèn)題
8、LLM 工具調(diào)用技術(shù)演進(jìn)的一點(diǎn)思考
從復(fù)雜提示詞→Function Calling→GPTs 插件→MCP 協(xié)議的技術(shù)演進(jìn)路徑,非常類(lèi)似于幾個(gè)經(jīng)典技術(shù)標(biāo)準(zhǔn)化的發(fā)展歷程,特別是 Web 技術(shù)、互聯(lián)網(wǎng)協(xié)議和 API 標(biāo)準(zhǔn)化的過(guò)程。以 Web API 的標(biāo)準(zhǔn)化進(jìn)程類(lèi)比,
Web API 演進(jìn) | AI 工具調(diào)用演進(jìn) |
早期:RPC(遠(yuǎn)程過(guò)程調(diào)用)各自實(shí)現(xiàn) | 早期:提示詞工程中的工具調(diào)用 |
發(fā)展期:SOAP 和 XML-RPC 等框架 | 發(fā)展期:Function Calling 的 JSON 結(jié)構(gòu)化調(diào)用 |
成熟期:REST API 成為主流 | 成熟期:GPTs 等平臺(tái)專(zhuān)屬實(shí)現(xiàn) |
統(tǒng)一期:GraphQL 等新一代標(biāo)準(zhǔn) | 統(tǒng)一期:MCP 作為統(tǒng)一協(xié)議 |
觀察 LLM 工具調(diào)用和相關(guān)技術(shù)標(biāo)準(zhǔn)的發(fā)展,似乎可以歸納出技術(shù)標(biāo)準(zhǔn)化的普遍規(guī)律:
探索期:
各方以自己的方式解決問(wèn)題(提示詞工程)
初步標(biāo)準(zhǔn)化:
出現(xiàn)基礎(chǔ)結(jié)構(gòu)化方案(Function Calling)
平臺(tái)主導(dǎo)期:
主要平臺(tái)推出自己的解決方案(GPTs 插件)
開(kāi)放標(biāo)準(zhǔn)期:
形成統(tǒng)一開(kāi)放標(biāo)準(zhǔn)(MCP 協(xié)議)
從歷史經(jīng)驗(yàn)看,統(tǒng)一標(biāo)準(zhǔn)的出現(xiàn)通常會(huì)帶來(lái)技術(shù)領(lǐng)域的爆發(fā)式增長(zhǎng),如 Web 標(biāo)準(zhǔn)統(tǒng)一后的互聯(lián)網(wǎng)繁榮。MCP 協(xié)議的出現(xiàn),很可能標(biāo)志著 LLM 工具生態(tài)即將進(jìn)入一個(gè)快速發(fā)展、廣泛應(yīng)用的新階段。
25 年由此說(shuō)來(lái),值得期待更多垂直場(chǎng)景的最佳實(shí)踐了。