MCP Loom:快速构建AI工具与数据连接器的开发框架

news2026/5/12 3:43:39
1. 项目概述MCP Loom一个连接AI与真实世界的“织布机”如果你最近在折腾AI应用开发特别是想让你的AI助手比如Claude、Cursor等能直接操作你电脑上的文件、数据库甚至调用外部API那么你很可能已经听说过“模型上下文协议”。这个协议正在成为连接AI模型与外部工具和数据的标准桥梁。而今天要聊的“karbassi/mcp-loom”这个项目在我看来就是为这个协议量身打造的一台高效“织布机”。它不是一个最终应用而是一个功能强大、设计精巧的开发框架和运行时专门用于快速构建、测试和运行MCP服务器。简单来说MCP Loom让你能像用织布机编织复杂图案一样轻松地将各种数据源和能力“编织”进AI的上下文里。想象一下你的AI助手不再只是基于训练数据和你输入的提示词来回答而是能实时读取你指定的Notion页面、查询公司内部的数据库、操作本地的文件系统甚至控制智能家居设备。MCP Loom就是实现这一切背后那个稳定、可扩展的引擎。它适合任何想要为AI构建自定义工具链的开发者、希望将内部系统AI化的团队以及热衷于探索AI代理边界的极客们。通过它你可以把想法快速变成可运行的MCP服务极大地降低了进入这个领域的门槛。2. 核心架构与设计哲学为什么是“Loom”2.1 MCP协议的精髓与Loom的定位要理解Loom的价值首先得搞懂MCP协议在解决什么问题。传统的AI应用调用外部能力往往需要为每个模型、每个工具编写特定的适配器代码耦合度高复用性差。MCP协议的出现旨在定义一个标准化的方式让AI模型客户端能够发现、描述并调用外部服务器提供的工具Tools和资源Resources。这就像给AI世界制定了USB协议各种“外设”数据源、执行器只要符合这个协议就能即插即用。而karbassi开发的MCP Loom正是这个协议生态中的一个关键基础设施。它的名字“Loom”织布机非常形象。在纺织中织布机负责将经线固定的框架和纬线变化的图案交织成布。在MCP Loom中“经线”是MCP协议的核心规范、通信机制和运行时管理它提供了稳定、可靠的基础框架“纬线”则是开发者定义的各种工具函数、数据查询逻辑和资源处理器。Loom的职责就是优雅地将你的业务逻辑纬线编织进标准的MCP协议框架经线中产出一件符合标准、可直接被AI客户端使用的“成品”——一个功能完整的MCP服务器。2.2 框架的核心设计优势与从零开始实现一个MCP服务器相比使用Loom带来了几个显著优势1. 协议细节的抽象MCP通信基于JSON-RPC over STDIO或SSE需要处理连接、会话、请求分发、错误处理等一系列繁琐但必要的工作。Loom帮你封装了所有这些底层通信的复杂性。作为开发者你只需要关注最核心的业务逻辑定义工具Tool能做什么以及资源Resource如何被获取。2. 开发体验的优化Loom提供了热重载、结构化日志、内置测试工具等开发特性。这意味着你在修改了工具的实现代码后无需重启整个服务器AI客户端就能立刻看到变化并调用新逻辑。这对于快速迭代和调试至关重要。3. 标准化与可移植性基于Loom构建的服务器天然符合MCP协议标准。这意味着你今天为Claude Desktop开发的服务器明天很可能无需修改就能用在Cursor或其他任何支持MCP的AI工作台上。这种可移植性保护了你的开发投资。4. 生态集成潜力作为一个活跃的开源框架Loom更容易吸引社区贡献共享的组件或适配器。例如未来可能会出现针对PostgreSQL、Slack、GitHub等常见服务的“Loom插件模块”进一步加速开发。注意选择使用框架而非裸写协议本质上是在用一定的灵活性换取开发效率和维护性。对于绝大多数MCP服务器场景Loom提供的“约束”正是你需要的“最佳实践”引导避免你陷入协议实现的细节泥潭。3. 快速上手构建你的第一个MCP服务器3.1 环境准备与项目初始化假设我们想构建一个服务器让AI能查询指定城市的实时天气。我们将其命名为weather-mcp-server。首先确保你的开发环境已安装Node.js建议18.x或更高版本和npm。然后我们可以利用Loom提供的模板或从零初始化一个项目。这里演示从零开始的清晰步骤# 1. 创建项目目录并进入 mkdir weather-mcp-server cd weather-mcp-server # 2. 初始化npm项目按照提示填写信息或一路回车使用默认值 npm init -y # 3. 安装MCP Loom核心依赖 npm install modelcontextprotocol/sdk loom # 4. 安装可能的辅助依赖例如用于HTTP请求的axios npm install axios接下来创建项目的入口文件例如index.js// index.js const { Server } require(modelcontextprotocol/sdk); const { Loom } require(loom); const axios require(axios); // 初始化MCP服务器 const server new Server( { name: weather-mcp-server, version: 0.1.0, }, { capabilities: { tools: {}, // 工具列表将在后面填充 resources: {}, // 资源列表将在后面填充 }, } ); // 创建Loom实例并将MCP服务器挂载上去 const loom new Loom(server); // 在这里定义工具和资源后续步骤展开 // ... // 启动织布机开始监听和处理请求 loom.start().catch((error) { console.error(Failed to start server:, error); process.exit(1); });这个骨架代码创建了一个最基本的MCP服务器外壳并通过Loom启动它。但目前它还没有任何实际功能。3.2 定义你的第一个工具Tool在MCP中“工具”是AI可以主动调用的函数。我们来定义一个get_weather工具。在index.js中在loom.start()之前添加工具定义// 定义 get_weather 工具 server.setRequestHandler(tools/list, async () { return { tools: [ { name: get_weather, description: 获取指定城市的当前天气情况。, inputSchema: { type: object, properties: { city: { type: string, description: 城市名称例如Beijing, Shanghai, New York, }, unit: { type: string, enum: [celsius, fahrenheit], description: 温度单位默认为摄氏度celsius, default: celsius, }, }, required: [city], }, }, ], }; }); // 处理工具的调用请求 server.setRequestHandler(tools/call, async (request) { const { name, arguments: args } request.params; if (name get_weather) { const { city, unit celsius } args; // 这里是模拟逻辑实际应调用天气API // 例如使用 axios.get(https://api.weatherapi.com/v1/current.json?keyYOUR_KEYq${city}) console.log(查询城市${city}, 单位${unit}); // 模拟API返回 const mockTemperature unit celsius ? 22°C : 72°F; const mockCondition 晴朗; return { content: [ { type: text, text: 城市 ${city} 的当前天气为${mockCondition}温度 ${mockTemperature}。, }, ], }; } throw new Error(未知的工具${name}); });关键点解析tools/list处理器当AI客户端查询服务器有哪些工具时返回此列表。每个工具都需要清晰的name、description和inputSchema。inputSchema使用JSON Schema定义输入参数这至关重要因为它指导AI如何正确地调用这个工具。tools/call处理器当AI客户端调用具体工具时触发。你需要根据request.params.name判断是哪个工具然后从request.params.arguments中获取参数执行你的业务逻辑最后返回结构化的content。模拟与真实API示例中使用了模拟数据。在实际项目中你会在这里集成真实的第三方天气API如OpenWeatherMap, WeatherAPI等并妥善处理API密钥、错误和网络超时。3.3 定义资源Resource及其模板“资源”是AI可以读取的静态或动态数据URI。例如你可以定义一个资源模板让AI通过weather://beijing这样的URI来获取北京天气。在index.js中继续添加// 定义资源模板 server.setRequestHandler(resources/list, async () { return { resources: [ { uri: weather://{city}, name: 城市天气资源, description: 通过URI格式 weather://{city} 访问指定城市的天气。, mimeType: text/plain, }, ], }; }); // 处理读取资源的请求 server.setRequestHandler(resources/read, async (request) { const url new URL(request.params.uri); if (url.protocol ! weather:) { throw new Error(不支持的资源协议${url.protocol}); } const city url.hostname; // URI格式为 weather://beijing, hostname就是‘beijing’ // 同样这里模拟数据获取 const mockInfo 城市 ${city} 的天气简报模拟数据 - 晴朗22°C。; return { contents: [ { uri: request.params.uri, mimeType: text/plain, text: mockInfo, }, ], }; });资源与工具的区别工具Tool是“动词”是AI主动发起的一个操作可以有复杂的输入参数和逻辑。资源Resource是“名词”是一个可以通过URI寻址的数据端点AI可以“读取”它。资源更适合暴露那些通过简单查询就能获取的数据。在上面的例子中AI既可以通过调用get_weather工具并传入参数来获取天气也可以通过直接“读取”weather://beijing这个资源来获得。这为AI客户端提供了更灵活的数据交互方式。3.4 运行与测试现在一个最简单的MCP服务器就完成了。你可以用以下命令启动它node index.js服务器启动后会在标准输入输出上监听。要测试它你需要一个MCP客户端。最方便的方式是使用Claude Desktop应用。打开Claude Desktop的设置。找到“开发者设置”或“MCP服务器”配置部分。添加一个新的服务器配置类型选择“stdio”并填入你的启动命令例如node /path/to/your/weather-mcp-server/index.js。保存并重启Claude Desktop。重启后在Claude的对话窗口中你可以尝试说“请使用get_weather工具查询一下北京的天气。” 或者 “读取一下 weather://shanghai 这个资源。” Claude应该能识别出你服务器提供的工具和资源并进行调用或读取。实操心得在开发初期除了依赖客户端测试强烈建议在服务器代码中添加详细的日志。Loom本身会输出一些日志但你可以在工具和资源处理器中手动添加console.log来观察请求和响应的具体数据格式这对于调试协议交互是否正确非常有帮助。4. 深入核心高级特性与最佳实践4.1 工具与资源的进阶设计模式一个实用的MCP服务器往往不止一两个简单的端点。随着功能增多代码组织变得重要。1. 模块化组织不要把所有工具和资源的处理器都堆在index.js里。建议按功能模块拆分src/ ├── index.js # 入口初始化服务器和Loom ├── tools/ │ ├── weather.js # 天气相关工具 │ ├── filesystem.js # 文件系统工具 │ └── index.js # 聚合所有工具定义 └── resources/ ├── weather.js # 天气相关资源 └── index.js # 聚合所有资源定义在每个工具模块中导出工具的定义列表和对应的处理函数。在入口文件统一注册。2. 工具输入的精细化设计inputSchema是AI理解工具用法的关键。充分利用JSON Schema的特性枚举enum对于有限的选项如单位、类型。模式pattern用正则表达式验证输入格式如邮箱、日期。默认值default为可选参数提供合理的默认值。复杂嵌套结构如果工具需要复杂对象作为输入可以定义object类型的属性并详细描述其内部结构。这能极大提升AI调用工具的准确率。3. 资源的动态发现resources/list不仅可以返回静态模板还可以根据上下文返回动态列表。例如一个文件系统MCP服务器可以在收到列表请求时扫描某个目录返回该目录下所有文件对应的资源URI。这通过实现resources/list处理器为动态逻辑即可实现。4.2 错误处理与健壮性生产级的服务器必须优雅地处理各种错误。1. 参数验证即使在inputSchema中定义了约束服务器端也应再次验证。使用如joi或zod库进行强验证。// 在 tools/call 处理器中 if (name get_weather) { const { city, unit } args; if (!city || typeof city ! string) { throw new Error(参数 city 必须为非空字符串); } if (unit ![celsius, fahrenheit].includes(unit)) { throw new Error(参数 unit 必须是 celsius 或 fahrenheit); } // ... 业务逻辑 }2. 外部API调用容错调用第三方服务必须考虑超时、网络异常、API限流等情况。const axios require(axios); const TIMEOUT 10000; // 10秒超时 async function fetchWeatherFromAPI(city) { try { const response await axios.get(https://api.weatherapi.com/v1/current.json, { params: { key: process.env.WEATHER_API_KEY, q: city }, timeout: TIMEOUT, }); return response.data; } catch (error) { if (error.code ECONNABORTED) { throw new Error(天气API请求超时${TIMEOUT}ms); } else if (error.response) { // API返回了错误状态码 throw new Error(天气API错误${error.response.status} - ${error.response.data?.error?.message || Unknown}); } else { // 网络错误或其他问题 throw new Error(无法连接到天气服务${error.message}); } } }3. 向AI返回友好的错误信息抛出的错误信息应当清晰、可读因为AI客户端可能会直接将错误信息呈现给最终用户。避免泄露内部堆栈或敏感信息。4.3 状态管理与安全性MCP服务器默认是无状态的每个请求独立。但某些场景可能需要状态如用户认证、临时会话。1. 基础认证如果服务器需要API密钥可以通过环境变量传入并在服务器启动时验证。切勿将密钥硬编码在代码中。# 启动时传入 WEATHER_API_KEYyour_real_key_here node index.js// 在代码中读取 const apiKey process.env.WEATHER_API_KEY; if (!apiKey) { console.error(错误未设置 WEATHER_API_KEY 环境变量。); process.exit(1); }2. 会话与上下文MCP协议本身不直接管理会话状态。如果你需要维护状态例如一个多步操作通常需要在工具调用间通过某种标识符如客户端提供的sessionId或由服务器生成并让AI在后续调用中传回来关联。状态可以存储在内存对于简单场景或外部存储如Redis中。需要注意的是设计有状态的MCP工具会增加复杂性需谨慎评估是否必要。5. 实战构建一个文件系统浏览器MCP服务器让我们用一个更复杂的例子巩固所学构建一个服务器让AI能列出目录、读取文件内容。5.1 项目结构与核心工具定义项目结构如下file-mcp-server/ ├── package.json ├── src/ │ ├── index.js │ ├── tools/ │ │ ├── listFiles.js │ │ ├── readFile.js │ │ └── index.js │ └── resources/ │ └── fileResource.js └── .env.example1. 工具listFiles// src/tools/listFiles.js const fs require(fs).promises; const path require(path); const toolDefinition { name: list_files, description: 列出指定目录下的文件和子目录。, inputSchema: { type: object, properties: { dirPath: { type: string, description: 要列出的目录的绝对路径。, }, }, required: [dirPath], }, }; async function handleListFiles(args) { const { dirPath } args; // 安全检查防止目录遍历攻击 const resolvedPath path.resolve(dirPath); // 这里可以添加更严格的路径白名单检查 if (!resolvedPath.startsWith(process.cwd())) { throw new Error(出于安全考虑只能访问当前工作目录及其子目录。); } try { const items await fs.readdir(resolvedPath, { withFileTypes: true }); const list items.map(dirent ({ name: dirent.name, type: dirent.isDirectory() ? directory : file, path: path.join(resolvedPath, dirent.name), })); return { content: [{ type: text, text: 目录 ${dirPath} 下的内容\n list.map(item - [${item.type}] ${item.name}).join(\n), }], }; } catch (error) { if (error.code ENOENT) { throw new Error(目录不存在${dirPath}); } throw new Error(无法读取目录${error.message}); } } module.exports { toolDefinition, handler: handleListFiles };2. 工具readFile// src/tools/readFile.js const fs require(fs).promises; const path require(path); const toolDefinition { name: read_file, description: 读取指定文件的内容。, inputSchema: { type: object, properties: { filePath: { type: string, description: 要读取的文件的绝对路径。, }, encoding: { type: string, description: 文件编码默认为 utf-8。, default: utf-8, }, }, required: [filePath], }, }; async function handleReadFile(args) { const { filePath, encoding utf-8 } args; const resolvedPath path.resolve(filePath); // 安全检查 if (!resolvedPath.startsWith(process.cwd())) { throw new Error(出于安全考虑只能访问当前工作目录及其子目录下的文件。); } // 可选检查文件类型避免读取二进制大文件 const stats await fs.stat(resolvedPath).catch(() null); if (!stats) throw new Error(文件不存在${filePath}); if (!stats.isFile()) throw new Error(路径不是一个文件${filePath}); if (stats.size 1024 * 1024) { // 限制1MB throw new Error(文件过大出于性能考虑暂不支持读取超过1MB的文件。); } try { const content await fs.readFile(resolvedPath, encoding); return { content: [{ type: text, text: 文件 ${filePath} 的内容\n\\\\n${content}\n\\\, }], }; } catch (error) { throw new Error(读取文件失败${error.message}); } } module.exports { toolDefinition, handler: handleReadFile };5.2 聚合工具与资源注册在src/tools/index.js中聚合所有工具const listFiles require(./listFiles); const readFile require(./readFile); const tools [ listFiles.toolDefinition, readFile.toolDefinition, ]; const toolHandlers { [listFiles.toolDefinition.name]: listFiles.handler, [readFile.toolDefinition.name]: readFile.handler, }; module.exports { tools, toolHandlers };在src/index.js中集成const { Server } require(modelcontextprotocol/sdk); const { Loom } require(loom); const { tools, toolHandlers } require(./tools); const { resourceTemplates, readResource } require(./resources/fileResource); const server new Server( { name: file-mcp-server, version: 0.1.0, }, { capabilities: { tools: {}, resources: {}, }, } ); // 注册工具列表 server.setRequestHandler(tools/list, async () ({ tools, })); // 注册工具调用处理器 server.setRequestHandler(tools/call, async (request) { const { name, arguments: args } request.params; const handler toolHandlers[name]; if (!handler) { throw new Error(未知的工具${name}); } return await handler(args); }); // 注册资源列表这里使用文件资源模板 server.setRequestHandler(resources/list, async () ({ resources: resourceTemplates, })); // 注册资源读取处理器 server.setRequestHandler(resources/read, async (request) { return await readResource(request.params.uri); }); const loom new Loom(server); loom.start().catch((error) { console.error(服务器启动失败:, error); process.exit(1); });5.3 安全与权限考量文件系统操作极其敏感必须实施严格的安全策略路径限制沙箱如上例所示通过path.resolve和startsWith将可访问范围限制在项目工作目录内。更严格的方案是配置一个明确的根目录白名单。输入验证防止路径遍历攻击如../../../etc/passwd。path.resolve可以解析掉..但结合白名单检查更安全。资源消耗控制对读取的文件大小进行限制防止服务器因读取超大文件而内存溢出。操作审计日志记录所有工具调用用户、工具名、参数、时间便于事后审计和故障排查。这可以在tools/call处理器的最外层添加。6. 调试、部署与生态集成6.1 开发调试技巧1. 使用Loom的调试模式Loom通常会有更详细的日志输出选项查阅其文档开启调试日志能帮助你理解MCP协议交互的每一个步骤。2. 独立测试脚本编写一个简单的测试脚本模拟MCP客户端向你的服务器发送请求。这可以帮助你在不依赖Claude Desktop的情况下验证核心逻辑。// test-server.js const { spawn } require(child_process); const serverProcess spawn(node, [src/index.js], { stdio: [pipe, pipe, inherit] }); // 向 stdin 写入一个模拟的 MCP “列出工具” 请求 const listToolsRequest { jsonrpc: 2.0, id: 1, method: tools/list, params: {} }; serverProcess.stdin.write(JSON.stringify(listToolsRequest) \n); // 从 stdout 读取响应 serverProcess.stdout.on(data, (data) { console.log(服务器响应:, data.toString()); }); serverProcess.on(close, (code) { console.log(子进程退出退出码 ${code}); });3. 利用MCP Inspector工具社区有一些工具如mcp-inspector可以充当MCP客户端并提供图形化界面来查看服务器提供的工具和资源并手动触发调用是强大的调试助手。6.2 部署与运行MCP服务器通常作为常驻进程运行。1. 进程管理在生产环境使用像PM2、systemd或Docker这样的进程管理器来确保服务器崩溃后能自动重启。# 使用PM2的例子 npm install -g pm2 pm2 start src/index.js --name file-mcp-server pm2 save pm2 startup # 设置开机自启2. 环境配置将所有配置API密钥、根目录路径、端口等通过环境变量或配置文件管理切勿写入代码。3. 性能监控为你的服务器添加健康检查端点虽然MCP协议本身没有规定但你可以额外开一个简单的HTTP服务并集成到你的监控系统中。6.3 融入MCP生态构建好服务器后你可以通过以下方式扩大其影响发布到MCP服务器注册表随着MCP生态发展可能会出现官方的或社区的服务器注册表。将你的服务器提交上去让更多用户发现和使用。编写清晰的文档在项目README中详细说明服务器的功能、安装方式、配置方法、工具和资源的详细说明。好的文档能极大降低用户的使用门槛。考虑开发客户端配置包对于复杂的服务器你可以创建一个简单的安装脚本或配置文件包用户一键即可将其添加到Claude Desktop等客户端中提升用户体验。构建MCP服务器的过程是一个将特定领域能力封装成AI可理解、可操作的标准化接口的过程。karbassi/mcp-loom这个框架通过处理大量底层样板代码让你能专注于创造价值本身。从简单的天气查询到复杂的文件系统操作其核心模式都是一致的定义清晰的工具和资源实现稳健的业务逻辑并处理好安全与错误。随着AI助手日益普及能够熟练地为其“制造工具”的开发者无疑将在人机协作的新范式下占据先机。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2605195.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SpringBoot-17-MyBatis动态SQL标签之常用标签

