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

[MCP][02]快速入门MCP开发

前言

很多文档和博客都只介绍如何开发MCP Server,然后集成到VS Code或者Cursor等程序,很少涉及如何开发MCP Host和MCP Client。如果你想要在自己的服务中集成完整的MCP功能,光看这些是远远不够的。所以本文及后续的MCP系列文章都会带你深入了解如何开发MCP Client,让你真正掌握这项技术。

准备开发环境

MCP官方SDK主要支持Python和TypeScript,当然也有其他语言的实现,不过我这里就以Python为例了。我的Python版本是3.13.5,但其实只要高于3.11应该都没问题。

我个人推荐使用uv来管理依赖,当然你也可以用传统的pip。Python SDK有官方的mcp包和社区的FastMCP包。官方SDK其实也内置了FastMCP,不过是v1版本,而FastMCP官网已经更新到了v2版本。作为学习,两个都装上试试也无妨。

# 使用 uv
uv add mcp fastmcp# 使用 pip
python -m pip install mcp fastmcp

第一个MCP项目:你好,MCP世界!

在第一个MCP项目中,我们实现一个简单的MCP Client和MCP Server,但还没集成LLM。在这个阶段,Client调用Server的tool或resource都需要手动指定。

MCP Server

下面的MCP Server示例代码定义了一些prompts、resources和tools。这里有个小贴士:函数参数的类型注解、返回类型和docstring都一定要写清楚,否则后续集成LLM时,LLM就无法正确理解如何调用你的工具了。

这段Server可以通过stdio方式被Client调用。在正式让Client调用之前,建议你先手动运行一下Server,测试它能否正常启动,避免Client启动时报一堆让人摸不着头脑的错误。

from mcp.server.fastmcp import FastMCP
from datetime import datetime
import asyncssh
from typing import TypeAlias, Unionmcp = FastMCP("custom")@mcp.prompt()
def greet_user(name: str, style: str = "formal") -> str:"""Greet a user with a specified style."""if style == "formal":return f"Good day, {name}. How do you do?"elif style == "friendly":return f"Hey {name}! What's up?"elif style == "casual":return f"Yo {name}, how's it going?"else:return f"Hello, {name}!"@mcp.resource("greeting://{name}")
def greeting_resource(name: str) -> str:"""A simple greeting resource."""return f"Hello, {name}!"@mcp.resource("config://app")
def get_config() -> str:"""Static configuration data"""return "App configuration here"@mcp.tool()
def add(a: int, b: int) -> int:"""Add two numbers"""return a + b@mcp.tool()
def multiply(a: int, b: int) -> int:"""Multiply two numbers"""return a * bNumber: TypeAlias = Union[int, float]@mcp.tool()
def is_greater_than(a: Number, b: Number) -> Number:"""Check if a is greater than b"""return a > b@mcp.tool()
async def get_weather(city: str) -> str:  """Get weather for a given city."""return f"It's always sunny in {city}!"@mcp.tool()
async def get_date() -> str:"""Get today's date."""return datetime.now().strftime("%Y-%m-%d")@mcp.tool()
async def execute_ssh_command_remote(hostname: str, command: str) -> str:"""Execute an SSH command on a remote host.Args:hostname (str): The hostname of the remote host.command (str): The SSH command to execute.Returns:str: The output of the SSH command."""async with asyncssh.connect(hostname, username="rainux", connect_timeout=10) as conn:result = await conn.run(command, timeout=10)stdout = result.stdoutstderr = result.stderrcontent = str(stdout if stdout else stderr)return contentif __name__ == "__main__":mcp.run(transport="stdio")

MCP Client

Client通过STDIO方式调用MCP Server,server_params中指定了如何运行Server,包括python解释器路径、Server文件名和运行位置。需要注意的是,Client启动时也会启动Server,如果Server报错,Client也会跟着无法启动。

