news 2026/2/24 20:33:29

FastMCP高级特性之Sampling(待重新排版)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
FastMCP高级特性之Sampling(待重新排版)

在 LLM(大语言模型) 的语境中,Sampling(采样) 指的是模型从预测的候选词概率分布中,选择下一个词来生成文本的过程。
简单来说,大语言模型生成文本时,不会直接 “确定” 下一个词,而是先计算出当前语境下所有可能出现的词的概率值,再通过特定的采样策略,从这个概率分布里挑选一个词,逐步拼接成完整的文本。

一、给MCP服务绑定LLM

importasyncioimportosfromopenaiimportOpenAIfromfastmcpimportFastMCPfromfastmcp.experimental.sampling.handlers.openaiimportOpenAISamplingHandler# 1. 初始化 FastMCP 服务器,配置大模型处理器server=FastMCP(name="Server-Controlled LLM",# 配置 OpenAI 大模型处理器(支持官方 API 或兼容 API)sampling_handler=OpenAISamplingHandler(default_model="gpt-4o-mini",# 默认使用的大模型client=OpenAI(api_key=os.getenv("OPENAI_API_KEY"),# 大模型 API 密钥base_url=os.getenv("OPENAI_BASE_URL"),# 可选:自定义 API 地址(如代理、私有部署)),),# 触发策略:always(强制用服务端大模型)/ fallback(客户端不支持时兜底)sampling_handler_behavior="always",)

二、通过 ctx.sample() 与大模型问答

方法一

*ctx.sample# async method请求大语言模型生成文本,并自动运行直至完成。

场景 1:简单文本生成(基础提问)

@server.toolasyncdefgenerate_summary(content:str,ctx:Context)->str:"""向大模型请求生成文本摘要"""# 构造提问提示prompt=f"请简洁总结以下内容:\n\n{content}"# 调用大模型response=awaitctx.sample(messages=prompt,# 简单字符串提问temperature=0.3,# 低随机性,保证摘要稳定max_tokens=300,# 限制摘要长度)# 返回大模型生成的结果(response.text 为文本内容)returnresponse.text

场景 2:带系统提示的专业问答(定义大模型角色)