文章目录 1 代码1.1 实体User.java1.2 接口UserMapper.java1.3 映射UserMapper.xml1.3.1 标签if1.3.2 标签if和where1.3.3 标签choose和when和otherwise1.4 UserController.java2 常用动态SQL标签2.1 标签set2.1.1 UserMapper.java2.1.2 UserMapper.xml2.1.3 UserController.ja…

wordpress后台更新后 前端没变化的解决方法

使用siteground主机的wordpress网站,会出现更新了网站内容和修改了php模板文件、js文件、css文件、图片文件后,网站没有变化的情况。 不熟悉siteground主机的新手,遇到这个问题,就很抓狂,明明是哪都没操作错误&#x…

网络编程(Modbus进阶)

思维导图 Modbus RTU(先学一点理论) 概念 Modbus RTU 是工业自动化领域 最广泛应用的串行通信协议,由 Modicon 公司(现施耐德电气)于 1979 年推出。它以 高效率、强健性、易实现的特点成为工业控制系统的通信标准。 包…

UE5 学习系列(二)用户操作界面及介绍

这篇博客是 UE5 学习系列博客的第二篇,在第一篇的基础上展开这篇内容。博客参考的 B 站视频资料和第一篇的链接如下: 【Note】:如果你已经完成安装等操作,可以只执行第一篇博客中 2. 新建一个空白游戏项目 章节操作,重…