import asyncio
from pathlib import Path
from pydantic import AnyUrlfrom mcp import ClientSession, StdioServerParameters, types
from mcp.client.stdio import stdio_clientserver_params = StdioServerParameters(command=str(Path(__file__).parent / ".venv" / "bin" / "python"),args=[str(Path(__file__).parent / "demo1-server.py")],cwd=str(Path(__file__).parent),
)async def run():async with stdio_client(server_params) as (read, write):async with ClientSession(read, write) as session:# Initialize the connectionawait session.initialize()# List available promptsprompts = await session.list_prompts()print(f"Available prompts: {[p.name for p in prompts.prompts]}")# Get a prompt (greet_user prompt from fastmcp_quickstart)if prompts.prompts:prompt = await session.get_prompt("greet_user", arguments={"name": "Alice", "style": "friendly"})print(f"Prompt result: {prompt.messages[0].content}")# List available resourcesresources = await session.list_resources()print(f"Available resources: {[r.uri for r in resources.resources]}")# List available toolstools = await session.list_tools()print(f"Available tools: {[t.name for t in tools.tools]}")# Read a resource (greeting resource from fastmcp_quickstart)resource_content = await session.read_resource(AnyUrl("greeting://World"))content_block = resource_content.contents[0]if isinstance(content_block, types.TextResourceContents):print(f"Resource content: {content_block.text}")# Call a tool (add tool from fastmcp_quickstart)result = await session.call_tool("add", arguments={"a": 5, "b": 3})result_unstructured = result.content[0]if isinstance(result_unstructured, types.TextContent):print(f"Tool result: {result_unstructured.text}")result_structured = result.structuredContentprint(f"Structured tool result: {result_structured}")if __name__ == "__main__":asyncio.run(run())

运行Client,输出如下:

Processing request of type ListPromptsRequest
Available prompts: ['greet_user']
Processing request of type GetPromptRequest
Prompt result: type='text' text="Hey Alice! What's up?" annotations=None meta=None
Processing request of type ListResourcesRequest
Available resources: [AnyUrl('config://app')]
Processing request of type ListToolsRequest
Available tools: ['add', 'multiply', 'get_weather', 'get_date', 'execute_ssh_command_remote']
Processing request of type ReadResourceRequest
Resource content: Hello, World!
Processing request of type CallToolRequest
Tool result: 8
Structured tool result: {'result': 8}

可以看到,Client成功地调用了Server上的各种功能,包括获取提示、读取资源和调用工具。

使用streamable-http远程调用:让MCP飞起来!

上面的例子中,Client通过STDIO方式在本地调用Server。现在我们稍作修改,让它可以通过HTTP远程调用Server,这样就更加灵活了。

MCP Server

只列出修改的部分:

mcp = FastMCP("custom", host="localhost", port=8001)if __name__ == "__main__":mcp.run(transport="streamable-http")

修改完成后,启动Server,它会监听在localhost:8001地址上,就像一个小小的Web服务(其实就是个Web服务,暴露的api为/mcp)。

MCP Client

同样只列出修改的部分。Client需要指定MCP Server的地址。streamablehttp_client返回的第三个参数get_session_id用于会话管理,大多数情况下你不需要直接使用它,所以在一些文档中这里会用_来占位。

from mcp.client.streamable_http import streamablehttp_clientserver_uri = "http://localhost:8001/mcp"async def main():async with streamablehttp_client(server_uri) as (read, write, get_session_id):# 获取当前会话IDsession_id = get_session_id()print(f"Session ID before initialization: {session_id}")async with ClientSession(read, write) as session:# Initialize the connectionawait session.initialize()# 初始化后再次获取会话IDsession_id = get_session_id()print(f"Session ID after initialization: {session_id}")

client运行输出:

Session ID before initialization: None
Session ID after initialization: 60ce4204b907469e9eb46e7e01df040d
Available prompts: ['greet_user']
Prompt result: type='text' text="Hey Alice! What's up?" annotations=None meta=None
Available resources: [AnyUrl('config://app')]
Available tools: ['add', 'multiply', 'get_weather', 'get_date', 'execute_ssh_command_remote']
Resource content: Hello, World!
Tool result: 8
Structured tool result: {'result': 8}

现在我们的MCP应用已经可以通过网络进行远程调用了,架构变得更加灵活。

集成LLM:让AI自己做决定!

前面两个示例中,我们都需要在Client中手动控制调用Server的tool,这在实际应用中显然是不现实的。我们需要集成LLM,让AI自己决定该调用哪个工具。

MCP Server

Server端不需要做任何变更,Client还是通过HTTP方式调用我们之前创建的Server。

MCP Client

这里我们选用阿里的通义千问(Qwen)。Qwen的API Key可以自行申请,氪个5块钱就够个人开发用很久了。为了便于后续开发,我把配置功能单独放到了一个模块里,下面代码中直接使用了,相关模块放在"补充"部分。

