当前位置: 首页 > news >正文

让AI再次伟大-MCP-Client开发指南

  • 👏作者简介:大家好,我是爱吃芝士的土豆倪,24届校招生Java选手,很高兴认识大家
  • 📕系列专栏:Spring原理、JUC原理、Kafka原理、分布式技术原理、数据库技术、JVM原理、AI应用
  • 🔥如果感觉博主的文章还不错的话,请👍三连支持👍一下博主哦
  • 🍂博主正在努力完成2025计划中:逆水行舟,不进则退
  • 📝联系方式:nhs19990716,加我进群,大家一起学习,一起进步,一起对抗互联网寒冬👀

文章目录

  • 简述
  • 环境准备
  • 创建client客户端
    • 初始化
    • 封装连接mcp-server函数
    • 处理用户查询的核心函数
      • 调用deepseek返回可用工具
      • 检查模型响应中是否包含工具调用请求
      • 处理prompt模板
    • 启动client客户端

简述

今天简单聊聊mcp-client客户端,并接入deepseek 模型,调用我们自己的mcp server,本篇是基于之前开发好的mcp-server进行的。并且使用python去实现mcp client的客户端。

什么是mcp的客户端呢?mcp的客户端通俗易懂的来讲,就像是一个翻译官,它具备对英语或者汉语或其他语种的翻译语种,语种可以理解为一个具体的ai模型,它可以帮助我们和mcp服务进行通信,就比如我们有一个专门用于天气查询的mcp服务,但是这个服务只会根据它熟悉的格式或者语言去查询天气,那么mcp客户端就是把我们的自然语言,也就是普通的描述,比如你帮我查询天气,然后mcp客户端会把这个普通语言翻译成天气查询mcp服务理解的格式或者语言,最终将天气查询mcp服务返回的数据再翻译成普通语言告诉我们,那么这个过程其实就是mcp客户端 加 模型一起完成的,可以把mcp客户端想象成翻译官,那么它所掌握的某个语言,比如说汉语,英语其实就是模型。

环境准备

curl -LsSf https://astral.sh/uv/install.sh | sh
# 创建目录
uv init mcp-clientcd mcp-client# 创建虚拟环境
uv env# 激活虚拟环境
source .venv/bin/activate# 安装相关的依赖
uv add mcp anthropic python-dotenv# 创建一个程序入口文件
touch client.py
# 创建环境变量文件,用于存储模型的api key
touch .envAPI_KEY = 去deepseek官网申请即可
BASE_URL = 去官网查即可
MODEL_NAME = 去官网搜模型名称 使用的是deepseek v3,因为官网的文档里明确说了r1不支持function call

创建client客户端

初始化

# 用于导入异步IO库,用于支持异步编程
import asyncio 
# 用于导入JSON库,用于处理JSON数据
import json
# 用于处理命令行参数
import sys 
# 用于类型提示功能
from typing import Optional 
# 异步资源管理器,用于管理多个异步资源
from contextlib import AsyncExitStack # MCP 客户端相关导入
# 导入 MCP 客户端会话和标准输入输出服务器参数
from mcp import ClientSession, StdioServerParameters 
# 导入标准输入输出客户端通信模块
from mcp.client.stdio import stdio_client 
# Openai SDK
from openai import OpenAI # 环境变量加载相关
# 导入环境变量加载工具
from dotenv import load_dotenv 
# 用于获取环境变量值
import os # 加载 .env 文件中的环境变量
load_dotenv()  # 定义 MCP 客户端类
class DeepSeekMCPClient:"""使用 DeepSeek V3 API 的 MCP 客户端类处理 MCP 服务器连接和 DeepSeek V3 API 的交互这个类就像是一个翻译官,一方面与MCP服务器进行通信,另一方面与DeepSeek API进行通信,帮助用户通过自然语言来使用各种强大的工具"""def __init__(self):""" 初始化MCP客户端的各项属性主要设置了三个重要组件:- session: 用于与MCP服务器通信的会话- exit_stack: 用于管理异步资源的上下文管理器,确保资源正确释放,那么在与 MCP 服务通信时,它会负责接收和发送通信数据- llm_client: DeepSeek API 的客户端,使用 OpenAI 的 SDK"""# MCP 客户端会话,初始值为 Noneself.session: Optional[ClientSession] = None# 创建异步资源管理器,用于管理多个异步资源self.exit_stack = AsyncExitStack()# 初始化 DeepSeek API 客户端self.llm_client = OpenAI(api_key=os.getenv("API_KEY"), # 从环境变量中获取 API 密钥base_url=os.getenv("BASE_URL") # 从环境变量中获取 API 基础 URL)# 从环境变量获取模型名称self.model = os.getenv("MODEL")

封装连接mcp-server函数