IDEA运行Tomcat出现乱码问题解决汇总

最近正值期末周,有很多同学在写期末Java web作业时,运行tomcat出现乱码问题,经过多次解决与研究,我做了如下整理: 原因: IDEA本身编码与tomcat的编码与Windows编码不同导致,Windows 系统控制台…

利用最小二乘法找圆心和半径

#include <iostream> #include <vector> #include <cmath> #include <Eigen/Dense> // 需安装Eigen库用于矩阵运算 // 定义点结构 struct Point { double x, y; Point(double x_, double y_) : x(x_), y(y_) {} }; // 最小二乘法求圆心和半径 …

使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式

一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明&#xff1a;假设每台服务器已…

XML Group端口详解

在XML数据映射过程中&#xff0c;经常需要对数据进行分组聚合操作。例如&#xff0c;当处理包含多个物料明细的XML文件时&#xff0c;可能需要将相同物料号的明细归为一组&#xff0c;或对相同物料号的数量进行求和计算。传统实现方式通常需要编写脚本代码&#xff0c;增加了开…

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器的上位机配置操作说明

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器专为工业环境精心打造&#xff0c;完美适配AGV和无人叉车。同时&#xff0c;集成以太网与语音合成技术&#xff0c;为各类高级系统&#xff08;如MES、调度系统、库位管理、立库等&#xff09;提供高效便捷的语音交互体验。 L…