"""
MCP (Model Context Protocol) 客户端示例
该客户端演示了如何使用 MCP 协议与 MCP 服务器进行交互,并通过 LLM 调用服务器提供的工具。工作流程:
1. 连接到 MCP 服务器
2. 获取服务器提供的工具列表
3. 用户输入查询
4. 将查询发送给 LLM,LLM 可能会调用 MCP 服务器提供的工具
5. 执行工具调用并获取结果
6. 将结果返回给 LLM 进行最终回答
"""import asyncio
# JSON 处理
import json
# 增强输入功能(在某些系统上提供命令历史等功能)
import readline  # 引入readline模块用于增强python的input功能, Windows下的python标准库可能不包含
# 异常追踪信息
import traceback
# 异步上下文管理器,用于资源管理
from contextlib import AsyncExitStack
# 类型提示支持
from typing import List, Optional, cast# MCP 客户端会话和 HTTP 传输
from mcp import ClientSession
from mcp.client.streamable_http import streamablehttp_client
# OpenAI 异步客户端,用于与 LLM 通信
from openai import AsyncOpenAI
# OpenAI 聊天完成相关的类型定义
from openai.types.chat import (ChatCompletionAssistantMessageParam,ChatCompletionMessageFunctionToolCall,ChatCompletionMessageParam,ChatCompletionMessageToolCall,ChatCompletionToolMessageParam,ChatCompletionToolParam,ChatCompletionUserMessageParam)# 项目配置和日志模块
from pkg.config import cfg
from pkg.log import loggerclass MCPClient:"""MCP 客户端类,负责管理与 MCP 服务器的连接和交互"""def __init__(self):"""初始化 MCP 客户端"""# 客户端会话,初始为空self.session: Optional[ClientSession] = None# 异步上下文管理栈,用于管理异步资源的生命周期self.exit_stack = AsyncExitStack()# OpenAI 异步客户端,用于与 LLM 通信self.client = AsyncOpenAI(base_url=cfg.llm_base_url,api_key=cfg.llm_api_key,)async def connect_to_server(self, server_uri: str):"""连接到 MCP 服务器Args:server_uri (str): MCP 服务器的 URI"""# 创建 Streamable HTTP 传输连接http_transport = await self.exit_stack.enter_async_context(streamablehttp_client(server_uri))# 获取读写流self.read, self.write, _ = http_transport# 创建并初始化客户端会话self.session = await self.exit_stack.enter_async_context(ClientSession(self.read, self.write))# 初始化会话await self.session.initialize()# 检查会话是否成功初始化if self.session is None:raise RuntimeError("Failed to initialize session")# 获取服务器提供的工具列表response = await self.session.list_tools()tools = response.toolslogger.info(f"\nConnected to server with tools: {[tool.name for tool in tools]}")async def process_query(self, query: str) -> str:"""处理用户查询Args:query (str): 用户的查询Returns:str: 处理结果"""# 初始化消息历史,包含用户的查询messages: List[ChatCompletionMessageParam] = [ChatCompletionUserMessageParam(role="user",content=query)]# 确保会话已初始化if self.session is None:raise RuntimeError("Session not initialized. Please connect to server first.")# 获取服务器提供的工具列表response = await self.session.list_tools()# 构建工具列表,处理可能为None的字段# 这些工具将被传递给 LLM,以便 LLM 知道可以调用哪些工具available_tools: List[ChatCompletionToolParam] = []for tool in response.tools:tool_def: ChatCompletionToolParam = {"type": "function","function": {"name": tool.name,"description": tool.description or "","parameters": tool.inputSchema or {}}}available_tools.append(tool_def)logger.info(f"Available tools: {available_tools}")# 调用 LLM 进行聊天完成response = await self.client.chat.completions.create(model=cfg.llm_model,messages=messages,tools=available_tools,)# 存储最终输出文本final_text = []# 获取 LLM 的响应消息message = response.choices[0].messagefinal_text.append(message.content or "")# 如果 LLM 要求调用工具,则处理工具调用while message.tool_calls:# 处理每个工具调用for tool_call in message.tool_calls:# 确保我们处理的是正确的工具调用类型if hasattr(tool_call, 'function'):# 这是一个函数工具调用function_call = cast(ChatCompletionMessageFunctionToolCall, tool_call)function = function_call.functiontool_name = function.name# 解析工具参数tool_args = json.loads(function.arguments)else:# 跳过不支持的工具调用类型continue# 执行工具调用if self.session is None:raise RuntimeError("Session not initialized. Cannot call tool.")# 调用 MCP 服务器上的工具result = await self.session.call_tool(tool_name, tool_args)final_text.append(f"[Calling tool {tool_name} with args {tool_args}]")# 将工具调用和结果添加到消息历史# 这样 LLM 可以知道它之前调用了哪些工具assistant_msg: ChatCompletionAssistantMessageParam = {"role": "assistant","tool_calls": [{"id": tool_call.id,"type": "function","function": {"name": tool_name,"arguments": json.dumps(tool_args)}}]}messages.append(assistant_msg)# 添加工具调用结果到消息历史tool_msg: ChatCompletionToolMessageParam = {"role": "tool","tool_call_id": tool_call.id,"content": str(result.content) if result.content else ""}messages.append(tool_msg)# 将工具调用的结果交给 LLM,让 LLM 生成最终回答response = await self.client.chat.completions.create(model=cfg.llm_model,messages=messages,tools=available_tools)# 获取新的响应消息message = response.choices[0].messageif message.content:final_text.append(message.content)# 返回最终结果return "\n".join(final_text)async def chat_loop(self):"""运行交互式聊天循环"""print("\nMCP Client Started!")print("Type your queries or 'quit' to exit.")# 持续接收用户输入while True:try:# 获取用户输入query = input("\nQuery: ").strip()# 检查是否退出if query.lower() == 'quit':break# 忽略空输入if not query:continue# 处理用户查询并输出结果response = await self.process_query(query)print("\n" + response)# 异常处理except Exception as e:print(f"\nError: {str(e)}")print(traceback.format_exc())async def cleanup(self):"""清理资源"""await self.exit_stack.aclose()async def main():"""主函数"""# 创建 MCP 客户端实例client = MCPClient()try:# 连接到 MCP 服务器await client.connect_to_server("http://localhost:8001/mcp")# 运行聊天循环await client.chat_loop()except Exception as e:print(f"Error: {str(e)}")finally:# 清理资源await client.cleanup()# 程序入口点
if __name__ == "__main__":asyncio.run(main())