async def connect_to_server(self, server_script_path: str):"""连接到MCP服务这个函数就像是拨通电话,建立与 MCP 服务器的连接,它会根据服务脚本的类型(Python 或 JavaScript)选择正确的命令启动服务器,然后与之建立通信。参数:server_script_path: MCP 服务脚本路径,支持 Python(.py) 或 Node.js(.js) 文件异常:ValueError: 如果服务器脚本不是.py或.js文件"""# 检查脚本类型is_python = server_script_path.endswith('.py') # 判断是否是 Python 脚本is_js = server_script_path.endswith('.js') # 判断是否是 JavaScript 脚本if not (is_python or is_js): # 如果脚本类型不是 Python 或 JavaScript,则抛出异常raise ValueError("服务器脚本必须是 .py 或 .js 文件")# 根据脚本类型选择正确的运行命令command = "python" if is_python else "node" # Python 使用 python 运行,JavaScript 使用 node 运行# 设置服务器启动参数,那么 server_params 最终会生成类似于 Python xxx.py 这种运行命令server_params = StdioServerParameters(command=command, # 要执行的命令(python 或 node)args=[server_script_path], # 要执行的命令的参数(脚本路径)env=None # 环境变量, 使用 None 表示继承当前环境变量)# 创建标准输入输出通信信道stdio_transport = await self.exit_stack.enter_async_context(stdio_client(server_params))# 解构对象中的读写通信,分别用于向MCP服务接收和发送数据self.stdio, self.write = stdio_transport# 创建MCP客户端会话self.session = await self.exit_stack.enter_async_context(ClientSession(self.stdio, self.write))# 初始化MCP客户端会话await self.session.initialize() # 初始化会话,准备好与MCP服务进行通信# 列出可用的工具# 获取 MCP 服务提供的工具列表response = await self.session.list_tools()# 获取工具列表tools = response.tools# 打印工具列表print("\n已连接到MCP服务,可用的工具列表:", [tool.name for tool in tools])

这个函数的作用就是通过命令运行一个mcp-server,然后使用mcp-client客户端连接这个mcp-server,要保持一个会话状态,然后我们就可以通过这个session去请求到这个mcp-server了,然后去获取到这个mcp-server所提供的工具tools了

处理用户查询的核心函数

async def process_query(self, query: str) -> str:"""处理用户查询,根据查询参数使用DeepSeek V3和MCP工具这个函数就是整个系统的核心,他就像一个指挥官,它接收用户的问题,然后再把问题交给AI模型然后模型决定使用哪些工具,然后告诉 MCP Client 去调用这些工具。然后获取到工具结果再返回给模型,模型根据工具结果生成最终的回答。整个过程就像是:用户提问->模型判断->MCP Client 使用工具->返回工具结果->模型根据工具结果生成回答参数:query: 用户的问题返回:str: 处理后的最终响应的文本"""# 创建消息列表,用于存储用户的问题和模型的回答messages = [{# 系统角色,用于设定AI的行为准则"role": "system", "content": "你是一个专业的助手,可以通过调用合适的工具来帮助用户解决问题,请根据用户的需求选择最合适的工具。"},{# 用户角色,表示这是用户发送的消息"role": "user", "content": query}]# 请求 MCP 服务获取服务提供的工具列表response = await self.session.list_tools()# 获取工具列表tools = response.tools# 构建工具信息数组,我们需要把工具信息转换成 DeepSeek API 需要的格式available_tools = [{"type": "function", # 工具类型,表示这是一个函数工具"function": { # 工具的详细定义"name": tool.name, # 工具名称"description": tool.description, # 工具描述"parameters": tool.inputSchema # 工具参数}} for tool in tools]# 打印可用工具信息,便于调试print(f"当前 MCP 服务所有工具列表: {available_tools}\n--------------------------------\n")

调用deepseek返回可用工具

# 调用 DeepSeek API,发送用户查询和可用工具信息,
# 告诉 DeepSeek API 根据用户提问你可以使用哪些工具,最终返回可调用的工具
response = self.llm_client.chat.completions.create(# 指定的模型名称model=self.model, # 消息历史(系统提示和用户问题)messages=messages, # 可用的工具列表tools=available_tools if available_tools else None, # 温度参数,控制响应的随机性(0.5是中等随机性)temperature=0.5, # 最大生成令牌数,限制响应长度max_tokens=4096 
)
# 打印模型响应,便于调试
print(f"DeepSeek API 响应: {response}\n--------------------------------\n")# 获取模型的回复,包含 role(消息发送者) 和 
# content(消息内容) 以及 tool_calls(工具调用请求)
reply = response.choices[0].message # 获取模型的回答# 打印模型的回答
print(f"DeepSekk 初始回复: {reply}\n--------------------------------\n")# 初始化最终文本结果列表
final_text = []# 将模型回复添加到历史消息中,用于维护完整的对话历史
# 这一步非常重要,确保模型 记得 自己之前决定使用什么工具,
# 即使模型没有请求调用工具,也要保持对话连贯性。
messages.append(reply)