(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)

题目&#xff1a;3442. 奇偶频次间的最大差值 I 思路 &#xff1a;哈希&#xff0c;时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况&#xff0c;哈希表这里用数组即可实现。 C版本&#xff1a; class Solution { public:int maxDifference(string s) {int a[26]…

【大模型RAG】拍照搜题技术架构速览:三层管道、两级检索、兜底大模型

摘要 拍照搜题系统采用“三层管道&#xff08;多模态 OCR → 语义检索 → 答案渲染&#xff09;、两级检索&#xff08;倒排 BM25 向量 HNSW&#xff09;并以大语言模型兜底”的整体框架&#xff1a; 多模态 OCR 层 将题目图片经过超分、去噪、倾斜校正后&#xff0c;分别用…

【Axure高保真原型】引导弹窗

今天和大家中分享引导弹窗的原型模板&#xff0c;载入页面后&#xff0c;会显示引导弹窗&#xff0c;适用于引导用户使用页面&#xff0c;点击完成后&#xff0c;会显示下一个引导弹窗&#xff0c;直至最后一个引导弹窗完成后进入首页。具体效果可以点击下方视频观看或打开下方…

接口测试中缓存处理策略

在接口测试中&#xff0c;缓存处理策略是一个关键环节&#xff0c;直接影响测试结果的准确性和可靠性。合理的缓存处理策略能够确保测试环境的一致性&#xff0c;避免因缓存数据导致的测试偏差。以下是接口测试中常见的缓存处理策略及其详细说明&#xff1a; 一、缓存处理的核…