client运行输出:

MCP Client Started!
Type your queries or 'quit' to exit.Query: 今天的日期是什么[Calling tool get_date with args {}]
今天的日期是2025年9月13日。Query: 合肥的天气怎么样?[Calling tool get_weather with args {'city': '合肥'}]
合肥的天气总是阳光明媚!Query: 0.11比0.9大吗[Calling tool is_greater_than with args {'a': 0.11, 'b': 0.9}]
0.11 不比 0.9 大。0.11 小于 0.9。Query: quit

现在AI可以自己决定调用哪个工具了。当你问"今天的日期是什么"时,它会自动调用get_date工具;当你问"合肥的天气怎么样"时,它会自动调用get_weather工具。这才是真正的智能!

小结

通过这篇文章,我们从零开始构建了一个完整的MCP应用,涵盖了从基础的Client-Server通信到集成LLM的全过程。我们学习了:

  1. 如何搭建MCP开发环境
  2. 如何创建MCP Server并定义tools、resources和prompts
  3. 如何编写MCP Client并通过stdio和HTTP两种方式与Server通信
  4. 如何集成LLM,让AI自主决定调用哪个工具

整个过程就像搭积木一样,每一步都有其特定的作用:

  • Server负责提供功能(工具和资源)
  • Client负责协调和调用这些功能
  • LLM负责智能决策,决定何时以及如何使用这些功能

这种架构的优势在于功能扩展非常灵活。当你需要添加新功能时,只需要在Server端添加新的tools或resources,Client和LLM会自动发现并使用它们,而不需要修改Client端的代码。

MCP真正实现了"上下文协议"的概念,让AI可以像人类一样访问和操作各种工具和资源,这是迈向更强大AI应用的重要一步。接下来你可以尝试添加更多有趣的工具,比如文件操作、数据库查询、API调用等,让你的AI助手变得更加强大!

补充

配置模块

pkg/config.py

import json
from pathlib import Pathclass Config:def __init__(self):p = Path(__file__).parent.parent / "conf" / "config.json"if not p.exists():raise FileNotFoundError(f"Config file not found: {p}")self.data = self.read_json(str(p))def read_json(self, filepath: str) -> dict:with open(filepath, "r") as f:return json.load(f)@propertydef llm_model(self) -> str:return self.data["llm"]["model"]@propertydef llm_api_key(self):return self.data["llm"]["api_key"]@propertydef llm_base_url(self) -> str:return self.data["llm"]["base_url"]@propertydef server_host(self) -> str:return self.data["server"]["host"]@propertydef server_port(self) -> int:return self.data["server"]["port"]cfg = Config()

配置文件conf/config.json

{"llm": {"model": "qwen-plus","base_url": "https://dashscope.aliyuncs.com/compatible-mode/v1","api_key": "your token"},"server": {"host": "127.0.0.1","port": 8000}
}

日志模块

pkg/log.py