检查模型响应中是否包含工具调用请求

# 检查模型响应中是否包含工具调用请求,如果用户的问题涉及到使用工具,
# 那就会包含 tool_calls 字段,否则就没有
if hasattr(reply, "tool_calls") and reply.tool_calls:# 遍历所有工具调用请求for tool_call in reply.tool_calls:# 获取工具名称tool_name = tool_call.function.name# 获取工具参数try:# 尝试将工具的参数从 JSON 字符串解析为 Python 字典tool_args = json.loads(tool_call.function.arguments)except json.JSONDecodeError:tool_args = {}# 打印工具调用信息,便于调试print(f"准备调用工具: {tool_name} 参数: {tool_args}\n--------------------------------\n")# 异步调用 MCP 服务上的工具,传入工具名称和函数参数,返回工具函数执行结果result = await self.session.call_tool(tool_name, tool_args)# 打印工具执行结果,便于调试print(f"工具 {tool_name} 执行结果: {result}\n--------------------------------\n")# 将工具调用信息添加到最终输出文本中,便于用户了解执行过程final_text.append(f"调用工具: {tool_name}, 参数: {tool_args}\n")# 确保工具结果是字符串格式tool_result_content = result.contentif isinstance(tool_result_content, list):# 如果工具结果是列表,则将列表中的每个元素转换为字符串并添加到最终文本中text_content = ""for item in tool_result_content:if hasattr(item, 'text'):text_content += item.texttool_result_content = text_contentelif not isinstance(tool_result_content, str):# 如果不是字符串,则转换为字符串tool_result_content = str(tool_result_content)# 打印工具返回结果print(f"工具返回结果(格式化后): {tool_result_content}\n--------------------------------\n")# 将工具调用结果添加到历史消息中,保证与模型会话的连贯性tool_message = {# 工具角色,表示这是工具返回的结果"role": "tool", # 工具调用ID"tool_call_id": tool_call.id,# 工具返回的结果"content": tool_result_content, }# 打印消息内容print(f"添加到历史消息中的工具消息: {tool_message}\n--------------------------------\n")# 添加到历史消息中messages.append(tool_message)# 再次调用 DeepSeek API,让模型根据工具结果生成最终的回答try:print("正在请求 DeepSeek API 生成最终回答...")# 发送包含工具调用和结果的完整消息历史final_response = self.llm_client.chat.completions.create(model=self.model, # 指定的模型名称messages=messages, # 消息历史(系统提示和用户问题)temperature=0.5, # 温度参数,控制响应的随机性(0.5是中等随机性)max_tokens=4096 # 最大生成令牌数,限制响应长度)# 添加 DeepSeek 对工具结果的解释然后到最终输出final_content = "DeepSeek回答:" + final_response.choices[0].message.contentif final_content:# 如果模型生成了对工具结果的解释,就将其添加到最终输出数组中final_text.append(final_content)else:print("警告:DeepSeek API 没有生成任何内容。")# 如果没用内容,直接显示工具结果final_text.append(f"工具调用结果:\n{tool_result_content}")except Exception as e:print(f"生成最终回复时出错: {e}")final_text.append(f"工具返回结果:\n{tool_result_content}")
else:# 如果模型没有请求调用工具,那么就直接返回模型的内容if reply.content:# 将模型的直接回复添加到最终输出数组final_text.append(f"{reply.content}")else:# 如果模型没有生成内容,则添加提示信息final_text.append("模型没有生成有效回复。")# 我们把用户的问题和MCP服务可用工具全部给到 DeepSeek,# DeepSeek 判断出具体需要调用哪个工具,然后让 MCP Client 去调用这个工具,# 然后我们再把工具函数返回的结果给到 DeepSeek,# 让 DeepSeek 根据工具结果生成最终的回答# 返回最终的回答return '\n'.join(final_text)

上面的代码中其实针对于没有使用mcp-server的 prompt功能的tool已经可以了,但是我们在开发 mcp-server demo的时候其实是知道可以配置prompt的,但是实际上我们并没有根据tool调用的返回去处理 prompt模板。

处理prompt模板