龙虎榜——20250610

上证指数放量收阴线&#xff0c;个股多数下跌&#xff0c;盘中受消息影响大幅波动。 深证指数放量收阴线形成顶分型&#xff0c;指数短线有调整的需求&#xff0c;大概需要一两天。 2025年6月10日龙虎榜行业方向分析 1. 金融科技 代表标的&#xff1a;御银股份、雄帝科技 驱动…

观成科技:隐蔽隧道工具Ligolo-ng加密流量分析

1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具&#xff0c;该工具基于TUN接口实现其功能&#xff0c;利用反向TCP/TLS连接建立一条隐蔽的通信信道&#xff0c;支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式&#xff0c;适应复杂网…

铭豹扩展坞 USB转网口 突然无法识别解决方法

当 USB 转网口扩展坞在一台笔记本上无法识别,但在其他电脑上正常工作时,问题通常出在笔记本自身或其与扩展坞的兼容性上。以下是系统化的定位思路和排查步骤,帮助你快速找到故障原因: 背景: 一个M-pard(铭豹)扩展坞的网卡突然无法识别了,扩展出来的三个USB接口正常。…

未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?

编辑&#xff1a;陈萍萍的公主一点人工一点智能 未来机器人的大脑&#xff1a;如何用神经网络模拟器实现更智能的决策&#xff1f;RWM通过双自回归机制有效解决了复合误差、部分可观测性和随机动力学等关键挑战&#xff0c;在不依赖领域特定归纳偏见的条件下实现了卓越的预测准…

Linux应用开发之网络套接字编程(实例篇)

服务端与客户端单连接 服务端代码 #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> #include <pthread.h> …

华为云AI开发平台ModelArts

华为云ModelArts&#xff1a;重塑AI开发流程的“智能引擎”与“创新加速器”&#xff01; 在人工智能浪潮席卷全球的2025年&#xff0c;企业拥抱AI的意愿空前高涨&#xff0c;但技术门槛高、流程复杂、资源投入巨大的现实&#xff0c;却让许多创新构想止步于实验室。数据科学家…

深度学习在微纳光子学中的应用

深度学习在微纳光子学中的主要应用方向 深度学习与微纳光子学的结合主要集中在以下几个方向&#xff1a; 逆向设计 通过神经网络快速预测微纳结构的光学响应&#xff0c;替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…