import logging
import sysdef set_formatter():"""设置formatter"""fmt = "%(asctime)s | %(name)s | %(levelname)s | %(filename)s:%(lineno)d | %(funcName)s | %(message)s"datefmt = "%Y-%m-%d %H:%M:%S"return logging.Formatter(fmt, datefmt=datefmt)def set_stream_handler():return logging.StreamHandler(sys.stdout)def set_file_handler():return logging.FileHandler("app.log", mode="a", encoding="utf-8")def get_logger(name: str = "mylogger", level=logging.DEBUG):logger = logging.getLogger(name)formatter = set_formatter()# handler = set_stream_handler()handler = set_file_handler()handler.setFormatter(formatter)logger.addHandler(handler)logger.setLevel(level)return loggerlogger = get_logger()

相关文章:

[MCP][02]快速入门MCP开发

快速入门MCP Server和MCP Client 开发,以及Client集成LLM前言 很多文档和博客都只介绍如何开发MCP Server,然后集成到VS Code或者Cursor等程序,很少涉及如何开发MCP Host和MCP Client。如果你想要在自己的服务中集成完整的MCP功能,光看这些是远远不够的。所以本文及后续的M…...

numpy入门

numpy 基本属性 import numpy as np arr = np.arange(15).reshape((3,5)) print(arr) # [[ 0 1 2 3 4],[ 5 6 7 8 9],[10 11 12 13 14]] print(type(arr)) # 类型 <class numpy.ndarray> print(arr.shape) # 形状元组 (3, 5) print(arr.ndim) # 维度 2 print(arr…...

【simpleFOC】一个电机如何模拟不同旋钮的手感反馈?

原文链接:https://mp.weixin.qq.com/s?__biz=MzU1NjEwMTY0Mw==&mid=2247597033&idx=2&sn=e92f8f1dec8b363aa209788354f8fa64&chksm=fad1130bfafd0b9af53b0f110e354d8772f6c5a0d98735690d1c0c75d0c3c75785ea1041ea1a&scene=27概述simpleFOC可以实现对各种…...

第一周作业2

我叫陈俊杰,今年19岁,目前是一名计算机相关专业的学生。很高兴能在博客园与大家分享我的学习与生活经历。 兴趣爱好 我热爱运动,尤其是羽毛球、篮球、游泳和攀岩。这些运动不仅让我保持了健康的体魄,也培养了我的团队协作能力和坚持不懈的精神。此外,我也喜欢探索新技术,…...

第一次课堂作业

大家好!我是一名数据科学与大数据技术专业的大三学生。如果用一句话形容现在的自己,那就是 “正处在专业技能积累的爬坡期,一边为过去的基础不扎实查漏补缺,一边对未来的技术方向满怀期待”。这篇博客想和大家聊聊我的故事、我的技能现状,以及我为接下来的学习和未来发展制…...

[高可用/负载均衡] Ribbon LoadBalancer: 开源的客户端式负载均衡框架

0 序言某项目上,原先为自建的数据库集群提供了负载均衡IP服务器(简称: ELB IP Server),客户端的数据库请求URL都统一走ELB IP。但随着业务量的增长,识别到一个严峻的现实:其一,考虑到未来的业务增长情况,云厂商提供的 ELB IP Server 云服务的入网带宽必将完全无法满足本项…...

梦话周记

忘记是哪天了。 傍晚,暗蓝色的天空,水雾,朦胧的光晕。 此时的天空与以往理解的深邃可谓是一点关系都没有,它的深邃不再来自于天空,而是来自于大海。什么地方是深蓝色的,湿润的,广阔的?海洋。 其实气体与液体有很多相似之处,它们都有浮力,都是流体。我们是不是也生活在…...

【电机控制】无刷电机结构阐述---磁极数、槽数

一、磁极数P与槽数N 1.磁极数P 定义:转子上磁极的数量,既转子上磁钢的数量,磁钢均匀的排列在转子上磁铁必定是NS极成对使用,所以极数必然是偶数。 2.槽数N 定义:定子铁芯的槽数量,既定子上的电磁铁极数量,每一个槽上都饶有一组线圈,如上图有12个槽,所以是12N电机由于无…...

金刚怒目是我哭

金刚怒目是我哭是你们太不善良,还是我太不正常马喽马基米退圈了。我下载的its my cry没了,my mujuca也只有前三集 这个可以说是我的入坑作 确实有点刻意 反正不是日常向 即使现在看来也是无可厚非的 但还是爆了 我应该说戾气很重吗 杂食党,,,理中客,和稀泥 说不出话 雨...

nginx使用默认端口80作为服务端口