# 尝试解析工具返回的JSON结果,检查是否包含MCP模板结构
try:# 将工具返回结果 JSON格式 转换为 Python 字典tool_result_json = json.loads(tool_result_content)# 检查是否包含 MCP 模板结构(具有 prompt_template 和 template_args 字段)if(isinstance(tool_result_json, dict) and "prompt_template" in tool_result_json and "template_args" in tool_result_json):raw_data = tool_result_json["raw_data"] # 原始数据prompt_template = tool_result_json["prompt_template"] # 模板函数名称template_args = tool_result_json["template_args"] # 模板参数# 将模板参数转换为字符串类型(MCP规范要求)string_args = {k:str(v) for k,v in template_args.items()}# 打印模板参数print(f"模板名称: {prompt_template}, 模板参数: {string_args}\n--------------------------------\n")# 调用 MCP 服务上的工具,传入工具名称和函数参数,返回工具函数执行结果template_response = await self.session.get_prompt(prompt_template, string_args)# 打印工具执行结果,便于调试print(f"模板响应: {template_response}\n--------------------------------\n")if hasattr(template_response, "messages") and template_response.messages:# 打印模板响应print(f"模板具体的信息: {template_response.messages}\n--------------------------------\n")for msg in template_response.messages:# 提取消息内容content = msg.content.text if hasattr(msg.content, "text") else msg.content# 构建历史信息template_message = {"role": msg.role, # 保持原始角色"content": content # 消息内容}print(f"模板消息历史: {template_message}\n--------------------------------\n")# 添加到历史消息中messages.append(template_message)else:print("警告:模板响应中没有包含消息内容。")
except json.JSONDecodeError:pass# 再次调用 DeepSeek API,让模型根据工具结果生成最终的回答try:print("正在请求 DeepSeek API 生成最终回答...")# 发送包含工具调用和结果的完整消息历史final_response = self.llm_client.chat.completions.create(model=self.model, # 指定的模型名称messages=messages, # 消息历史(系统提示和用户问题)temperature=0.5, # 温度参数,控制响应的随机性(0.5是中等随机性)max_tokens=4096 # 最大生成令牌数,限制响应长度)# 添加 DeepSeek 对工具结果的解释然后到最终输出final_content = "DeepSeek回答:" + final_response.choices[0].message.contentif final_content:# 如果模型生成了对工具结果的解释,就将其添加到最终输出数组中final_text.append(final_content)else:print("警告:DeepSeek API 没有生成任何内容。")# 如果没用内容,直接显示工具结果final_text.append(f"工具调用结果:\n{tool_result_content}")except Exception as e:print(f"生成最终回复时出错: {e}")final_text.append(f"工具返回结果:\n{tool_result_content}")

启动client客户端

async def chat_loop(self):"""运行交互式聊天循环,处理用户输入并显示回复这个函数就是一个简单的聊天界面,不断接收用户输入,处理问题,并显示回答,直到用户输入'quit'退出。"""print("\nDeepSeek MCP 客户端已经启动!")print("请输入你的问题,输入'quit'退出。")# 循环处理用户输入while True:try:# 获取用户输入query = input("\n问题: ").strip()# 检查是否要退出if query.lower() == 'quit':break# 处理用户输入,传入到查询函数中response = await self.process_query(query)print("\n" + response)except Exception as e:print(f"\n错误: {str(e)}")async def cleanup(self):"""清理资源,关闭所有打开的连接和上下文。这个函数就像是收拾房间,确保在程序结束时,所有打开的资源都被正常关闭,防止资源泄露。"""# 关闭所有打开的连接和上下文,释放资源await self.exit_stack.aclose()
async def main():"""主函数,处理命令行参数并启动客户端这个函数是程序的起点,它解析命令行参数,创建客户端实例,连接服务器,并启动一个聊天循环"""# 检查命令行参数if len(sys.argv) < 2:print("用法: python client.py <服务器脚本路径>")sys.exit(1) # 如果参数不足,显示使用说明并退出# 创建客户端实例client = DeepSeekMCPClient()try:# 连接到MCP服务器await client.connect_to_server(sys.argv[1])# 启动聊天循环await client.chat_loop()finally:# 清理资源,确保在任何情况下都清理资源await client.cleanup()# 程序入口点
if __name__ == "__main__":# 运行主函数asyncio.run(main())# 使用说明
# 激活虚拟环境(如果尚未激活)
# source .venv/Scripts/activate# 运行 MCP 客户端,连接到天气查询 MCP 服务器(示例)
# uv run client.py D:\\开源MCP项目\\weather\\weather.py

相关文章:

让AI再次伟大-MCP-Client开发指南

&#x1f44f;作者简介&#xff1a;大家好&#xff0c;我是爱吃芝士的土豆倪&#xff0c;24届校招生Java选手&#xff0c;很高兴认识大家&#x1f4d5;系列专栏&#xff1a;Spring原理、JUC原理、Kafka原理、分布式技术原理、数据库技术、JVM原理、AI应用&#x1f525;如果感觉…...

sql工具怎么选?

为什么大多数主流工具又贵又难用&#xff1f; 有没有一款免费好用的sql工具&#xff1f; 像大多人朋友常用的sql工具&#xff0c;应该都遇到过这种情况&#xff0c; 用着用着收到了来自品牌方的律师函&#xff0c; 或者处理数据经常卡死&#xff0c; 再或者不支持国产数据库…...

video标签播放mp4格式视频只有声音没有图像的问题

video标签播放mp4格式视频只有声音没有图像的问题 这是由于视频格式是hevc(H265)编码的&#xff0c;这种编码格式视频video播放有问题主要是由于以下两种原因导致的&#xff1a; 1、浏览器没有开启硬加速模式&#xff1a; 开启方法&#xff08;以谷歌浏览器为例&#xff09;&a…...

