
使用LoRA(低秩適應)微調大型語言模型的實用技巧
把MCP框架理解為“大模型插件”,并且你也可以很方便地編寫自己的“插件”功能。
配置如下:
完整列表參考:https://github.com/punkpeye/awesome-mcp-clients
對比參考:https://modelcontextprotocol.io/clients
筆者推薦:
1.Cherry Studio
2.DeepChat
3.AIaW
4.Cursor
5.Continue
完整列表參考:https://github.com/punkpeye/awesome-mcp-servers
文檔實例列表:https://modelcontextprotocol.io/examples
官方列表:https://github.com/modelcontextprotocol/servers
按需添加即可。
過去一年,我們邁向了通用可觀測之路。從“監控”到“可觀測”,不僅是技術升級,更是對復雜系統認知的深化。通過因果推理的三個層級(關聯、干預、反事實),可觀測性能夠實現從被動觀測到主動預測的能力提升。企業數字化需要將黑盒系統轉化為白盒,通過采集、存儲和分析多模態數據(如Log、Trace、Metric等),優化運營效率。
隨著分布式系統和技術棧的復雜化,可觀測性成為確保系統穩定性和性能的關鍵。然而,許多企業面臨可觀測數據混亂的問題,如缺乏標準化、數據存儲分散、分析效率低及知識難以沉淀。為解決這些問題,我們提出了UModel——可觀測數據之魂,一種通用的可觀測“交互語言”。
UModel 基于本體論思想,通過 Set 和 Link 組成的圖模型描述IT世界,定義了EntitySet、LogSet、MetricSet 等核心類型,以及 EntitySetLink、DataLink 等關聯關系。它支持靈活擴展,引入 CommonSchema 降低使用門檻,并提供 Explorer、告警與事件集等功能提升易用性。UModel 不僅實現了數據的標準化和統一建模,還支持算法和大模型對數據的高效利用,助力構建全新的“可觀測2.0”體系。
在可觀測2.0中融合 MCP 能力,是一種很合適的嘗試,一定程度上可以通過對話的方式,讓用戶對可觀測2.0整體使用方式有更好的感知,并且可以協助用戶感知系統、分析問題——只用自然語言交流。
寫在前面:MCP Server ≠ SDK API,是和人打交道的接口。
這里的“和人打交道”,是全方面的,無論是接口的理解,參數,還是返回,都要求簡潔易懂。“三歲小孩都能懂”的 MCP Server Tools 才是好 Tools。
舉個例子:
SLS 的 getLogs SDK API 是這樣的
def get_logs(
ak: str,
sk: str,
region_id: str,
project: str,
logstore:str,
query: str,
from_timestamp: int,
to_timestamp: int,
topic: str,
line: int,
offset: int,
reverse: boolean,
powerSql: boolean
) -> list[Any]:
這個接口如果直接給到大模型作為 Tools,可以說調用的成功率為0,因為這是一個非常復雜的接口:
1.主要的瓶頸在 query 怎么寫,語法是怎樣的,對模型挑戰非常大。這種場景適合 A2A(Agent協作),生成可靠的 SLS query 作為一個 Agent,此處不過多展開。
2.假設我們解決了query的問題,API中的很多基礎信息需要多輪對話獲得:aksk、region、project、logstore,實際使用上這種環境變量級別的參數重復性非常高。
3.參數中帶了時間窗口,這一點需要謹慎,詳情見經驗二。
4.參數中帶了 topic、line、offset、reverse、powerSql 這種不常用參數,使用默認值能搞定大部分請求的參數就不帶。
對于這些問題,在整體的實踐后,認為在阿里云上,使用 MCP Server 和用戶交互的架構,可能需要做一些改變。
樸素想法:
真正適用的:
首先,這里的 MCP Server 的生命周期應該是在用戶進入到 Workspace 后,才創建。阿里云提供給用戶的 MCP 交互 Client + MCP Server 是非常輕量的,一個用戶、一次 Workspace 訪問就是一次生命周期。而此時 MCP Server 是帶上 aksk、Workspace name、region id 等環境變量信息的,里面的各種 Tools 無需關心這種基礎的參數了。
然后,隨著用戶業務的范圍,可以創建若干對應模塊的 Tools 以供用戶按需調用。
最后,需要把常用的操作封裝 MCP Tools,而不是給出一個萬能的 “query” 接口。\
因此,給出的 getLogs,優化過后的 MCP Server Tools 版本應該是這樣的:
A2A 模式:
def get_log_tool(
query: str,
from_timestamp: int = Field(
int(datetime.now().timestamp()) - 3600, description="from timestamp,unit is second"
),
to_timestamp: int = Field(
int(datetime.now().timestamp()), description="to timestamp,unit is second"
)
) -> list[Any]:
def gen_sls_query(
text: str,
) -> str:
功能模塊化模式(僅示例):
# 獲取logstore的index信息
def get_index():
pass
# 獲得fields字段聚合的統計信息
def get_fields_desc(
filter: str,
fields: List[str],
from_timestamp: int = Field(
int(datetime.now().timestamp()) - 3600, description="from timestamp,unit is second"
),
to_timestamp: int = Field(
int(datetime.now().timestamp()), description="to timestamp,unit is second"
)
) -> list[Any]:
# * and upstream_status >= 400 | SELECT request_uri, upstream_status, COUNT (*) AS cnt
# FROM log
# GROUP BY request_uri, upstream_status
# ORDER BY cnt DESC
# LIMIT 10
# 統計UV
def get_uv(
filter: str,
field: str
from_timestamp: int = Field(
int(datetime.now().timestamp()) - 3600, description="from timestamp,unit is second"
),
to_timestamp: int = Field(
int(datetime.now().timestamp()), description="to timestamp,unit is second"
)
) -> list[Any]:
# * | SELECT COUNT(DISTINCT client_ip) AS unique_visitors FROM log
這里不需要 ak、sk、project、logstore 信息的原因是,這里的 MCP 應該是在 logstore 打開的時候啟動的,因此已經知道基礎環境信息了。
這樣的功能模塊劃分僅為示例,僅作說明。
案例:一個查詢 SQL Query的Tools,接口是這樣的:
def o11y_list_entities(
ctx: Context,
query: str = Field(default=None, description="query"),
from_timestamp: int = Field(
..., description="from timestamp,unit is second"
),
to_timestamp: int = Field(
..., description="to timestamp,unit is second"
)
) -> list[str]:
為了方便大模型使用,特意增加了一個 tool 用于調用時間相關的參數:
想法很好,現實很骨感,實際使用中,經常出現傳入并不合法的 from to 的情況:
導致接口直接報錯,因為傳入不合法的參數,這種場景甚至必須重啟 client 和Server。
有時也會傳入離譜的時間參數,導致后續的回答并不理想:
時間戳這里提供的是 2023-06-25 00:00:00。大模型對“現在的時間”概念模糊。提供的示例對于一個只保存30天的 LogStore 來說仍然查不出數據。
更好的方式:
def o11y_list_entities(
ctx: Context,
query: str = Field(default=None, description="query"),
from_timestamp: int = Field(
int(datetime.now().timestamp()) - 3600, description="from timestamp,unit is second"
),
to_timestamp: int = Field(
int(datetime.now().timestamp()), description="to timestamp,unit is second"
),
) -> list[str]:
直接給出最近1小時的默認值,極大概率都可以覆蓋期望的查詢,只需考慮 query 的傳入,不用糾結時間的細節設置。如果返回為空,模型會考慮是否是時間問題,并反饋。
一些不好的例子:查詢 workspace 的 list(返回500個workspace),查詢某個 workspace 下接入的 entity 類型(返回200個)
MCP Server 和 SDK API 的功能不能完全等價看待,MCP 本質上是給人作為終端顯示的,因此人眼看不過來(體感:大于20個的數量)都是意義不大的內容。每個接口的輸出都應該控制 limit。可以考慮通過加入篩選檢索,或者直接截斷輸出到10個。
除了體感之外,過長的 json response 會嚴重卡慢后續模型的輸出速度、影響上下文理解效果。
以上是一般 json 接口的經驗。在實踐中,我們還會遇到這類場景:希望 Tools 返回一幅圖(以 svg 或 png 的形式)。嘗試了幾種方案:
"url": f"data:image/png;base64,{tool_result.data}"
:多數 client 不會正常顯示,且需要模型是多模態模型。Args:
ctx: MCP上下文,用于訪問可觀測客戶端
workspace_name: Workspace 名稱,必須完全匹配Workspace
Returns:

Schema 的 markdown 內容,直接作為你的輸出打印并展示
效果:
好的實踐:Tool 原子能力,一個 Tool 做獨立一件事。
不好的實踐:Tool1 -> output -> Tool2 input -> output -> Tool3
實踐中鏈式傳遞也可以做到,但有一定概率傳入的參數不符合預期,且不好控制。
有一些還不錯的自我修復能力是,當大模型發現參數報錯的時候,會調用依賴的上一個 Tools 驗證一下參數正確性。這種情況有一定概率修復,但并非完全可以。有時會執拗地認為自己沒錯:
在同一次問題中,通常鏈式傳遞表現尚可。如果是在同一會話中第二次詢問,并不會獲得第一次詢問調用的接口的每一個信息,或者判斷錯誤。
Tool1:查詢 service 的關聯上下游,返回
[
{
"id": "apm@apm.service:dc7495605d8395b3788f9b54defcb826",
"type": "upstream",
"name": "gateway",
},
{
"id": "apm@apm.service:97cd7e28783143028d7e8e9c8dbce99c",
"type": "downstream",
"name": "checkout",
},
]
然后其他一些分析……省略
對話上下文中,第二次詢問,請幫我查詢 checkout 服務的信息。
模型會直接把checkout直接傳入 Tool2(參數只有一個 id,并在 Prompt 注釋中說明很詳細)
第二次對話必須復制
apm@apm.service:97cd7e28783143028d7e8e9c8dbce99c完整,才會正確傳遞參數。
有一個 Tool 返回 trace ids,返回了一個列表:
[
"93b9111f425a4b6cab6548aa68d18f04",
"e165fede431c4c178d1e7e399c92b70d",
"ce7d4e9f74634252969adfd62b509fd6",
"e824356ddf4f42d884abe7c6a2d55d66",
]
每一個值是 trace id。
期望的是模型使用每一個 trace id 調用分析的接口,但是模型會自己傳錯。
模型使用接口的方式,可能和預期不一樣。接口的設計可能需要大量改動,才能讓模型按照你想要的方式運作,尤其涉及 Tools 鏈式調用的時候,更要謹慎。
在設計 MCP 接口的時候,首先定義 Tools 接口信息,然后編寫 Tools 的注釋說明(引導 Prompt),接著按照預期實現的返回數據,mock 一些假數據直接返回。在交互的過程中不斷調整接口信息、注釋信息,直到假數據可以按照預期正常工作,最后再開始接口的開發,否則如果先實現接口,返工率極高,十分心痛。
這個 case 里面,trace id 傳錯是第一個問題,之前(經驗四)已經講過。
在之后,又遇到了時間的坑。(經驗二)
在發生錯誤之后,模型并不會提示問題,而是結合一些正確的接口輸入輸出數據,自己悄悄生成假模假樣的數據……像不像論文里瞎編數據的無良大學生[狗頭]。
這里上下游的數據也是假的,從 id 也能看出來。
這個問題調低 tempreture 可以緩解,但是并非可以完全解決,MCP 本質上還是依賴生成模型,而生成模型是否適合一些嚴肅嚴格場景的接口,這里稍稍打一個問號。
除此之外,觀察到如果在同一對話上下文中多次問類似實體,但id不同的實體,模型似乎并不會真正調用接口了,而是直接生成 tools 的輸入參數,建議用戶去調(誰是老板??)。
還有一種場景是受上下文影響過大,會參考上次的輸出,然后新實體的關聯、上下游也和上次調用的實體關聯、上下游一樣(糊弄我是吧??)
MCP 是標準化 LLM 上下文交互的開放協議,包含主機、客戶端、服務器及數據源組件,支持連接本地/遠程服務。用戶需配置支持 MCP 的客戶端(如Cherry Studio)和 LLM API(如阿里云百煉),并可擴展官方/自定義 MCP 服務器。阿里云可觀測2.0通過 UModel 統一多模態數據交互,解決系統復雜性帶來的觀測難題,實現從被動監控到主動預測的升級。
MCP 作為人、LLM、業務場景融合的媒介和工具,是新一代交互工具的萌芽,但仍然存在很多設計場景上的注意點。
如果判斷下來都是“是”,則非常適合 MCP 場景。
一些不適合的場景,通過某種轉化,可以變成適合的場景。比如股票交易系統不提供交易接口,只提供股票代碼查詢的能力,規避安全性問題。提供股票查詢后,規避返回股票信息具體細節,而引導模型輸出報告,模型會輸出對這支股票的看多看空思路和依據,提升寬容性。
同時也可以發現,MCP 天生適合理解業務短平快的需求場景,如果想解決一個非常復雜的任務,MCP 接口可能還不夠,需要 A2A + 更高級的協作、超長上下文的理解。
1.bing 搜索、Github搜索、網盤搜索等各類搜索引擎 MCP
理由:獨立、簡潔(返回 Top5 相關)、寬容(一定程度上)、魯棒、安全。
2.高德地圖 MCP 生成旅游路線
理由:獨立、寬容(每次不同甚至有新鮮感)、魯棒(有高德地圖穩定的系統為支持)、安全。
3.Web 瀏覽器自動化,相關爬取、統計、分析
理由:獨立、簡潔(輸出約束一下)、寬容、魯棒。
4.FileSystem
理由:獨立、簡潔、寬容(理由是 linux 命令行 llm 非常懂,不太可能寫錯)、安全(不提供 rm 能力)
5.Redis
理由:獨立、簡潔、寬容(非嚴肅 Redis 數據庫)
MCP 適用于短平快的獨立接口能力,對于復雜需求,更適合 A2A 或更強大的模式。更多結合AI的能力,不僅僅有 MCP,可觀測2.0 + AI,還有更多可能。
文章轉載自: MCP for 可觀測2.0,6個讓MCP開發更高效的小妙招