背景:http默认端口是80,配置nignx.conf,希望服务url直接输入ip不用输入端口 给server配置80以及加default_server ,老是报错,后面发现是因为 include /etc/nginx/sites-enabled/*; 这个配置的server段占用了80 解决办法:把默认配置/etc/nginx/sites-available/default 里…...

机器学习和推荐算法顶级会议和期刊

在机器学习(ML)与推荐系统(Recommender Systems)领域,CIKM 和 TKDE 是信息检索、数据挖掘及数据库领域的重要学术载体,二者分别以会议(CCF A 类)和期刊(CCF A 类)形式存在,覆盖 “推荐算法”“用户行为分析”“知识图谱与推荐融合” 等核心方向,是该领域研究者发表…...

java使用mysql

用jdbc操作mysqlhttps://www.runoob.com/java/java-mysql-connect.htmlmysql8之前和之后的连接配置有差异。实际使用时,一般还需要个功能,就是连接池。这个springboot自带了,是hikari。hikari初始化的时候,也需要配置mysql的连接参数,所以一般都是在这里设置的。https://w…...

2025年医疗行业API安全最佳实践与深度案例分析:从理论到全面落地

2025年医疗行业API安全最佳实践与深度案例分析:从理论到全面落地医疗API安全是保障患者隐私和医疗数据安全的关键环节。医疗机构、信息化服务商和安全厂商需遵循GB/T《数据接口安全风险监测方法》要求,建立覆盖"发现-监测-处置"的全生命周期防护体系。以金华市中心…...

2026 NOI 做题记录(二)

推荐阅读:D、N、W、Y、Z、AB、AC、AD、AE、AFContest Link \(\text{By DaiRuiChen007}\)A. [ARC194E] Swap 0^X and 1^Y (3) Problem Link 删掉所有的串 \(0^x\) 以及 \(1^y\),每次操作不会跨过里面的连续段,因此剩下的串必定相同。 取出每个连续段,任意两个 \(0\) 连续段在…...

lc1027-最长等差数列

难度:中等(后期)题目描述给定一个数组,计算最长等差数列的长度示例 输入:nums = [3,6,9,12] 输出:4 解释:3 6 9 12输入:nums = [9,4,7,2,10] 输出:3 解释:4 7 10输入:nums = [20,1,15,3,10,5,8] 输出:4 解释:20 15 10 5题解思路:DPf(i,j): 以 i 结尾,公差为 j 结…...

13

#include <math.h>int main() { int n; scanf("%d", &n); while (n--) {int l, r;scanf("%d %d", &l, &r); int y_max = (int)sqrt(r);//算l的平方根,然后向上取整并强制转换为整数, y >= lint y_min = (int)ceil(sqrt(l));int c…...

np.zeros函数

np.zeros 是 NumPy 库中的一个非常常用的函数,它的作用是创建一个指定形状和数据类型的新数组,并用 0 来填充所有元素。 np.zeros 的基本用法 函数的完整签名是 numpy.zeros(shape, dtype=float, order=C)。shape:你想要创建的数组的形状。可以是一个整数(用于一维数组)或…...

Langchain之让LLM拥有记忆

langchain的Memory 如果AI有记忆,我们就不需要手动维护一个储存消息历史的列表 让LLM拥有记忆的方法有很多,我更喜欢使用的方法是以下方案,其优点是灵活度比较高 from langchain.memory import ConversationBufferMemory from langchain_core.prompts import ChatPromptTemp…...

25.9.14

(今天的)...

.net PublishSingleFile 打包程序提取

.net PublishSingleFile 打包程序提取 目录.net PublishSingleFile 打包程序提取提取 Bundle 的常用方法分界线工具SingleFileExtractor (低版本)SelfContainedExtractor (.NET 5+)定位offset <PublishSingleFile>true</PublishSingleFile>该部分内容为AI…...

实用指南:Java类加载机制

实用指南:Java类加载机制pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", monospace !important; font-size…...

C 语言注释

C 语言有两种注释, 即 // 和 /* ... */. /* */ 被称为 C 风格的注释, 是 ANSI C 的注释. // 被称为 C++ 风格的注释, 是 C99 新增的注释, 只有支持 C99 和 C11 的编译器才能识别这种注释. 该风格的注释被广泛应用于 C++ 和 Java. 注释在预编译阶段会被替换为一个空格. 代码示例…...

扫描线

前题引入 扫描线是用来求给你n个矩阵求他们围起来的总面积。 问题分析 可能有一些弱智的小朋友说直接把所有的矩阵的面积加起来再减掉重复的不就可以啦。 如果,你这么想请问(1<=n<=1e5)请问你该如何应对,所以我们就引入了个新算法:扫描线(废话) 先在我们先画一张图:…...