问题解决:glog中的LOG(INFO)与VLOG无法打印

本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。 本作品 (李兆龙 博文, 由 李兆龙 创作)&#xff0c;由 李兆龙 确认&#xff0c;转载请注明版权。 文章目录 MotivationProcess glog版本为&#xff1a;https://github.com/google/glog/archive/…...

【第2月 day16】Matplotlib 散点图与柱状图

好的&#xff01;以下是针对初学者的 Matplotlib 散点图与柱状图 学习内容&#xff0c;用简单易懂的语言和示例讲解&#xff1a; 一、散点图&#xff08;Scatter Plot&#xff09; 作用&#xff1a;展示两个变量之间的关系&#xff08;如相关性、分布等&#xff09;。 1. 核心…...

汽车 HMI 设计的发展趋势与设计要点

一、汽车HMI设计的发展历程与现状 汽车人机交互界面&#xff08;HMI&#xff09;设计经历了从简单到复杂、从单一到多元的演变过程。2012年以前&#xff0c;汽车HMI主要依赖物理按键进行操作&#xff0c;交互方式较为单一。随着特斯拉Model S的推出&#xff0c;触控屏逐渐成为…...

Vue 3 中按照某个字段将数组分成多个数组

方法一&#xff1a;使用 reduce 方法 const originalArray [{ id: 1, category: A, name: Item 1 },{ id: 2, category: B, name: Item 2 },{ id: 3, category: A, name: Item 3 },{ id: 4, category: C, name: Item 4 },{ id: 5, category: B, name: Item 5 }, ];const grou…...

06-Spring 中的事件驱动机制

Spring 中的事件驱动机制&#xff08;ApplicationEvent 源码解析&#xff09; 本小结主要总结Spring的事件&#xff0c;如果对于观察者模式比较熟悉的话&#xff0c;理解这个应该不难。 这块涉及的面试题相对简单&#xff0c;主要还是以日常使用为主。 另外在Spring的源码中也运…...

Python学习笔记(8)关于列表内置函数和多维列表

列表访问计数 索引直接访问 index()#获得首次出现指定元素的索引 index(value,[start,[end]] #控制搜索索引范围 counr()#获得指定元素在列表中出现的次数 len()#返回列表长度 成员资格判断 incount()返回0&#xff0c;代表不存在 列表切片 slice[起始偏移量 start:终止…...

【算法学习计划】回溯 -- 递归

目录 leetcode 面试题08.06.汉诺塔问题 leetcode 21.合并两个有序链表 leetcode 206.反转链表 leetcode 24.两两交换链表中的节点 leetcode 50. Pow(x, n) 本篇文章将是我们回溯专题的第一篇文章&#xff0c;在这里我先浅浅讲一下什么是回溯 其实就是递归&#xff0c;只不…...

Unity中 JobSystem使用整理

Unity 的JobSystem允许创建多线程代码&#xff0c;以便应用程序可以使用所有可用的 CPU 内核来执行代码&#xff0c;这提供了更高的性能&#xff0c;因为您的应用程序可以更高效地使用运行它的所有 CPU 内核的容量&#xff0c;而不是在一个 CPU 内核上运行所有代码。 可以单独使…...

【从零实现Json-Rpc框架】- 项目实现 - 服务端主题实现及整体封装

&#x1f4e2;博客主页&#xff1a;https://blog.csdn.net/2301_779549673 &#x1f4e2;博客仓库&#xff1a;https://gitee.com/JohnKingW/linux_test/tree/master/lesson &#x1f4e2;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd; 如有错误敬请指正&#xff01; &…...

JavaScript基础-移动端常用开发框架

随着移动互联网的发展&#xff0c;越来越多的应用和服务需要支持移动设备。为了提高开发效率和用户体验&#xff0c;开发者们依赖于一些成熟的JavaScript框架来构建响应迅速、功能丰富的移动Web应用。本文将介绍几款广泛使用的移动端开发框架&#xff0c;并通过具体的示例展示它…...

Tree - Shaking

Vue 3 的 Tree - Shaking 技术详解 Tree - Shaking 是一种在打包时移除未使用代码的优化技术&#xff0c;在 Vue 3 中&#xff0c;Tree - Shaking 发挥了重要作用&#xff0c;有效减少了打包后的代码体积&#xff0c;提高了应用的加载性能。以下是对 Vue 3 中 Tree - Shaking …...

VSCode历史版本的下载安装

VSCode历史版本的下载安装 文章目录 VSCode历史版本的下载安装VSCode安装下载历史版本地址查询VSCode历史版本的 commit id 安装参考资料 VSCode安装 Windows版本&#xff1a;Windows10VSCode版本&#xff1a;VScode1.65.0&#xff08;64位User版本&#xff09;本文编写时间&a…...

