本地Agent实现最佳组合=LangGraph+MCP+Ollama

简介

本文提供一个简短教程,展示如何使用 LangGraphMCP(模型上下文协议) 和 Ollama 创建多代理聊天机器人,构建适用于商业或个人使用的强大智能代理聊天机器人。

不久前,我制作了一段关于模型上下文协议(MCP)的视频。一些开发者将其比喻为“为AI打造的Zapier”,认为它仅为API使用增加了额外步骤。

“在MCP出现之前,开发者需要编写代码并通过API将AI工具连接到外部系统,这意味着每个集成都需要提前编码。” —— John Rush

尽管MCP于2024年11月发布,但近期突然流行,引发了关于其“繁荣期”持续时间的讨论。LangChain 在 X 平台上发起投票,结果显示:

•40.8% 认为 MCP 是未来标准;•25.8% 认为 MCP 只是昙花一现;•33.4% 选择观望。

MCP 虽新,但已支持 GitHub、Slack 和 PostgreSQL 等服务。作为开放标准,它可与任何大语言模型(LLM,如 Claude、OpenAI、Gemini 等)配合使用,令人惊讶。

接下来,我将通过实时聊天机器人演示展示其效果。

演示

我将向聊天机器人提出两个问题:

1.“你能写一份关于最新大语言模型的报告吗?”
您也可自由提问。

观察聊天机器人输出,代理通过 create_chatbot 函数使用结构化流程处理输入。该函数整合系统指令、用户消息和工具执行,形成流畅交互,并根据查询选择工具。

对于第一个问题,聊天机器人调用 Google 搜索工具获取最新信息并生成报告。对于第二个问题,“编写一个使用 Seaborn 创建带回归线的散点图的 Python 脚本”,聊天机器人处理请求并路由到适当工具(如 python_repl 或 data_visualization),具体取决于查询结构。async_tool_executor 动态处理工具调用,确保同步和异步功能(如生成代码或可视化)正确执行。

StateGraph 管理对话状态,确保后续问题响应准确且具上下文相关性。get_tools 函数确保仅使用可用工具,维护系统稳定性。main 函数确保顺畅运行,实时处理用户输入、调用工具并处理输出。

通过本文,您将了解 MCP 与函数调用(Function Call)的区别、何时使用两者,以及如何使用 LangGraph、MCP 和开源工具创建强大的智能代理聊天机器人。

开始之前!🦸🏻‍♀️

如果您喜欢此主题并想支持我:

•为文章鼓掌50次,助力我前行!👏•在 Medium 上关注我并订阅,免费获取最新文章🫶•订阅我的 YouTube 频道,加入大家庭!

MCP 与函数调用的区别

函数调用中,AI 像遵循严格脚本的工人,仅能调用预定义工具,逐一执行,限制于已获取工具。而在 MCP 中,AI 像拥有工具箱的代理,可探索新工具、组合使用,处理更多任务,拥有更大自主性。

函数调用与模型提示紧密耦合,开发者需管理调用顺序,控制性强但灵活性有限。MCP 通过开放协议实现松耦合,灵活可扩展,但需精心设计以管理复杂性和确保安全性。下一节将探讨如何使用 MCP 构建代理并应对其灵活性挑战。

何时使用函数调用和 MCP

选择函数调用或 MCP 取决于用例:

函数调用:适用于明确定义的简单动作或单步查询,需高度结构化输出。适合可预测任务和轻量集成,MCP 的额外开销可能过重。若需结构化、狭窄任务和简单应用集成,选择函数调用。•MCP:适用于需灵活性、多功能工具或跨交互演变上下文的场景。适合复杂、多步骤工作流程,或 AI 需维护长期上下文并与多种系统交互(如跨内部系统的通用助手,调用多数据源)。

两者不互斥,可互补。例如,函数调用可在 MCP 客户端内处理模型结构化输出。概念上,函数调用将自然语言转化为可控的函数执行,而 MCP 为 AI 提供更广接口以探索和操作环境。

开始编码

让我们逐步探索如何创建 MCP 应用程序。首先安装支持模型的库:

pip install -r requirements.txt

接下来导入相关库,其重要性将在后续显现:

langchain_mcp_adapters:将 MCP 工具转为 LangChain 工具,供 LangGraph 代理使用,提供客户端实现,连接多个 MCP 服务器加载工具。•MCP:开放协议,标准化应用程序为大语言模型提供上下文。•googlesearch-python:便于 Google 搜索的包。

代码文件概览

agent.py

我设计了 create_agent 函数作为异步过程构建 AI 代理,接受可选参数 docs_info 提供聊天机器人数据。MultiServerMCPClient 集成到异步上下文管理器,确保与 MCP 服务器(http://localhost:8000/sse)通过服务器发送事件(SSE)无缝通信,超时30秒。

调用 client.get_tools() 获取 MCP 工具,启用高级功能。使用 MessagesState 构建 StateGraph 管理对话状态,通过 create_chatbot(docs_info) 创建聊天机器人节点,处理和交互文档。

from langchain_core.messages importAIMessage,ToolMessage,HumanMessagefrom langgraph.graph importStateGraph, START,END,MessagesStatefrom nodes import create_chatbotimport asyncioimport osimport dotenvfrom langchain_mcp_adapters.client importMultiServerMCPClient
async def create_agent(docs_info=None):    async withMultiServerMCPClient({"server":{"url":"http://localhost:8000/sse","transport":"sse","timeout":30}})as client:        tools = client.get_tools()        graph_builder =StateGraph(MessagesState)        chatbot_node = create_chatbot(docs_info)        graph_builder.add_node("chatbot", chatbot_node)

async_tool_executor 动态处理工具调用,输入为包含对话消息列表的 state。提取最后消息(messages[-1])检查工具调用,从 tool_calls 或 additional_kwargs 获取。若无工具调用,返回未更改消息。

为处理工具调用,复制消息到 new_messages,遍历每个工具调用,提取 tool_nametool_args 和 tool_id,支持字典和对象格式。匹配 tool_name 查找工具;若未找到,生成错误消息列出有效工具。

若工具存在,使用 asyncio.iscoroutinefunction() 判断是否异步函数——若异步,执行 await tool.coroutine(**tool_args);否则,调用 tool.func(**tool_args) 或 tool(**tool_args)。通过捕获异常处理错误,附加详细错误消息到 new_messages

async def async_tool_executor(state):    messages = state["messages"]    last_message = messages[-1]    tool_calls =Noneif hasattr(last_message,"tool_calls"):        tool_calls = last_message.tool_callselif hasattr(last_message,"additional_kwargs")and"tool_calls"in last_message.additional_kwargs:        tool_calls = last_message.additional_kwargs["tool_calls"]
ifnot tool_calls:return{"messages": messages}
    new_messages = messages.copy()for tool_call in tool_calls:if isinstance(tool_call, dict):            tool_name = tool_call.get("name")            tool_args = tool_call.get("args",{})            tool_id = tool_call.get("id","tool-call-id")else:            tool_name = tool_call.name            tool_args = tool_call.args if hasattr(tool_call,"args")else{}            tool_id = getattr(tool_call,"id","tool-call-id")
print(f"执行工具:{tool_name}")print(f"工具参数:{tool_args}")
        tool =next((t for t in tools if t.name == tool_name),None)ifnot tool:            tool_error = f"错误:{tool_name} 不是有效工具,请尝试以下工具之一:{[t.name for t in tools]}。"            new_messages.append(AIMessage(content=tool_error))else:try:if asyncio.iscoroutinefunction(tool.coroutine):                    result = await tool.coroutine(**tool_args)else:                    result = tool.func(**tool_args)if hasattr(tool,'func')else tool(**tool_args)
print(f"工具结果:{result}")                new_messages.append(ToolMessage(                    content=str(result),                    tool_call_id=tool_id,                    name=tool_name))exceptExceptionas e:                error_msg = f"错误:{str(e)}\n 请修复您的错误。"print(f"工具错误:{error_msg}")                new_messages.append(AIMessage(content=error_msg))
return{"messages": new_messages}

通过集成异步工具执行节点和路由函数,设计了结构化对话流程。添加 async_tool_executor 作为“tools”节点,动态处理工具调用。创建路由函数,根据最后消息决定下一步:若 AI 消息含工具调用,路由到“tools”;否则,结束对话。

为图添加边:从“chatbot”开始,条件路由到“tools”或“end”,并将“tools”循环回“chatbot”,支持多次工具交互。​​​​​​​

graph_builder.add_node("tools", async_tool_executor)
def router(state):    messages = state["messages"]    last_message = messages[-1]
    has_tool_calls =Falseif isinstance(last_message,AIMessage):if hasattr(last_message,"tool_calls")and last_message.tool_calls:            has_tool_calls =Trueelif hasattr(last_message,"additional_kwargs")and last_message.additional_kwargs.get("tool_calls"):            has_tool_calls =True
return"tools"if has_tool_calls else"end"
graph_builder.add_edge(START,"chatbot")graph_builder.add_conditional_edges("chatbot",    router,{"tools":"tools","end":END})graph_builder.add_edge("tools","chatbot")graph = graph_builder.compile()return graph, client
nodes.py

get_system_prompt 函数动态生成 AI 助手系统提示,确保明确指导和上下文感知。使用 datetime.now().strftime("%Y-%m-%d") 格式化当前日期嵌入提示,提供实时参考。

定义助手角色和能力,列出三个工具:generate_image(DALL-E 生成图像)、data_visualization(matplotlib 生成图表)、python_repl(Python 执行环境)。​​​​​​​

from server import get_toolsfrom langgraph.graph importMessagesStatefrom langchain_openai importChatOpenAIfrom langchain_ollama importChatOllamafrom langchain_core.prompts importChatPromptTemplate,SystemMessagePromptTemplate,HumanMessagePromptTemplatefrom datetime import datetimeimport os
def get_system_prompt(docs_info=None):    system_prompt = f"""今天是{datetime.now().strftime("%Y-%m-%d")}你是一个有用的 AI 助手,可使用以下工具:- generate_image:根据提示使用 DALL-E 生成图像- data_visualization:使用Python和 matplotlib 创建图表- python_repl:执行Python代码
调用图像生成或数据可视化工具时,仅回答生成事实,不返回 base64 代码或 URL。一旦通过工具生成图像,在一个回答中不再重复调用。"""if docs_info:        docs_context ="\n\n你可以访问以下文档:\n"for doc in docs_info:            docs_context += f"- {doc['name']}:{doc['type']}\n"        system_prompt += docs_context
    system_prompt +="\n你应始终使用与用户提问相同的语言回答。"return system_prompt

create_chatbot 函数处理用户输入并生成 AI 响应,使用 ChatPromptTemplate 结合系统指令(来自 get_system_prompt)和用户消息。通过管道(|)将提示传递到 LLM,创建无缝处理链。

函数将字符串转为 HumanMessage 对象,确保消息格式一致。聊天机器人调用 LLM 处理用户消息并附加响应,维护结构化对话历史。助手遵循规则,适应查询,保持工具无关性,提供灵活响应,确保互动动态体验。🚀​​​​​​​

def create_chatbot(docs_info=None):    prompt =ChatPromptTemplate.from_messages([SystemMessagePromptTemplate.from_template(get_system_prompt(docs_info)),HumanMessagePromptTemplate.from_template("{input}")])
    chain = prompt | llm
def chatbot(state:MessagesState):if isinstance(state["messages"], str):from langchain_core.messages importHumanMessage            messages =[HumanMessage(content=state["messages"])]else:            messages = state["messages"]
        response = chain.invoke(messages)return{"messages": messages +[response]}
return chatbot
server.py

开发了一套工具,用于生成图像、可视化数据和执行 Python 代码。generate_image 工具使用 DALL-E 根据提示生成图像,验证提示有效后,异步调用 OpenAI API,成功返回图像 URL,失败返回错误消息。

data_visualization 工具使用 matplotlib 执行 Python 代码创建图表,保存为 base64 编码的 PNG 图像。python_repl 工具在 REPL 环境运行 Python 代码,提供动态执行。工具均设计为处理错误并返回有意义响应。​​​​​​​

from mcp.server.fastmcp importFastMCPfrom langchain_experimental.utilities importPythonREPLimport ioimport base64import matplotlib.pyplot as pltfrom openai importOpenAIfrom pydantic importBaseModel,Fieldimport osfrom dotenv import load_dotenvimport asynciofrom googlesearch import search
@mcp.tool()async def generate_image(prompt: str)-> str:"""根据给定的提示使用 DALL-E 生成图像。"""ifnot isinstance(prompt, str)ornot prompt.strip():raiseValueError("无效提示")
try:        loop = asyncio.get_event_loop()        response = await loop.run_in_executor(None,lambda: client.images.generate(                model="dall-e-3",                prompt=prompt,                size="1024x1024",                quality="standard",                n=1))return f"成功生成 {prompt} 的图像!URL:{response.data[0].url}"exceptExceptionas e:return f"生成图像错误:{str(e)}"
repl =PythonREPL()
@mcp.tool()def data_visualization(code: str):"""执行 Python 代码,使用 matplotlib 进行可视化。"""try:        repl.run(code)        buf = io.BytesIO()        plt.savefig(buf, format='png')        buf.seek(0)        img_str = base64.b64encode(buf.getvalue()).decode()return f"data:image/png;base64,{img_str}"exceptExceptionas e:return f"创建图表错误:{str(e)}"
@mcp.tool()def python_repl(code: str):"""执行 Python 代码。"""return repl.run(code)

get_tools 函数返回可用工具列表,确保仅包含功能性工具,包括 generate_imagepython_repl 和 data_visualization。若提供 retriever_tool,则加入列表。脚本通过 mcp.run(transport="sse") 运行 MCP 服务器,确保工具可用。​​​​​​​

def get_tools(retriever_tool=None):    base_tools =[generate_image, python_repl, data_visualization]if retriever_tool:        base_tools.append(retriever_tool)return base_tools
if __name__ =="__main__":    mcp.run(transport="sse")
main.py

main 函数运行异步代理,动态处理用户输入和工具交互。通过 await create_agent() 创建代理和客户端,通过命令行获取用户输入,构造 HumanMessage

通过 agent.ainvoke() 异步调用代理处理请求,打印用户输入或工具结果(若为图像生成,提取 URL)。捕获异常并打印。客户端保持活跃,脚本通过 asyncio.run(main()) 异步执行。​​​​​​​

import streamlit as stimport asynciofrom agent import create_agentfrom langchain_core.messages importHumanMessage
async def main():    agent, client = await create_agent()    user_input = input("您想问什么? ")    initial_message =HumanMessage(content=user_input)
try:print("正在处理您的请求...")        result = await agent.ainvoke({"messages":[initial_message]})for message in result["messages"]:if hasattr(message,"type")and message.type =="human":print(f"用户:{message.content}")elif hasattr(message,"type")and message.type =="tool":print(f"工具结果:{message.content}")if"image"in message.content.lower()and"url"in message.content.lower():print("图像生成成功!")else:print(f"AI:{message.content}")exceptExceptionas e:print(f"错误:{str(e)}")
if __name__ =="__main__":    asyncio.run(main())

结论

MCP 不仅是工具调用协议的升级,而是范式变革。它提供通用开放标准,使 AI 系统以标准化方式连接数据源、工具和服务,减少单独连接器需求,简化集成。

非智能服务可通过 MCP 暴露功能为“工具”,供大语言模型调用,无需大幅修改现有系统即可交互和执行任务。

学习是持续的过程,充满挑战。天道酬勤,愈努力愈优秀。

 

 如何系统的去学习大模型LLM ?

大模型时代,火爆出圈的LLM大模型让程序员们开始重新评估自己的本领。 “AI会取代那些行业?”“谁的饭碗又将不保了?”等问题热议不断。

事实上,抢你饭碗的不是AI,而是会利用AI的人。

科大讯飞、阿里、华为等巨头公司发布AI产品后,很多中小企业也陆续进场!超高年薪,挖掘AI大模型人才! 如今大厂老板们,也更倾向于会AI的人,普通程序员,还有应对的机会吗?

与其焦虑……

不如成为「掌握AI工具的技术人」,毕竟AI时代,谁先尝试,谁就能占得先机!

但是LLM相关的内容很多,现在网上的老课程老教材关于LLM又太少。所以现在小白入门就只能靠自学,学习成本和门槛很高。

基于此,我用做产品的心态来打磨这份大模型教程,深挖痛点并持续修改了近70次后,终于把整个AI大模型的学习门槛,降到了最低!

在这个版本当中:

第一您不需要具备任何算法和数学的基础
第二不要求准备高配置的电脑
第三不必懂Python等任何编程语言

您只需要听我讲,跟着我做即可,为了让学习的道路变得更简单,这份大模型教程已经给大家整理并打包,现在将这份 LLM大模型资料 分享出来:包括LLM大模型书籍、640套大模型行业报告、LLM大模型学习视频、LLM大模型学习路线、开源大模型学习教程等, 😝有需要的小伙伴,可以 扫描下方二维码领取🆓↓↓↓

一、LLM大模型经典书籍

AI大模型已经成为了当今科技领域的一大热点,那以下这些大模型书籍就是非常不错的学习资源。

在这里插入图片描述

二、640套LLM大模型报告合集

这套包含640份报告的合集,涵盖了大模型的理论研究、技术实现、行业应用等多个方面。无论您是科研人员、工程师,还是对AI大模型感兴趣的爱好者,这套报告合集都将为您提供宝贵的信息和启示。(几乎涵盖所有行业)
在这里插入图片描述

三、LLM大模型系列视频教程

在这里插入图片描述

四、LLM大模型开源教程(LLaLA/Meta/chatglm/chatgpt)

在这里插入图片描述

五、AI产品经理大模型教程

在这里插入图片描述

LLM大模型学习路线 

阶段1:AI大模型时代的基础理解

  • 目标:了解AI大模型的基本概念、发展历程和核心原理。

  • 内容

    • L1.1 人工智能简述与大模型起源
    • L1.2 大模型与通用人工智能
    • L1.3 GPT模型的发展历程
    • L1.4 模型工程
    • L1.4.1 知识大模型
    • L1.4.2 生产大模型
    • L1.4.3 模型工程方法论
    • L1.4.4 模型工程实践
    • L1.5 GPT应用案例

阶段2:AI大模型API应用开发工程

  • 目标:掌握AI大模型API的使用和开发,以及相关的编程技能。

  • 内容

    • L2.1 API接口
    • L2.1.1 OpenAI API接口
    • L2.1.2 Python接口接入
    • L2.1.3 BOT工具类框架
    • L2.1.4 代码示例
    • L2.2 Prompt框架
    • L2.3 流水线工程
    • L2.4 总结与展望

阶段3:AI大模型应用架构实践

  • 目标:深入理解AI大模型的应用架构,并能够进行私有化部署。

  • 内容

    • L3.1 Agent模型框架
    • L3.2 MetaGPT
    • L3.3 ChatGLM
    • L3.4 LLAMA
    • L3.5 其他大模型介绍

阶段4:AI大模型私有化部署

  • 目标:掌握多种AI大模型的私有化部署,包括多模态和特定领域模型。

  • 内容

    • L4.1 模型私有化部署概述
    • L4.2 模型私有化部署的关键技术
    • L4.3 模型私有化部署的实施步骤
    • L4.4 模型私有化部署的应用场景

这份 LLM大模型资料 包括LLM大模型书籍、640套大模型行业报告、LLM大模型学习视频、LLM大模型学习路线、开源大模型学习教程等, 😝有需要的小伙伴,可以 扫描下方二维码领取🆓↓↓↓

<think>好的,用户想了解Dify和MCP实现原理、开发文档以及框架集成。首先,我需要先回顾一下之前提供的引用内容。根据引用[1]和[2],MCP是Anthropic提出的协议层创新,主要解决智能体调用外部工具的标准化问题。而Dify则被描述为一个一站式平台,帮助开发者快速创建和运营AI应用。用户的问题集中在它们的实现方式上,需要详细解释原理和相关文档。 首先,我需要明确Dify和MCP各自的定位。MCP是协议,属于底层标准,可能涉及API规范、通信协议等。Dify作为应用平台,可能构建在类似MCP的协议之上,或者使用其他框架如LangChain。但根据引用[2],MCP和Dify属于不同层面,MCP在协议层,Dify在应用层,所以它们的实现方式会有很大不同。 接下来,关于Dify的实现原理。作为一站式平台,Dify可能提供用户界面、工作流引擎、模型集成、数据处理等功能。需要查阅Dify的官方文档,确认其架构。可能涉及微服务架构,前后端分离,支持多种模型API的接入,比如OpenAI、Anthropic等。同时,Dify可能提供可视化编排工具,让用户通过拖拽方式构建AI应用,这需要前端框架如React或Vue,后端可能用Python/Django或Node.js。 然后是MCP实现原理。作为协议,MCP需要定义标准化的接口和通信格式,确保不同工具和智能体之间的互操作性。可能包括API网关、请求/响应格式、认证机制、错误处理等。实现上可能采用HTTP/REST或gRPC,使用JSON或Protocol Buffers进行数据序列化。开发文档可能包含协议规范、API参考、示例代码和集成指南。 关于框架集成,Dify可能需要集成各种AI模型和工具,比如LangChain,或者支持自定义插件的开发。MCP作为协议,可能需要开发者按照其规范开发适配器,以便现有的工具能够兼容MCP,方便智能体调用。 用户还提到开发文档,需要提供官方链接。Dify的文档可能在其官网,比如docs.dify.ai,而MCP作为Anthropic的项目,可能需要查看其官方资源,但目前信息有限,可能还在早期阶段。 需要注意的是,用户可能混淆了MCP和Dify的关系,因为它们属于不同层面,但引用[2]已经说明它们分别在不同层面推动AI应用。因此,在回答中需要明确区分,并解释各自的实现方式,避免混淆。 另外,用户可能对如何将MCP集成到自己的项目中感兴趣,所以需要说明MCP的集成步骤,比如遵循协议规范,开发适配器,处理请求响应等。而Dify的集成可能更偏向于使用其平台功能,通过API或SDK接入现有系统。 最后,确保回答结构清晰,分点说明Dify和MCP实现原理、开发文档和框架集成,引用提供的资料,并在末尾添加相关问题。</think>### Dify与MCP实现原理及集成解析 #### 一、Dify实现原理 1. **架构设计** Dify采用前后端分离的微服务架构,核心模块包括: - **工作流引擎**:通过可视化界面实现AI应用逻辑编排(如条件分支、API调用) - **模型抽象层**:支持多模型接口标准化接入,例如: ```python # 模型调用示例 def model_invoke(provider, model_name, inputs): if provider == "openai": return openai.ChatCompletion.create(model=model_name, messages=inputs) elif provider == "anthropic": return anthropic.Messages.create(model=model_name, messages=inputs) ``` - **数据管道**:内置ETL工具处理非结构化数据,支持$PDF$解析、$JSON$转换等操作[^2] 2. **核心功能实现** - **RAG增强**:通过向量数据库实现知识库检索增强 $$ \text{相似度计算}:\ \text{cosine}(q,d) = \frac{q \cdot d}{\|q\| \|d\|} $$ - **插件系统**:允许开发者通过SDK扩展自定义工具 ```python # 插件开发示例 @dify.plugin def weather_query(params): return requests.get(f"https://api.weather.com?city={params['city']}") ``` 官方文档:https://docs.dify.ai #### 二、MCP协议实现 1. **协议层设计** MCP定义了三层标准化规范: - **通信协议**:基于HTTP/2的二进制流传输 - **接口规范**:工具描述采用$JSON$ Schema格式 ```json { "tool_name": "calculator", "parameters": { "expression": {"type": "string", "format": "arithmetic"} } } ``` - **安全控制**:OAuth2.0认证流程,包含$access\_token$动态获取机制 2. **运行时实现** - **智能体调度**:通过$DAG$(有向无环图)管理工具调用顺序 $$ \text{执行流程图}:\ A \rightarrow B \rightarrow C \quad \text{当} \ f(A.output) > \theta $$ - **异常处理**:定义标准错误码体系(如`MCP-4001`表示参数格式错误) 协议文档:https://mcp-spec.ai (示例地址) #### 三、框架集成对比 | 集成方式 | Dify | MCP | |----------------|--------------------|----------------| | **接入形式** | Web控制台/API | 协议适配器 | | **代码改造** | 无需修改业务代码 | 需实现协议接口 | | **典型场景** | 快速构建对话机器人 | 跨平台工具调用 | #### 四、开发集成指引 1. **Dify集成步骤** ```mermaid graph TD A[注册Dify账号] --> B[创建应用] B --> C{选择模式} C -->|提示词工程| D[配置知识库] C -->|工作流模式| E[拖拽编排节点] ``` 2. **MCP集成示例** ```python # 工具服务端实现 from mcp_server import ToolServer class CalculatorTool(ToolServer): @endpoint("/calculate") def handle_request(self, params): try: result = eval(params["expression"]) return {"result": result} except: raise MCPError(code=1001, message="计算表达式错误") ``` ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值