@server.toolasyncdefgenerate_python_code(concept:str,ctx:Context)->str:"""让大模型生成 Python 代码示例(指定角色为专家)"""response=awaitctx.sample(messages=f"写一个简单的 Python 代码示例,演示:{concept}",system_prompt="你是资深 Python 工程师,只提供可运行的简洁代码,不附加解释",# 系统提示定义角色temperature=0.7,# 适度随机性,允许代码变体max_tokens=500,model_preferences="gpt-4",# 本次请求优先使用 gpt-4(覆盖默认的 gpt-4o-mini))# 格式化代码输出returnf"```python\n{response.text}\n```"

场景 3:多轮对话(结构化消息)
通过 SamplingMessage 构造多轮对话上下文,支持角色区分(user/assistant):

fromfastmcp.client.samplingimportSamplingMessage@server.toolasyncdefmulti_turn_analysis(user_query:str,context_data:str,ctx:Context)->str:"""多轮对话式分析(带历史上下文)"""# 构造多轮消息(角色+内容)messages=[SamplingMessage(role="user",content=f"我的数据:{context_data}"),# 第一轮:用户提供数据SamplingMessage(role="assistant",content="已收到数据,你想分析什么?"),# 第二轮:助手回应SamplingMessage(role="user",content=user_query)# 第三轮:用户具体提问]response=awaitctx.sample(messages=messages,# 传入结构化消息列表system_prompt="你是数据分析师,基于对话上下文提供详细分析",temperature=0.2,# 低随机性,保证分析严谨)returnresponse.text

场景 4:情感分析(简单分类任务)

@server.toolasyncdefanalyze_sentiment(text:str,ctx:Context)->dict:"""让大模型分析文本情感(正面/负面/中性)"""prompt=f""" 分析以下文本的情感,仅输出一个词:positive(正面)、negative(负面)或 neutral(中性)。 文本:{text}"""response=awaitctx.sample(prompt,temperature=0.0)# 0 随机性,保证分类一致sentiment=response.text.strip().lower()# 标准化结果if"positive"insentiment:result="positive"elif"negative"insentiment:result="negative"else:result="neutral"return{"text":text,"sentiment":result}

方法二

ctx.sample_step()

三、结构化输出

当你需要经过验证的、有类型的数据而非自由格式的文本时,请使用 result_type 参数。FastMCP 确保大语言模型返回与你的类型相匹配的数据,并自动处理验证和重试操作。result_type 参数可接受 Pydantic 模型、数据类以及基本类型,如 int、list [str] 或 dict [str, int]。

frompydanticimportBaseModelfromfastmcpimportFastMCP,Context mcp=FastMCP()classSentimentResult(BaseModel):sentiment:strconfidence:floatreasoning:str@mcp.toolasyncdefanalyze_sentiment(text:str,ctx:Context)->SentimentResult:"""Analyze text sentiment with structured output."""result=awaitctx.sample(messages=f"Analyze the sentiment of:{text}",result_type=SentimentResult,)returnresult.result# A validated SentimentResult object

当你调用这个工具时,大语言模型(LLM)会返回一个结构化响应,FastMCP 会根据你的 Pydantic 模型对该响应进行验证。你可以通过result.result访问经过验证的对象,而result.text则包含 JSON 格式的表示。

当你传入result_type时,sample ()会自动创建一个 final_response 工具,大语言模型会调用该工具来提供其响应。如果验证失败,错误会被发送回大语言模型以进行重试。这种自动处理仅适用于sample ()—— 对于sample_step (),你必须自行管理结构化输出。

四、使用工具进行采样

借助工具进行采样能够实现智能体工作流,让大语言模型(LLM)在做出回应前可以调用函数来收集信息。这一功能实现了 SEP-1577,允许大语言模型自主编排多步骤操作。

将 Python 函数传递给 tools 参数,FastMCP 会自动处理执行循环 —— 调用工具、将结果返回给大语言模型,并持续这一过程,直到大语言模型给出最终回应。

4.1 定义工具

使用类型提示和文档字符串定义常规的 Python 函数。FastMCP 会提取函数的名称、文档字符串和参数类型,以创建大语言模型能够理解的工具模式。

fromfastmcpimportFastMCP,Contextdefsearch(query:str)->str:"""Search the web for information."""returnf"Results for:{query}"defget_time()->str:"""Get the current time."""fromdatetimeimportdatetimereturndatetime.now().strftime("%H:%M:%S")mcp=FastMCP()@mcp.toolasyncdefresearch(question:str,ctx:Context)->str:"""Answer questions using available tools."""result=awaitctx.sample(messages=question,tools=[search,get_time],)returnresult.textor""

大语言模型(LLM)会查看每个函数的签名和文档字符串,并利用这些信息来决定何时以及如何调用它们。工具错误会被捕获并反馈给大语言模型,使其能够平稳地恢复。一个内部安全限制可防止无限循环。

4.2 工具错误处理

默认情况下,当采样工具抛出异常时,错误消息(包括详细信息)会发送回大语言模型,以便其尝试恢复。为防止敏感信息泄露给大语言模型,请使用 mask_error_details 参数:

result=awaitctx.sample(messages=question,tools=[search],mask_error_details=True,# Generic error messages only)

当 mask_error_details=True 时,工具错误会变成诸如 “执行工具‘search’时出错” 之类的通用消息,而不会暴露堆栈跟踪或内部细节。

若要不管是否启用屏蔽,都特意向 LLM 提供特定的错误消息,请抛出 ToolError:

fromfastmcp.exceptionsimportToolErrordefsearch(query:str)->str:"""Search for information."""ifnotquery.strip():raiseToolError("Search query cannot be empty")returnf"Results for:{query}"

工具错误消息总会传递给大语言模型(LLM),使其成为你希望大语言模型看到并处理错误的应急出口。

对于自定义名称或描述,请使用 SamplingTool.from_function ():

fromfastmcp.server.samplingimportSamplingTool tool=SamplingTool.from_function(my_func,name="custom_name",description="Custom description")result=awaitctx.sample(messages="...",tools=[tool])

4.3 组合结构化输出

将工具与结果类型相结合,用于生成能返回经过验证的结构化数据的智能代理工作流。大语言模型(LLM)会使用你的工具来收集信息,然后返回与你的类型相匹配的响应。

result=awaitctx.sample(messages="Research Python async patterns",tools=[search,fetch_url],result_type=ResearchResult,)

五、循环控制

虽然 sample () 会自动处理工具执行循环,但在某些场景下,需要对每个步骤进行精细控制。sample_step () 方法会进行一次 LLM 调用,并返回一个包含响应和更新后历史记录的 SampleStep。

与 sample () 不同,sample_step () 是无状态的 —— 它不会记住之前的调用。你需要通过每次传递完整的消息历史来控制对话。

返回的 step.history 包含截至当前响应的所有消息,便于继续循环。

在以下情况时使用 sample_step ():

  • 在工具调用执行前对其进行检查
  • 实现自定义终止条件
  • 在步骤之间添加日志记录、指标监控或检查点设置
  • 利用特定领域逻辑构建自定义智能体循环

5.1 使用 sample_step ()

默认情况下,sample_step () 会执行所有工具调用,并将结果包含在历史记录中。在循环中调用它,每次传递更新后的历史记录,直到满足停止条件。

frommcp.typesimportSamplingMessage@mcp.toolasyncdefcontrolled_agent(question:str,ctx:Context)->str:"""Agent with manual loop control."""messages:list[str|SamplingMessage]=[question]# strings auto-convertwhileTrue:step=awaitctx.sample_step(messages=messages,tools=[search,get_time],)ifstep.is_tool_use:# Tools already executed (execute_tools=True by default)# Log what was called before continuingforcallinstep.tool_calls:print(f"Called tool:{call.name}")ifnotstep.is_tool_use:returnstep.textor""# Continue with updated historymessages=step.history

5.2 SampleStep属性

每个 SampleStep 都会提供有关大语言模型(LLM)返回内容的信息:

  • step.is_tool_use— 如果大语言模型请求调用工具,则为 True
  • step.tool_calls— 请求的工具调用列表(如有)
  • step.text— 文本内容(如有)
  • step.history— 到目前为止交换的所有消息
  • step.history的内容取决于 execute_tools:
  • execute_tools=True(默认值):包含工具结果,为下一次迭代做好准备
  • execute_tools=False:包含助手的工具请求,但需要您自行添加结果

5.3 手动执行工具

将 execute_tools 设置为 False,以便自行处理工具执行。禁用该功能时,step.history 会包含用户消息以及带有工具调用的助手回复,但不包含工具结果。您需要执行这些工具,并将结果作为用户消息追加进去。

frommcp.typesimportSamplingMessage,ToolResultContent,TextContentfromfastmcpimportFastMCP,Context mcp=FastMCP()@mcp.toolasyncdefresearch(question:str,ctx:Context)->str:"""Research with manual tool handling."""defsearch(query:str)->str:returnf"Results for:{query}"defget_time()->str:return"12:00 PM"# Map tool names to functionstools={"search":search,"get_time":get_time}messages:list[SamplingMessage]=[question]# strings are converted automaticallywhileTrue:step=awaitctx.sample_step(messages=messages,tools=list(tools.values()),execute_tools=False,)ifnotstep.is_tool_use:returnstep.textor""# Execute tools and collect resultstool_results=[]forcallinstep.tool_calls:fn=tools[call.name]result=fn(**call.input)tool_results.append(ToolResultContent(type="tool_result",toolUseId=call.id,content=[TextContent(type="text",text=result)],))messages=list(step.history)messages.append(SamplingMessage(role="user",content=tool_results))

错误处理
要报告错误,请将 isError 设置为 True。大语言模型(LLM)会看到该错误,并能决定如何继续处理:

tool_result=ToolResultContent(type="tool_result",toolUseId=call.id,content=[TextContent(type="text",text="Permission denied")],isError=True,)

六、备用处理

MCP 默认优先调用客户端已配置的大模型,服务端无需额外配置大模型信息,直接通过 ctx.sample() 触发即可。

客户端对采样的支持是可选的 —— 有些客户端可能不会实现这一功能。为确保你的工具无论客户端具备何种能力都能正常运行,请配置一个直接向大语言模型(LLM)提供商发送请求的采样处理器(sampling_handler)。

FastMCP 为 OpenAI 和 Anthropic 的应用程序接口(API)提供了内置处理器。这些处理器支持完整的采样应用程序接口,包括工具相关功能,能自动将你的 Python 函数转换为各个提供商所需的格式。

使用 pip install fastmcp [openai] 或 pip install fastmcp [anthropic] 安装处理器。

fromfastmcpimportFastMCPfromfastmcp.client.sampling.handlers.openaiimportOpenAISamplingHandler server=FastMCP(name="My Server",sampling_handler=OpenAISamplingHandler(default_model="gpt-4o-mini"),sampling_handler_behavior="fallback",)

或者

fromfastmcpimportFastMCPfromfastmcp.client.sampling.handlers.anthropicimportAnthropicSamplingHandler server=FastMCP(name="My Server",sampling_handler=AnthropicSamplingHandler(default_model="claude-sonnet-4-5"),sampling_handler_behavior="fallback",)

6.1 行为模式

sampling_handler_behavior参数控制handler的使用时机:

  • “fallback”(默认值):仅当客户端不支持采样时使用处理器。这使得有能力的客户端可以使用自己的大语言模型(LLM),同时确保你的工具在缺乏采样支持的客户端上仍然能正常工作。
  • “always”:始终使用handler,完全绕过客户端。当你需要确保对处理请求的大语言模型(LLM)拥有控制权时使用此选项,例如出于成本控制、合规要求,或者当特定的模型特性至关重要时。

使用工具进行采样要求客户端声明具备sampling.tools能力。FastMCP 客户端会自动进行声明。对于不支持工具启用采样的外部客户端,请将 fallback 处理器配置为 sampling_handler_behavior=“always”。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/2/24 12:40:38

redis 发布订阅功能

redis发布订阅是一种消息通知模式,发布者发送消息,订阅者接收消息。角色说明发布者 (Publisher)向频道发送消息的客户端订阅者 (Subscriber)订阅频道接收消息的客户端频道 (Channel)消息传递的管道/主题基本命令1. 订阅频道#订阅一个或多个频道 SUBSCRIB…

作者头像 李华
网站建设 2026/2/21 19:30:27

【保姆级教程】10分钟轻松搭建属于自己的AI助手

想拥有专属AI助手,无需复杂编码,无需漫长等待!借助扣子平台的可视化能力,搭配数眼智能搜索与网页阅读接口,全程免费!10分钟就能快速搭建完成,轻松实现精准信息检索与网页内容解析。本文为你带来…

作者头像 李华
网站建设 2026/2/21 7:45:16

3D模型生成终极指南:腾讯Hunyuan3D-2mini轻量化技术深度解析

还在为复杂的3D建模软件发愁吗?专业建模师需要花费数小时完成的工作,现在普通人只需输入文字描述,30秒内就能获得完整的3D模型。腾讯最新开源的Hunyuan3D-2mini模型,以仅0.6B的参数规模,实现了前所未有的"轻量高速…

作者头像 李华
网站建设 2026/2/21 20:59:56

Kubernetes Dashboard可视化监控:从架构原理到生产实践

在Kubernetes集群运维中,命令行工具虽然功能强大但学习曲线陡峭,而Dashboard作为官方提供的Web管理界面,通过直观的可视化方式降低了操作门槛。本文将深入解析Dashboard的部署架构、安全认证机制和实际应用场景,帮助您构建可靠的可…

作者头像 李华
网站建设 2026/2/24 2:43:16

基于DWS MCP Server搭建数据分析Agent

本文分享自华为云社区《基于DWS MCP Server搭建数据分析Agent》 1. 前言 MCP(Model Context Protocol)是由Anthropic于2024年11月提出的开放协议标准,旨在解决大型语言模型与外部系统(如数据库、API)交互的碎片化问题。…

作者头像 李华