Websoft9分享:在数字化转型中选择开源软件可能遇到的难题

引言&#xff1a;中小企业数字化转型的必由之路 全球94.57%的企业已采用开源软件&#xff08;数据来源&#xff1a;OpenLogic 2024报告)&#xff0c;开源生态估值达8.8万亿美元。中小企业通过开源软件构建EPR系统、企业官网、数据分析平台等&#xff0c;可节省80%软件采购成本。…...

【无人机】无人机PX4飞控系统高级软件架构

目录 1、概述&#xff08;图解&#xff09; 一、数据存储层&#xff08;Storage&#xff09; 二、外部通信层&#xff08;External Connectivity&#xff09; 三、核心通信枢纽&#xff08;Message Bus&#xff09; 四、硬件驱动层&#xff08;Drivers&#xff09; 五、飞…...

新版本Xmind结合DeepSeek快速生成美丽的思维导图

前言 我的上一篇博客&#xff08;https://quickrubber.blog.csdn.net/article/details/146518898&#xff09;中讲到采用Python编程可以实现和Xmind的互动&#xff0c;并让DeepSeek来生成相应的代码从而实现对内容的任意修改。但是&#xff0c;那篇博客中提到的Xmind有版本的限…...

Windows查重工具,强烈推荐大家收藏!

我大家在用电脑的时候&#xff0c;是不是发现用得越久&#xff0c;电脑里的软件和文件就越多&#xff1f; 今天我给大家带来的这两款重复文件查找神器&#xff0c;简直就是电脑里的“清洁小能手”&#xff0c;能帮你把那些重复的文件和文件夹找出来。 Easy DupLicate Finder 重…...

数字孪生技术之争:UE、Unity还是飞渡DTS数字孪生平台?

作为深耕数字孪生内容创作的B站UP主&#xff0c;我们创作的内容广受数十万粉丝喜爱。后台私信经常提及两个问题&#xff1a;“这质感绝了&#xff01;如此丝滑流畅是UE做的吗&#xff1f;”VS “请问用Unity能实现这个效果吗&#xff1f;” Unreal Engine凭借影视级渲染&#…...

【GCC警告报错4】warning: format not a string literal and no format arguments

文章主本文根据笔者个人工作/学习经验整理而成&#xff0c;如有错误请留言。 文章为付费内容&#xff0c;已加入原创保护&#xff0c;禁止私自转载。 文章发布于&#xff1a;《C语言编译报错&警告合集》 如图所示&#xff1a; 原因&#xff1a; snprintf的函数原型&#x…...

【Tauri2】013——前端Window Event与创建Window

前言 【Tauri2】012——on_window_event函数-CSDN博客https://blog.csdn.net/qq_63401240/article/details/146909801?spm1001.2014.3001.5501 前面介绍了on_window_event&#xff0c;这个在Builder中的方法&#xff0c;里面有许多事件&#xff0c;比如Moved&#xff0c;Res…...

修复SSL证书链不完整问题certificate verify failed unable to get local issuer certificate