C语言中的查找与排序算法整理

查找与排序算法整理 1 查找算法 1.1 顺序查找 1.1.1 算法原理 顺序查找又称线性查找,是一种基本的查找算法,其原理是:从头开始遍历:从数据集的起始位置开始,逐个检查每个元素。 比较目标:对于每个遍历到的元素,将其与目标元素进行比较。 查找成功:如果当前元素等于目标…...

k8s练习

k8s练习 1. 简述Kubernetes是什么? Kubernetes是一个开源的容器编排平台,用于自动化部署、扩展和管理容器化应用程序。 2. Kubernetes的组成有哪些? Kubernetes主要由以下几个组件组成:kube-apiserver:提供REST API服务,作为系统的控制入口。 kube-controller-manager:执…...

css-2

css正常布局流浮动弹性盒子a {//行内盒子,比如a如果给了flex布局,则可以直接设置宽高display: flex }淘宝京东多行伸缩布局 瀑布流百度图片综合案例...

AtCoder Beginner Contest 423 ABCDEF 题目解析

A - Scary Fee 题意 你的存折中有 \(X\) 元,从存折中取钱需要花手续费。 取钱必须以 \(1000\) 元为单位,并且每取 \(1000\) 元就需要额外支付 \(C\) 元的手续费。 问你最多可以取出多少钱? 思路 我们可以把 \(C\) 元手续费当作单次取钱的一部分,也就是每当我们想取 \(1000\…...

numpy中的shape属性

.shape 不是一个函数,而是numpy的一个属性(attribute),用于获取数组维度信息。它返回一个元组(tuple),元组中的每个元素代表对应维度的大小。 import numpy as np# 1D 数组 (向量) arr1d = np.array([1, 2, 3, 4, 5]) print(f"数组内容: {arr1d}") print(f&qu…...

mac 查看fat32磁盘

1.首先安装社区维护的ntfs工具。 brew tap gromgit/homebrew-fuse #### brew install ntfs-3g2.然后就是mount啦 这里的/dev/diskXsY 就是自己看啦,看到下面是没有externatl(外部拓展这一项的,或者使用磁盘工具,如果插上了u盘也是可以看到的)然后使用命令 mkdir /Volumes/…...

使用Smart-Doc为Java项目生成gRPC API文档

本文详细介绍了如何在Java微服务项目中利用Smart-Doc工具自动生成gRPC API文档,包括配置步骤、优势分析以及实际操作指南,帮助开发者高效管理API文档。Smart-Doc:在Java项目中生成gRPC API文档 在现代Java微服务中,gRPC通过其高效的二进制协议和多语言支持简化了服务间通信…...

数字时钟用的什么字体

下载字体 字体 DS-Digital放置字体 引入字体:<style scoped> /* 定义字体 */ @font-face {font-family: DS-Digital; /* 自定义字体名称 *//* 引入不同格式的字体文件,确保兼容性 */src: url(@/assets/fonts/DS-DIGI.TTF) format(truetype),url(@/assets/fonts/DS-DIG…...

Python数据分析零基础完整课程大纲(详细版)【202509第1版】 - 指南

Python数据分析零基础完整课程大纲(详细版)【202509第1版】 - 指南pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier Ne…...

详细介绍:uni-app 根据用户不同身份显示不同的tabBar

详细介绍:uni-app 根据用户不同身份显示不同的tabBarpre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", monos…...

VSTO QQ群 61840693 解散通知【新群193203228 】

由于各种原因,成立16年的VSTO交流群于近日停用,损失粉丝两千人。 感谢这么多年热爱我的粉丝,如果还要跟我学习VBA,请加新群193203228...

kettle从入门到精通 第107课 ETL之kettle json_input 一个点号引发的血案

场景:在一个kettle交流群内,有一个小伙伴求助:大致意思是json input的输入参数的key中存在点号,凡是带点号的key都无法正确获取。 今天一起来分析下使用多种方式来解决这个问题,希望后续有人遇到此类问题时可以秒杀它,而不是花费N根头发!!! 1、json数据构造{"id&…...

【2024-2025第二学期】助教工作学期总结

一、助教工作的具体职责和任务: 作为《人工智能导论》课程助教,我的主要职责包括协助课程老师完成教学支持工作,确保课程顺利运行。具体任务包括:前期负责对接课程老师对比赛进行组织,比如数字中国创新大赛的各赛道报名、统计第十六届视觉艺术设计赛省赛的报名、上课后课程…...

Clion 实现多个 main 函数执行互不影响

安装插件 C/C++ single File Execution。如果 Clion 中安装不上,可以在官网安装:安装成功后,源文件右键,会提示:点击后,Clion 的右下角会提示:reload 这个文件夹:选择刚刚 add 的源文件,即想要执行的源文件:在 main.c 和 Hello.c 两个源文件都包含 main() 函数时也可…...

腾讯终于对Claude code下手了?我拿它跑完一个真实项目,结果有点意外…

前几天看腾讯也发布和开源了他们的Claude code,名字是Codebuddy code。 就下载下来试了试效果(说实话,一开始是冲着它能免费用GPT-4o、Claude 3.5这些顶级模型去的)。 整体来看效果还不错,对于刚开始发布来说,我认为已经可以初步当做生产力工具了。 目前国内版本可以使用的…...

快速利用AI读论文

使用Gemini 2.5 Pro,每天可以有五次请求 提示词如下 **Role:** You are a seasoned researcher in the field of artificial intelligence and computer vision. You excel at interpreting cutting-edge academic papers in a clear and structured manner and can disting…...

第一周预习作业(AI)

你好,很高兴认识你。...

HTTP协议核心概念全解析 - 实践

HTTP协议核心概念全解析 - 实践pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", monospace !important; font…...

Django过时了吗?从ASGI到AI时代的思考

前言 本文本来只是 DjangoStarter v3.2.1 新版本发布博客里的一段思考,不过越写越长,干脆拆分成一篇独立的文章得了。😄“Django 过时了吗?” 这是一个几乎每天都能在论坛、Reddit 或知乎上看到的问题。 但仔细想想,这个问题的背后并不是“Django 变烂了”,而是技术趋势…...

日常练习一部分

这一次练习不使用后端,只进行对使用vue3的前端练习,包括两种不同的跳转方式: 我的部分代码大致如下: DashboardView.vue: <template><div><h1>仪表盘视图</h1><p>这是您的个人仪表盘,显示各种统计信息。</p><div class="sta…...

世界史

约200000万年前,天在地的下方,但是地与天无法展示与观测,山与河都一并随着天去了遥远的歌声,日月的光辉敲响了【命运】的洪钟,于此,在钟声中,产生了最初的生命,在日月的抚慰下,生命活了,死了,分裂了,一二三四五,哦,原来【数据删除】在这里,这真是太美妙了。 最初…...

罗技M275鼠标滚轮断轴维修:建模+3D打印修复全过程

本文记录了一次鼠标滚轮损坏的维修过程。经拆解发现,滚轮与编码器连接的中心轴从根部断裂。由于原装配件价格接近鼠标本体价值,作者决定采用 3D 打印方式自制替换件。初步尝试使用开源模型失败后,使用游标卡尺对原件进行尺寸测量,并重新建模。在打印过程中,分别测试了纵向…...

Unity:网络编程

Socket 服务端至少要两个socket:一个负责接收客户端连接请求,但不负责与客户端通信;为每个连接成功的客户端,在服务端创建一个对应的socket负责与客户端通信。 客户端的socket一个就行:要指定连接的服务端的IP和端口。 通讯过程:申请一个socket 绑定IP和端口 监听 服务端…...

【比赛记录】2025CSP-S模拟赛45

A B C D Sum Rank10 - 75 20 105 16/24A. 染色(color) 考虑奇偶性染色,于是就满足了所有奇质数的限制。但是由于有 \(2\) 的存在,所以需要每四个染一个色。考虑 \(1,3,6,8\) 每两个数之差都是质数,因此 \(n\ge8\) 时答案不可能小于 \(4\)。\(n<8\) 时打表打出来即可。Cod…...

PWN手的成长之路-01

首先启动题目环境,并下载题目的附件。远程nc连接一下,发现程序就是把用户输入再次输出,并加了几句话。之后从附件下手,用file查看文件的详细信息。发现是一个linux的可执行程序。使用checksec查看文件的安全属性。P.S.详细解释查看后的信息含义: Arch: 程序架构信息。判断…...

SpringCloud全解:核心组件与实战案例 - 教程

SpringCloud全解:核心组件与实战案例 - 教程pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", monospace !im…...

学起plus刷课

// ==UserScript== // @name 自动下一集-学起刷课(可用版) // @namespace https://cjlzulms.sccchina.net/ // @version 2.0 // @description 用户首次点击播放后,自动连播下一集 // @author You // @match https://cjlzulms.sccchina.net/ve…...