基于Alexa技能与无服务器架构的香港地铁实时查询系统开发实战

news2026/5/10 3:37:02
1. 项目概述与核心价值最近在折腾智能音箱的技能开发发现一个挺有意思的开源项目tomfong/hk-mtr-next-train-skill。这是一个为香港地铁MTR乘客量身定做的语音技能让你动动嘴皮子就能问出下一班车什么时候来。听起来是不是挺方便的对于每天穿梭在港岛、荃湾、东涌线之间的通勤族来说能省下掏出手机、打开App、输入站点的时间尤其是在早高峰人挤人的时候或者手里提着东西不方便操作时这个技能的价值就凸显出来了。这个项目本质上是一个语音交互应用的后端服务。它不只是一个简单的API调用封装而是一个完整的、符合语音平台规范比如亚马逊Alexa技能的解决方案。开发者tomfong将查询香港地铁下一班车次这个特定需求封装成了一个标准的、可被语音助手调用的“技能”。当你对智能音箱说“Alexa问港铁下一班车”时你的语音请求会经过Alexa平台的处理最终转发到这个项目部署的服务上。服务会解析你的意图比如你想查询从“金钟”到“中环”的列车然后去抓取香港地铁的实时数据处理好之后再以语音的形式回答你“下一班开往中环的列车将在2分钟后到达。”我之所以觉得这个项目值得深挖不仅仅是因为它解决了某个具体场景的痛点更因为它是一个非常典型的“场景化API服务语音交互”的实战案例。它涉及了现代应用开发的几个关键环节第三方数据接口的调用与解析、无服务器架构Serverless的实践、语音交互协议的处理、以及针对特定地区服务的本地化开发。无论你是想学习语音技能开发还是想了解如何将公共服务数据包装成更便捷的接口这个项目都能提供一套完整的、可复现的代码范本。2. 项目架构与核心技术栈拆解2.1 整体技术架构设计这个项目采用了典型的无服务器函数即服务FaaS架构这是目前开发语音技能最主流、最经济高效的方式。整个技能的生命周期由以下几个核心部分组成语音交互界面VUI定义在亚马逊Alexa开发者控制台。这里配置了技能的唤醒词如“港铁下一班车”、意图NextTrainIntent、以及对话中可能需要的槽位Slots例如“起点站”fromStation和“终点站”toStation。这部分定义了用户“可以说什么”以及技能“能听懂什么”。业务逻辑后端Lambda函数这是本项目的核心代码部署在AWS Lambda上。当Alexa平台识别到用户的意图后会将一个结构化的请求JSON格式发送到这个Lambda函数。函数内部负责意图分发根据请求中的intent.name判断用户想做什么查询下一班车。参数提取与验证从槽位中提取用户说的车站名并验证其有效性比如用户说的“金钟”是否对应MTR内部的站点代码ADM。业务逻辑执行调用香港地铁的实时数据API获取班次信息。响应构建将获取到的数据如“2分钟”组织成符合Alexa响应格式SSML语音合成标记语言或简单文本的JSON返回给Alexa平台最终由音箱播报出来。第三方数据源MTR实时数据API项目的“数据心脏”。它需要从香港地铁的官方或第三方提供的实时接口中获取列车时刻数据。这部分通常是整个项目中最不稳定的一环因为接口可能会变更、需要处理网络异常、数据格式可能调整。这种架构的优势非常明显开发者几乎无需关心服务器的运维、扩缩容和网络配置只需要专注于业务逻辑代码。AWS Lambda会根据请求量自动伸缩按实际计算资源消耗计费在技能访问量不高的情况下成本可以忽略不计。2.2 核心依赖与技术选型打开项目的package.json文件我们可以看到其技术栈的选择这反映了开发者的技术偏好和项目需求运行时环境Node.js。这是Alexa技能开发最主流的环境生态成熟有完善的Alexa SDK支持异步非阻塞的特性非常适合处理高并发的语音请求。核心框架ask-sdk-core(Alexa Skills Kit SDK)。这是亚马逊官方提供的SDK它封装了与Alexa平台交互的复杂细节提供了清晰的请求处理程序Request Handlers和响应构建器Response Builders模式让开发者可以像写普通HTTP路由一样编写语音交互逻辑。辅助工具库axios一个基于Promise的HTTP客户端用于向MTR的API发送请求。相比原生的http模块axios提供了更简洁的API、自动的JSON转换和更好的错误处理是调用外部服务的首选。i18next国际化框架。虽然项目主要服务于粤语/英语用户但使用i18next可以方便地管理不同语言的提示语为技能未来的多语言扩展打下基础。例如错误信息“车站未找到”可以分别用中文和英文定义。moment-timezone时间处理库。香港使用特定时区Asia/Hong_Kong所有时间的解析、格式化和计算都必须基于此时区否则会出现时间偏差。moment-timezone是处理此类问题的标准工具。注意技术选型看似简单但背后有深意。例如为什么不用更轻量的node-fetch而用axios因为在语音技能场景下网络请求的稳定性和详细的错误信息至关重要。axios内置的请求/响应拦截器、超时配置、自动重试需自行封装等特性能帮助开发者更好地构建健壮的服务。2.3 数据流与交互协议解析理解数据如何在用户、Alexa平台和你的Lambda函数之间流动是调试技能的关键。下图描绘了完整的交互链条用户说“Alexa问港铁从金钟到中环下一班车什么时候来” ↓ Alexa设备录音并上传至云端 ↓ Alexa自然语言理解NLU服务 ↓ 解析出意图NextTrainIntent槽位fromStation金钟, toStation中环 ↓ Alexa平台构造一个 LaunchRequest 或 IntentRequest JSON 对象通过HTTPS POST发送到你的Lambda函数URL ↓ 你的Lambda函数被触发收到如下格式的请求体 { version: 1.0, session: { ... }, context: { ... }, request: { type: IntentRequest, requestId: ..., timestamp: ..., locale: zh-HK, // 关键标识语言地区 intent: { name: NextTrainIntent, confirmationStatus: NONE, slots: { fromStation: { name: fromStation, value: 金鐘, // 注意这里是NLU识别后的原始值 resolutions: { ... }, // 可能包含实体解析结果 confirmationStatus: NONE }, toStation: { ... } } } } } ↓ Lambda函数代码执行 1. 从 event.request.intent.slots 提取槽位值。 2. 将中文站名“金鐘”映射为内部代码“ADM”。 3. 使用 axios 向 MTR API 发送请求携带 fromADMtoCHW。 4. 解析API返回的JSON得到下一班车时间如120秒后。 5. 构建SSML响应speak下一班開往中環的列車將在2分鐘後到達。/speak ↓ Lambda函数返回如下格式的响应给Alexa平台 { version: 1.0, sessionAttributes: {}, response: { outputSpeech: { type: SSML, ssml: speak下一班開往中環的列車將在2分鐘後到達。/speak }, card: { ... }, // 可选在Alexa App中显示图文信息 shouldEndSession: true } } ↓ Alexa平台将SSML转换为语音通过音箱播放给用户。这个流程中最需要你关注的环节是槽位值的映射和第三方API的调用与容错。Alexa NLU识别出的站名是文本而MTR API通常需要站点代码。因此项目中必须维护一个站名到代码的映射表。这个映射表的设计需要考虑同义词如“金钟”和“金鐘”、常见口误以及不同线路的相同站名如“旺角”在东铁线和荃湾线代码不同等问题。3. 核心功能实现与代码深度解析3.1 意图处理器Intent Handler的构建在ask-sdk中每个意图都由一个RequestHandler来处理。我们来看一个简化的NextTrainIntent处理器实现框架const NextTrainIntentHandler { canHandle(handlerInput) { // 判断这个处理器是否能处理当前请求 return handlerInput.requestEnvelope.request.type IntentRequest handlerInput.requestEnvelope.request.intent.name NextTrainIntent; }, async handle(handlerInput) { // 核心处理逻辑 const { request } handlerInput.requestEnvelope; const slots request.intent.slots; // 1. 提取并验证槽位 const fromStationSlot slots.fromStation; const toStationSlot slots.toStation; if (!fromStationSlot || !fromStationSlot.value) { // 处理用户未提供起点站的情况通过对话“追问” const speechText 請問你想從哪個車站出發; return handlerInput.responseBuilder .speak(speechText) .reprompt(speechText) // 等待用户回复 .getResponse(); } // 2. 槽位值标准化映射到内部代码 const fromStationCode stationNameToCode(fromStationSlot.value); const toStationCode stationNameToCode(toStationSlot.value); if (!fromStationCode) { return handlerInput.responseBuilder .speak(抱歉我找不到名稱為「${fromStationSlot.value}」的車站請再說一次。) .getResponse(); } // 3. 调用外部API获取数据 let trainData; try { trainData await fetchMTRNextTrain(fromStationCode, toStationCode); } catch (error) { console.error(调用MTR API失败:, error); // 根据错误类型返回不同的友好提示 if (error.code NETWORK_ERROR) { return handlerInput.responseBuilder .speak(目前無法連接到港鐵服務請稍後再試。) .getResponse(); } else if (error.code API_ERROR) { return handlerInput.responseBuilder .speak(港鐵服務暫時無法提供班次信息。) .getResponse(); } // 未知错误 return handlerInput.responseBuilder .speak(查詢過程中出現了一些問題請再試一次。) .getResponse(); } // 4. 处理API返回的数据并构建语音响应 if (!trainData || trainData.length 0) { return handlerInput.responseBuilder .speak(目前沒有從${fromStationSlot.value}開往${toStationSlot.value}的列車班次信息。) .getResponse(); } const nextTrain trainData[0]; // 假设第一个就是下一班 const waitingTime Math.ceil(nextTrain.time / 60); // 将秒转换为分钟 let speechText; if (waitingTime 1) { speechText 下一班開往${toStationSlot.value}的列車即將到達。; } else { speechText 下一班開往${toStationSlot.value}的列車將在約${waitingTime}分鐘後到達。; } // 5. 使用SSML增强语音表现力 const ssml speak${speechText}/speak; return handlerInput.responseBuilder .speak(ssml) .withSimpleCard(港鐵下一班車, ${fromStationSlot.value} - ${toStationSlot.value}: ${waitingTime}分鐘) // 在App中显示卡片 .getResponse(); }, };关键点解析canHandle方法这是一个过滤器确保每个请求只被正确的处理器处理。这对于拥有多个意图的技能至关重要。槽位验证与对话修复代码中检查了槽位是否存在。如果用户只说“下一班车”Alexa可能无法填充槽位这时技能应该主动追问引导用户完成对话。这是构建流畅语音体验的核心。错误处理的粒度对外部API的调用必须包裹在try-catch中。并且错误处理不应只是笼统地报错而应区分网络错误、API服务错误、业务数据错误等并给出有针对性的、友好的语音提示。SSML的使用虽然这里示例简单但SSML可以控制语音的停顿break time500ms/、语速、音调甚至播放简短音效能让技能的反馈听起来更自然。3.2 站名映射与数据标准化策略stationNameToCode函数是这个项目的数据桥梁。香港地铁站名有英文、繁体中文口语中还有简称如“铜锣湾”可能被说成“铜锣湾站”或“CWB”。一个健壮的映射策略至关重要。// 一个增强版的站名映射表示例 const stationMap { // 中文全名繁体 金鐘: ADM, 金钟: ADM, // 简体兼容 中環: CHW, 中环: CHW, 銅鑼灣: CAB, 铜锣湾: CAB, // 英文名 Admiralty: ADM, Central: CHW, Causeway Bay: CAB, // 常见口语/简称 金鐘站: ADM, Central Station: CHW, CWB: CAB, }; // 模糊匹配函数 function stationNameToCode(stationName) { if (!stationName) return null; const normalizedName stationName.trim().toLowerCase(); // 1. 精确匹配 if (stationMap[normalizedName]) { return stationMap[normalizedName]; } // 2. 遍历映射表进行模糊匹配例如包含关系 for (const [key, code] of Object.entries(stationMap)) { if (normalizedName.includes(key.toLowerCase()) || key.toLowerCase().includes(normalizedName)) { console.log(模糊匹配: ${stationName} - ${key} - ${code}); return code; } } // 3. 可以集成更高级的字符串相似度算法如Levenshtein Distance // 对于识别置信度低的槽位值特别有用 return null; // 未找到匹配 }实操心得在实际开发中仅仅依靠静态映射表是不够的。Alexa的NLU本身支持“实体解析”Entity Resolution你可以在技能控制台定义Station类型并上传一个包含所有站名和同义词的清单。这样当用户说“金钟”时NLU可以直接返回标准化的IDADM大大减轻后端的映射负担。本项目的代码实现可以看作是后端的兜底逻辑。3.3 第三方API集成与数据抓取这是项目中最具挑战性的部分因为你需要逆向工程或找到可靠的MTR实时数据源。通常这类数据来自非官方的、为手机App提供服务的API。const axios require(axios); const https require(https); // 用于自定义Agent应对某些证书问题 // 创建一个自定义的axios实例便于统一配置 const mtrApiClient axios.create({ baseURL: https://api.example-mtr-service.com, // 假设的API地址 timeout: 5000, // 5秒超时语音交互要求快速响应 httpsAgent: new https.Agent({ keepAlive: true }), // 保持连接提升性能 headers: { User-Agent: HK-MTR-Next-Train-Skill/1.0 (Node.js), // 有些API可能需要特定的Referer或Token // Authorization: Bearer YOUR_TOKEN } }); async function fetchMTRNextTrain(fromCode, toCode) { try { // 参数需要根据实际API文档调整 const response await mtrApiClient.get(/next-train, { params: { line: TCL, // 例如TCL东涌线需根据站点判断线路 from: fromCode, to: toCode, lang: tc // 繁体中文 } }); // 假设API返回格式为 { data: [ { time: 120, destination: CHW, ... }, ... ] } if (response.data response.data.data) { return response.data.data; } else { throw new Error(API返回数据格式异常); } } catch (error) { // 细化错误类型 if (error.response) { // 请求已发出服务器返回状态码非2xx console.error(API响应错误: ${error.response.status}, error.response.data); throw { code: API_ERROR, message: 服务端错误: ${error.response.status} }; } else if (error.request) { // 请求已发出但无响应 console.error(网络无响应:, error.request); throw { code: NETWORK_ERROR, message: 无法连接到港铁服务 }; } else { // 请求配置出错 console.error(请求配置错误:, error.message); throw { code: CONFIG_ERROR, message: error.message }; } } }关键注意事项API稳定性非官方API可能随时失效或变更。在项目中必须将API的URL、参数等配置化放在环境变量或配置文件中而不是硬编码在代码里。请求频率限制避免过于频繁地调用API以免被拉黑。Lambda函数本身是无状态的如果需要限流可以考虑使用AWS API Gateway的节流设置或者在代码中加入简单的内存缓存对于Lambda由于冷启动缓存效果有限。数据缓存策略列车时刻数据变化频率是分钟级的。对于同一对车站的查询在短时间内例如30秒结果是相同的。可以在Lambda函数内部使用一个简单的内存对象做短期缓存键为${fromCode}-${toCode}值为数据和过期时间。这能显著减少对外部API的调用提升响应速度并降低对方服务器的压力。备用数据源如果主要API失效是否有备选方案例如是否可以解析MTR官网的移动版页面虽然这不是最佳实践但作为降级方案可以保证技能在极端情况下仍能提供基本服务哪怕只是提示“服务暂时不可用”而非直接崩溃。4. 本地开发、测试与部署全流程4.1 本地开发环境搭建你不需要每次都部署到Lambda才能测试。亚马逊提供了非常强大的本地测试工具。安装ASK CLI命令行工具这是管理Alexa技能的瑞士军刀。npm install -g ask-cli ask configure # 按照提示登录你的亚马逊开发者账号和AWS账号初始化项目如果你是从头创建技能可以使用ask new。对于现有项目如克隆的hk-mtr-next-train-skill你需要关注其目录结构。标准的ASK项目通常包含skill-package/ # 交互模型、技能元数据 interactionModels/custom/zh-HK.json # 粤语交互模型 skill.json # 技能清单文件 lambda/ # Lambda函数代码 index.js package.json util/ ... .ask/ # ASK CLI配置文件本地模拟测试使用ask simulate或ask dialog命令可以直接在终端模拟语音交互无需真实设备。# 模拟说一句“查询从金钟到中环的下一班车” ask simulate -t 問港鐵從金鐘到中環下一班車 -l zh-HK --skill-id your-skill-id这会返回一个详细的JSON响应包含Alexa的回复文本。这是调试意图和槽位解析最快的方式。4.2 单元测试与集成测试策略为语音技能写测试主要针对Lambda函数里的业务逻辑。单元测试使用Jest或Mocha。测试stationNameToCode映射函数、时间计算函数等纯逻辑。// jest 测试示例 describe(stationNameToCode, () { test(应正确映射繁体中文站名, () { expect(stationNameToCode(金鐘)).toBe(ADM); }); test(应处理简体中文站名, () { expect(stationNameToCode(金钟)).toBe(ADM); }); test(应处理英文站名, () { expect(stationNameToCode(Admiralty)).toBe(ADM); }); test(未匹配时应返回null, () { expect(stationNameToCode(不存在的车站)).toBeNull(); }); });集成测试模拟请求模拟完整的AlexaIntentRequest事件对象测试整个handle函数的处理流程。ASK SDK提供了skill-testing库来帮助构建模拟事件。const { handler } require(../index); const alexaTest require(ask-sdk-test); const testSkill alexaTest.fromSkill(handler); describe(NextTrainIntent Handler, () { test(应能处理完整的查询请求, async () { const event alexaTest.getIntentRequest({ name: NextTrainIntent, slots: { fromStation: { value: 金鐘 }, toStation: { value: 中環 } } }, zh-HK); const response await testSkill.invoke(event); expect(response.response.outputSpeech.ssml).toContain(分鐘後到達); expect(response.response.shouldEndSession).toBe(true); }); });4.3 部署到AWS Lambda使用ASK CLI可以一键部署技能的所有部分。部署Lambda函数代码cd lambda npm install --production # 安装生产环境依赖 ask deploy --target lambda这个命令会将你的lambda目录打包上传到AWS Lambda。部署技能包交互模型ask deploy --target skill这个命令会更新Alexa开发者控制台中的技能交互模型和配置。环境变量配置在Lambda控制台或使用AWS CLI为你函数的环境变量设置必要的值如API端点、缓存时间等。绝对不要将敏感信息写在代码里。4.4 真实设备测试与技能认证在本地和模拟测试通过后必须在真实Alexa设备或模拟器上进行端到端测试。在开发者控制台进行测试Alexa开发者控制台提供了“测试”标签页你可以直接在那里输入文本或语音需要麦克风进行测试并查看详细的请求/响应日志。这是排查问题最有效的工具。在真实设备上测试将你的技能从“开发”状态切换到“测试”状态后在绑定了同一亚马逊账号的Alexa设备上就可以直接说“打开[你的技能名]”进行测试。技能发布与认证当你准备公开发布技能时需要在控制台提交认证。亚马逊会对你的技能进行审核检查内容包括交互是否流畅、隐私政策是否合规、功能描述是否准确等。对于查询公共交通信息的技能通常还需要确保数据源的可靠性和时效性有明确说明。5. 常见问题、优化思路与扩展可能5.1 开发与调试中的常见“坑”问题现象可能原因排查步骤与解决方案技能无法唤醒或报“技能没有响应”Lambda函数超时或崩溃技能ID配置错误。1. 检查CloudWatch日志看Lambda是否有报错。2. 确认skill.json中的endpoint指向正确的Lambda ARN。3. 确保Lambda函数的超时时间设置合理建议5-10秒。Alexa说“我没有听懂”或错误触发其他意图交互模型意图、话语样本定义不充分槽位类型或值冲突。1. 为每个意图提供足够多、涵盖不同表达方式的话语样本。2. 检查槽位是否有同义词并确保实体解析配置正确。3. 在开发者控制台的“测试”页面查看NLU解析结果确认槽位填充是否正确。能识别意图但返回错误数据站名映射失败第三方API调用失败或返回格式变化。1. 在代码中打印出接收到的槽位原始值检查映射逻辑。2. 使用axios拦截器或直接打印API请求和响应验证数据获取是否正常。3. 为外部API调用添加完善的错误处理和降级方案。技能响应速度慢Lambda冷启动外部API响应慢网络延迟。1. 为Lambda函数配置预留并发Provisioned Concurrency以减少冷启动。2. 实现数据缓存减少重复API调用。3. 优化代码移除不必要的依赖减小部署包体积。在设备上测试正常但提交认证失败技能可能在某些边缘场景下崩溃隐私政策或使用条款缺失。1. 进行全面的负面测试测试未提供槽位、提供无效槽位、网络中断等情况。2. 确保技能详情页填写完整包括详细的描述、示例语句、隐私政策链接如果收集数据。5.2 性能与体验优化进阶实现多线路自动判断当前示例需要手动传入line参数。一个更智能的实现是根据fromCode和toCode自动判断所属线路。这需要一个站点-线路映射关系表。例如金钟站ADM属于港岛线ISL和南港岛线SIL查询时需要分别调用两条线的API然后合并结果告诉用户“港岛线下班车2分钟南港岛线下班车5分钟”。增加对话状态管理让技能支持多轮对话。例如用户问“下一班车”技能反问“从哪里出发”用户回答“金钟”技能再问“去哪里”。这需要利用sessionAttributes来存储对话状态。支持更多查询类型末班车查询LastTrainIntent。车站设施查询FacilityIntent如“金钟站有没有洗手间”运营状态查询StatusIntent如“东铁线现在是否正常”适配更多语音平台核心业务逻辑数据获取、处理是通用的。你可以用同一套逻辑封装成符合Google Assistant Actions、百度DuerOS或小米小爱同学规范的技能最大化代码复用。5.3 从项目中学到的核心经验通过剖析tomfong/hk-mtr-next-train-skill这个项目我们可以提炼出开发一个成功语音技能的通用经验语音交互设计优先不要一上来就写代码。先想清楚用户会怎么问设计好对话流程。用纸笔画出来或者用工具模拟这能节省大量的后期调试时间。外部依赖是最大的风险点尤其是依赖非官方的、逆向工程得到的API。你的技能稳定性直接取决于它的稳定性。一定要有降级方案和监控报警例如当API连续失败多次时通过SNS发送邮件或短信通知开发者。错误处理要面向用户后端代码的try-catch里不能只是console.error。必须转化为用户能听懂的、友好的、甚至带有引导性的语音提示。测试必须覆盖全链路从NLU解析、意图处理、外部API调用、到语音响应构建每一个环节都要测试。模拟测试、单元测试、集成测试、真机测试一环都不能少。无服务器不是“免运维”你仍然需要关注日志CloudWatch、监控X-Ray、成本Lambda调用次数、持续时间和安全性IAM角色权限。这个项目就像一个精心打磨的样板间展示了如何将一个具体的日常生活需求通过清晰的技术架构和扎实的代码实现转化为一个真正可用的语音应用。无论你是想复现一个类似的交通查询技能还是想借鉴其模式开发其他领域的语音助手其中的设计思路和实战代码都极具参考价值。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2599465.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;替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…