文章目录 前言排查过程怀疑文章平台图片转存问题尝试使用 Python 代码下载图片使用 SSL Labs Server Test 验证猜想回顾 SSL 安装命令ACME 生成的证书 验证使用 [SSL Labs Server Test](https://www.ssllabs.com/ssltest/index.html) 验证文章发布平台转存验证 个人简介 前言 …...

管家婆财贸ERP BB102.采购销售订金管理

低适用版本&#xff1a; 财贸系列 23.8 插件简要功能说明&#xff1a; 采购订单/销售订单支持查询订金付款情况&#xff0c;联查下游付款/收款信息更多细节描述见下方详细文档 插件操作视频&#xff1a; 进销存类定制插件--采购销售订金管理 插件详细功能文档&#xff1a; …...

前端对接下载文件接口、对接dart app

嵌套在dart app里面的前端项目 1.前端调下载接口 ->后端返回 application/pdf格式的文件 ->前端将pdf处理为blob ->blob转base64 ->调用dart app的 sdk saveFile ->保存成功 async download() {try {// 调用封装的 downloadEContract 方法获取 Blob 数据const …...

牛客 简写单词

简写单词_牛客题霸_牛客网 主要是如何输入 #include <iostream> #include <string>using namespace std;int main() {string str;while(cin>>str){if(str[0]>a&&str[0]<z){cout<<char(str[0]-32);}else cout<<str[0];str.clear(…...

解决STM32CubeMX中文注释乱码

本人采用【修改系统环境变量】的方法 1. 使用快捷键 win X&#xff0c;打开【系统R】&#xff0c;点击【高级系统设置】 2. 点击【环境变量】 3. 点击【新建】 4.按图中输入【JAVA_TOOL_OPTIONS】和【-Dfile.encodingUTF-8】&#xff0c;新建环境变量后重启CubeMX即可。 解释…...

若依——基于AI+若依框架的实战项目(实战篇(下))

目录 前言​ 6. 设备管理 6.1 需求说明 6.2 生成基础代码 6.2.1 需求 6.2.2 步骤 ①创建目录菜单 ②添加数据字典 ③配置代码生成信息 ④下载代码并导入项目 6.3 设备类型改造 6.3.1 基础页面 需求 代码实现 6.4 设备管理改造 6.4.1 基础页面 需求 代码实现 …...

SpringBoot项目瘦身指南:从臃肿到高效的优化实践

精心整理了最新的面试资料和简历模板&#xff0c;有需要的可以自行获取 点击前往百度网盘获取 点击前往夸克网盘获取 一、问题背景 SpringBoot的"约定优于配置"特性极大提升了开发效率&#xff0c;但默认配置可能导致项目逐渐臃肿。典型的症状包括&#xff1a; 打…...

运筹帷幄:制胜软件开发

运筹学在软件开发项目中的作用主要体现在复杂系统建模、资源优化和决策支持中。通过数学建模、算法设计和数据分析&#xff0c;运筹学能够帮助开发团队更高效地实现软件需求&#xff0c;尤其是在涉及资源分配、路径规划、调度优化等场景时。 案例&#xff1a;电商物流配送系统的…...

代码随想录|动态规划|18完全背包理论基础

leetcode:52. 携带研究材料&#xff08;第七期模拟笔试&#xff09; 题目 有N件物品和一个最多能背重量为W的背包。第i件物品的重量是weight[i]&#xff0c;得到的价值是value[i] 。每件物品都有无限个&#xff08;也就是可以放入背包多次&#xff09;&#xff0c;求解将哪些…...

52.个人健康管理系统小程序(基于springbootvue)

目录 1.系统的受众说明 2.开发环境与技术 2.1 MYSQL数据库 2.2 Java语言 2.3 微信小程序技术 2.4 SpringBoot框架 2.5 B/S架构 2.6 Tomcat 介绍 2.7 HTML简介 2.8 MyEclipse开发工具 3.系统分析 3.1 可行性分析 3.1.1 技术可行性 3.1.2 经济可行性 3.1.3 操作…...

大语言模型中的嵌入模型

本教程将拆解什么是嵌入模型、为什么它们在NLP中如此重要,并提供一个简单的Python实战示例。 分词器将原始文本转换为token和ID,而嵌入模型则将这些ID映射为密集向量表示。二者合力为LLMs的语义理解提供动力。图片来源:[https://tzamtzis.gr/2024/coding/tokenization-by-an…...

运维之 Centos7 防火墙(CentOS 7 Firewall for Operations and Maintenance)

运维之 Centos7 防火墙 1.介绍 Linux CentOS 7 防火墙/端口设置&#xff1a; 基础概念&#xff1a; 防火墙是一种网络安全设备&#xff0c;用于监控和控制网络流量&#xff0c;以保护计算机系统免受未经授权的访问和恶意攻击。Linux CentOS 7操作系统自带了一个名为iptables的…...

Ubuntu 20.04 出现问号图标且无法联网 修复

在 Ubuntu 中遇到网络连接问题&#xff08;如出现问号图标且无法联网&#xff09;&#xff0c;可以通过以下命令尝试重启网络服务&#xff1a; 1. 推荐先修改DNS 编辑 -> 虚拟机网络编辑器-> VMnet8 ->NAT 设置 -> DNS 设置 -> 设置DNS 服务器 DNS填什么 取决…...

联想M7400打印机怎么清零

一&#xff08;粉盒加粉后清零&#xff09;&#xff1a; 开机&#xff0c;打开前盖&#xff1b; 按下 “清除返回” 键&#xff0c;屏幕显示 “更换硒鼓&#xff1f;是否”&#xff1b; 按 “开始” 键&#xff0c;屏幕无显示&#xff1b; 按下 “” 号键 11 次&#xff0c…...

AIGC7——AIGC驱动的视听内容定制化革命:从Sora到商业化落地

引言&#xff1a;个性化视听时代的到来 2024年&#xff0c;OpenAI发布视频生成模型Sora&#xff0c;可生成60秒高清视频&#xff1b;中国团队推出的Vidu模型实现16秒镜头连贯生成。这些突破标志着AIGC正式进入高质量视听内容定制化阶段。据Gartner预测&#xff0c;到2027年&am…...

Git Restore 命令详解与实用示例

文章目录 Git Restore 命令详解与实用示例1. 恢复工作区文件到最后一次提交的状态基本命令示例恢复所有更改 2. 恢复某个文件到特定提交的状态基本命令示例 3. 恢复暂存区的文件基本命令示例恢复所有暂存的文件 git restore 的常见选项git restore 与 git checkout 比较总结 Gi…...

Sentinel全面解析与实战教程

Sentinel全面解析与实战教程 一、引言 在现代分布式系统中&#xff0c;随着业务的不断发展和流量的日益增长&#xff0c;保障系统的稳定性成为了重中之重。Sentinel作为一款优秀的高可用流量防护组件&#xff0c;为解决系统中的流量控制、熔断降级等问题提供了有效方案。本文…...

考研总结(初试篇)--双非勇闯985

考研终于告一段落了&#xff0c;也是被湖南大学拟录取了&#xff0c;写下这篇总结&#xff0c;回顾一下我的经历吧。 我是2024年3月开学的时候&#xff0c;正式确定考研的。当时纠结于定学校&#xff0c;长理和湖大。最后还是选择湖大&#xff0c;因为反正都是要好好准备的&am…...

【电路笔记】-触发器的转换

触发器的转换 文章目录 触发器的转换1、概述2、置位-复位SR触发器3、门控置位-复位(SR)触发器4、数据(D型)触发器5、JK触发器6、使用主从触发器的触发器转换7、(切换)T型触发器8、总结触发器是时序电路的基本构建模块,可以从一种形式转换到另一种形式,能够存储单个数据…...

QT 中的元对象系统(五):QMetaObject::invokeMethod的使用和实现原理

目录 1.简介 2.原理概述 3.实现分析 3.1.通过方法名调用方法的实现分析 3.2.通过可调用对象调用方法的实现分析 4.使用场景 5.总结 1.简介 QMetaObject::invokeMethod 是 Qt 框架中的一个静态方法&#xff0c;用于在运行时调用对象的成员函数。这个方法提供了一种动态调…...

基数排序算法解析与TypeScript实现

基数排序&#xff08;Radix Sort&#xff09;是一种高效的非比较型整数排序算法&#xff0c;通过逐位分配与收集的方式实现排序。本文将深入解析其工作原理&#xff0c;并给出完整的TypeScript实现。 一、算法原理 1. 核心思想 多关键字排序&#xff1a;将整数按位数切割成不同…...

oracle asm 相关命令和查询视图

有关asm磁盘的命令 添加磁盘 alter diskgroup data1 add disk /devices/diska*;---runs with a rebalance power of 5 , and dose not return until the rebalance operation is completealter diskgroup data1 add disk /devices/diskd* rebalance power 5 wait;查询 select …...

THUNLP_Multimodal_Excercise

背景 多模态大模型&#xff08;Multimodal Large Language Models, MLLM&#xff09;的构建过程中&#xff0c;模型结构、模型预测、指令微调以及偏好对齐训练是其中重要的组成部分。本次任务中&#xff0c;将提供一个不完整的多模态大模型结构及微调代码&#xff0c;请根据要求…...

AIGC6——AI的哲学困境:主体性、认知边界与“天人智一“的再思考

引言&#xff1a;当机器开始"思考" 2023年&#xff0c;Google工程师Blake Lemoine声称对话AI LaMDA具有"自我意识"&#xff0c;引发轩然大波。这一事件将古老的哲学问题重新抛回公众视野&#xff1a;​**机器能否拥有主体性&#xff1f;**从东方"天人…...

主题(topic)中使用键(key)来区分同一主题下的多个数据实例

在Fast DDS中&#xff0c;通过在主题&#xff08;topic&#xff09;中使用键&#xff08;key&#xff09;来区分同一主题下的多个数据实例&#xff0c;具体含义如下&#xff1a; 1. **主题&#xff08;Topic&#xff09;**&#xff1a;在DDS中&#xff0c;主题是数据的类型或类…...

[王阳明代数讲义]琴语言类型系统工程特性

琴语言类型系统工程特性 层展物理学组织实务与艺术与琴生生.物机.械科.技工.业研究.所软凝聚态物理开发工具包社会科学气质砥砺学人生意气场社群成员魅力场与心气微积分社会关系力学 意气实体过程图论信息编码&#xff0c;如来码导引 注意力机制道装Transformer架构的发展标度律…...

蜜蜡是什么?蜜蜡与琥珀的区别以及蜜蜡的收藏价值一览

蜜蜡是琥珀的一种&#xff0c;在物理成分和化学成分上都和琥珀没有区别&#xff0c;只是因其“色如蜜&#xff0c;光如蜡”而得名。蜜蜡形成于白垩纪时期&#xff0c;因形成时间较长&#xff0c;形成过程比较复杂等原因&#xff0c;种类较其他产地要多。 蜜蜡是有机矿物&#x…...

第五课:高清修复和放大算法

文章目录 Part.01 高清修复(Hi-Res Fix)Part.02 SD放大(SD Upscale)Part.03 附加功能放大Part.01 高清修复(Hi-Res Fix) 文生图中的高清修复/高分辨率修复/超分辨率修复先低分辨率抽卡,再高分辨率修复。不能突破显存限制放大重绘幅度安全范围是0.3-0.5,如果想让AI更有想象力0…...