
人工智能大模型本地部署AI 应用移动开发AI AgentAI 技能MCP Clients【免费下载链接】galleryA gallery that showcases on-device ML/GenAI use cases and allows people to try and use models locally.项目地址https://gitcode.com/GitHub_Trending/gallery44/gallery点击查看免费下载本篇技术指南以 AI Edge Gallerygallery仓库中的内置技能query-wikipedia为主体系统讲解如何在端侧on-device大语言模型环境中通过SKILL.md指令编排 隐藏 WebView 中运行的 JavaScript 脚本实现对 Wikipedia 的模糊搜索、Infobox 信息抽取与多语言摘要查询。读完本文你将掌握该技能的完整参数规范、底层run_js工具调用链、ai_edge_gallery_get_result脚本接口契约以及语言截断、实体抽取等工程细节并可据此理解并改造同类API 查询型端侧技能。一、技能定位端侧 LLM 如何查询 WikipediaAI Edge Gallery 是一个展示端侧机器学习 / GenAI 用例的应用仓库其核心能力之一是Agent Skills代理技能以模块化方式扩展端侧 LLM 的能力边界。由于端侧 LLM 运行在沙箱化的移动环境中无法像云端那样直接执行 Python 脚本或 CLI 命令仓库采用了两条主要执行路径见 skills/README.mdJavaScript 技能在轻量级隐藏 WebView 中执行自定义逻辑原生 App Intent调用 Android/iOS 系统内置能力如发送邮件/短信。query-wikipedia正是第一类JS 技能同时依赖外部 API的典型代表。它的SKILL.md元数据明确标注了其类别标签JSAPI见 skills/README.md 的技能示例清单在仓库中有两个等价副本打包进 App 的版本Android/src/app/src/main/assets/skills/query-wikipedia/SKILL.md含 scripts/index.html仓库开发目录版本skills/built-in/query-wikipedia/SKILL.md含 scripts/index.html。用户向 Agent 提问后LLM 根据系统提示词中附带的技能名称与描述判断相关性命中后自动触发该技能技能背后的 JS 脚本在隐藏 WebView 中完成对https://lang.wikipedia.org/w/api.php的 HTTP 请求再把结构化结果交回 LLM 生成最终回答。二、技能契约SKILL.md 指令文件逐字段解析SKILL.md是每个技能的灵魂文件采用 YAML frontmatter Markdown 指令体的结构Android 端通过 SkillManager.kt 的convertSkillMdToProto将其解析为Skillproto对应字段定义见 skill.proto。2.1 frontmatter 元数据--- name: query-wikipedia description: Query summary from Wikipedia for a given topic. ---name技能唯一标识kebab-case也是 LLM 调用run_js时传入的skillNamedescription插入系统提示词的技能摘要LLM 据此判断用户请求是否与该技能匹配。2.2 Instructionsrun_js 调用规范与 data JSON 结构## Instructions Call the run_js tool using index.html and a JSON string for data with the following fields: - **topic**: Required. Extract ONLY the primary entity, person, or event (e.g., 2026 Oscars, Albert Einstein). You MUST REMOVE all specific question details, action words, or conversational text (e.g., do NOT include words like winner, best picture, who won, history of). Search for the broad subject so the tool can return the main article. - **lang**: Required. The 2-letter language code. This code MUST match the language of the keywords you provided in the topic field. Use standard codes, e.g., en (English), es (Spanish), zh (Chinese), fr (French), de (German), ja (Japanese), ko (Korean), it (Italian), pt (Portuguese), ru (Russian), ar (Arabic), hi (Hindi).字段规格汇总字段是否必填类型取值与规则topic必填String只提取主要实体/人物/事件如2026 Oscars、Albert Einstein必须剔除疑问词、动作词、会话性文本如winner、best picture、who won、history of以宽泛主题词触发主词条搜索lang必填String两位字母语言代码且必须与topic关键词的语言一致标准代码见下表支持的lang标准代码来自原指令均为 ISO 639-1 风格两位代码代码语言代码语言en英语ja日语es西班牙语ko韩语zh中文it意大利语fr法语pt葡萄牙语de德语ru俄语——ar阿拉伯语——hi印地语topic 提取示例指令中的规则在实际问答中的运用用户提问应提取的topic应剔除的内容谁赢得了 2026 年奥斯卡最佳影片2026 Oscarswho won、best picture爱因斯坦的相对论是什么Albert Einsteinrelativity具体问题细节法国大革命的历史意义French Revolutionhistory of、significance2.3 Constraints输出与行为约束**Constraints:** - Provide a concise summary (1-3 complete sentences) to conserve context. Always ensure your response ends with a finished sentence. your response MUST BE written in the SAME language as the users original prompt. - For recurring events or time-sensitive facts, query the specific iteration (e.g., 2026 Oscars). If the user omits the year, default to the current year. - If the exact answer to the users question is not found in the extract, briefly state this, then proactively offer a related piece of information that *was* found in the text.三条约束分别解决三个工程问题上下文节约摘要必须控制在 1–3 个完整句子且以完整句收尾避免污染后续对话上下文同时回答语言必须与用户原始提问语言一致而非与lang一致时效性对周期性事件如奥斯卡、奥运会查询具体届次用户未给年份时默认当年信息兜底抽取文本中找不到确切答案时如实说明并主动补充文本中确实存在的相关内容保证回答有料且诚实。三、脚本实现index.html 的 Wiki 查询流水线技能的真实执行逻辑位于 scripts/index.html核心是fetchWikiFuzzyAndInfobox(topic, lang)函数分四步完成模糊搜索 → 抽取引言 → 解析 Infobox → 语言截断。3.1 第一步模糊搜索获取精确词条标题与引言const baseUrl https://${lang}.wikipedia.org/w/api.php; const searchParams new URLSearchParams({ action: query, format: json, generator: search, gsrsearch: topic, gsrlimit: 1, prop: extracts, explaintext: 1, exintro: 1, origin: *, });要点通过generatorsearchgsrlimit1做模糊搜索并只取第一条从而把用户给出的宽泛topic归一化为维基百科的精确词条标题propextractsexplaintext1获取纯文本提取内容剥离 Wiki 标记exintro1只取引言词条开篇摘要这是后续 LLM 总结的主要素材origin*允许跨域请求适配 WebView 环境的 CORS 策略若searchData.query.pages为空直接返回error: No Wikipedia articles found matching topic in language lang.。3.2 第二步拉取 Section 0 的 HTML 并解析 Infoboxconst parseParams new URLSearchParams({ action: parse, page: title, section: 0, prop: text, format: json, origin: *, });拿到标题后通过actionparsesection0获取词条顶部含信息框的 HTML再用DOMParser定位table.infobox遍历其tr行取每行的th键与td值let key th.textContent.replace(/\[\d\]/g, ).trim(); let value td.textContent .replace(/\[\d\]/g, ) .trim() .replace(/\n/g, | ); infoboxText ${key}: ${value}\n;这里有两处关键的数据清洗删除[1]、[2]之类的引注角标并将多行值合并为|分隔的紧凑文本。若解析失败如页面无 infobox仅打印console.warn后静默继续不阻塞主流程。3.3 第三步合并 Infobox 与引言摘要let finalResult ; if (infoboxText) { finalResult --- INFOBOX ---\n${infoboxText}\n\n; } if (extract) { finalResult --- SUMMARY ---\n${extract}; } if (!finalResult.trim()) { return { error: Found page ${title} but no text or infobox was available. }; }最终输出以--- INFOBOX ---与--- SUMMARY ---两个带标记的区块返回明确区分结构化属性数据与自然语言引言方便 LLM 按需取材。3.4 第四步语言相关的安全截断let maxChars; switch (lang.toLowerCase()) { case zh: maxChars 1500; break; case fr: maxChars 4300; break; case es: maxChars 4500; break; case en: default: maxChars 5000; break; } if (finalResult.length maxChars) { finalResult finalResult.substring(0, maxChars) \n\n... [TRUNCATED TO SAVE CONTEXT]; }不同语言的字符密度差异很大脚本按语言设置了不同的安全上限防止超长文本一次性塞满 LLM 上下文窗口中文zh上限 1500 字符法语fr4300西班牙语es4500英语及其余语言默认 5000截断处以... [TRUNCATED TO SAVE CONTEXT]显式标记。这一设计与SKILL.md中Provide a concise summary to conserve context的约束前后呼应。3.5 对外接口ai_edge_gallery_get_resultwindow[ai_edge_gallery_get_result] async (data) { try { const jsonData JSON.parse(data); if (!jsonData.topic) return JSON.stringify({ error: No topic provided to search. }); if (!jsonData.lang) return JSON.stringify({ error: No language code (lang) provided. }); const wikiResponse await fetchWikiFuzzyAndInfobox(jsonData.topic, jsonData.lang); return JSON.stringify(wikiResponse); } catch (e) { console.error(e); return JSON.stringify({ error: Failed to query Wikipedia: ${e.message} }); } };这是所有 JS 技能必须遵守的统一契约详见 skills/README.md在window上暴露名为ai_edge_gallery_get_result的异步函数接收 App 传入的字符串化 JSON即SKILL.md定义的data解析后执行业务逻辑返回字符串化的 JSON 对象——成功时含title与result字段失败时含error字段。返回值会被 Android 端的run_js工具解析并回传给 LLM。四、调用链剖析run_js 工具如何在 Android 端驱动脚本SKILL.md指令让 LLM 调用run_js工具该工具在 Android 端的实现位于 RunJsTool.kt其注解声明了三个参数Tool(description Runs JS script) fun runJs( ToolParam(description The name of skill) skillName: String, ToolParam(description The script name to run. Use index.html if not provided by user) scriptName: String, ToolParam(description The data to pass to the script. Use empty string if not provided by user) data: String, ): MapString, Any完整执行链路如下定位技能通过skillsProvider.loadSkill(skillName)从已启用技能列表SkillManager.getSelectedSkills()见 SkillManager.kt中按名称模糊匹配忽略大小写、下划线/连字符差异未找到则返回errorstatus: failed密钥处理可选若技能requireSecret为 true先从 DataStore 读取已保存密钥缺失时弹原生对话框向用户索取本技能不涉及构造脚本 URL调用 SkillExtensions.kt 中的getJsSkillUrl(scriptName)把技能目录拼接为baseUrl/scripts/scriptName形式的本地 URL内置技能基于LOCAL_URL_BASE指向 assets发送执行动作通过CallJsToolAction(url, data, secret)让隐藏 WebView 加载index.html并调用ai_edge_gallery_get_result解析结果用 Moshi 将脚本返回的字符串按CallJsSkillResult反序列化error非空判为失败result字段作为文本结果回传image/webview字段则触发对应的 UI 呈现本技能仅返回文本result。期间通过SkillProgressToolAction在聊天界面展示Calling JS script的执行进度与传入的data便于用户观察与调试。此外LoadSkillTool.kt 提供了配套的load_skill工具可将技能完整指令内容注入模型上下文让 LLM 在首次调用前精确理解脚本契约。五、在 App 中启用与安装该技能query-wikipedia属于内置built-in技能。Android 端在启动时会通过 SkillManager.kt 的loadSkills()读取assets/skills目录下的所有SKILL.md并解析为 proto 存储到 DataStore其selected状态决定是否进入 LLM 的系统提示词技能清单getSelectedSkillsNamesAndDescriptions()。若该技能默认未启用用户可参照 skills/README.md 的三种方式添加从社区精选列表添加进入 Agent Skills 用例 → 点击 Skills 芯片进入 Skill Manager → 点()→ 选择Add skill from featured list从 URL 添加将技能托管到真正的 Web 服务如 GitHub Pages需在仓库根目录放置.nojekyll禁用 Jekyll 渲染在Load skill from URL弹窗中输入指向技能文件夹的地址浏览器可直接打开https://your/url/SKILL.md验证远端版本由SkillManager.addSkillFromUrl()拉取校验从本地导入adb push技能目录到设备后通过Import local skill使用系统文件选择器选中目录App 会将其复制到内部存储。启用后用户只需用自然语言提问如用中文介绍一下阿尔伯特·爱因斯坦LLM 即会按SKILL.md指令组装{topic: Albert Einstein, lang: zh}驱动脚本完成查询并以用户语言总结回答。六、工程启示与扩展建议从query-wikipedia的完整实现中可以提炼出通用API 查询型 JS 技能的三个最佳实践指令即契约SKILL.md必须把data的 JSON 字段、取值规则必填/可选、格式写清楚并给出反例如不要包含 winner 这类动作词LLM 才能稳定生成合法参数脚本侧做防御与限流在ai_edge_gallery_get_result内校验必填字段、捕获异常返回error并按语言做字符截断——这比在指令层约束更可靠是保护端侧上下文窗口的最后一道闸门结构化输出便于消费--- INFOBOX ---/--- SUMMARY ---的分区标记让 LLM 能清晰区分事实属性与叙述摘要从而在约束 3 的兜底逻辑下给出更精准的回答。若需在此基础上扩展例如增加维基百科其他 API action、按日期区间检索、或把查询结果以 WebView 形式渲染成富文本卡片只需同步修改index.html的返回 JSON加入webview/image字段与SKILL.md的指令说明其余调用链run_js工具、URL 构造、结果解析无需改动体现了 AI Edge Gallery 技能体系的低耦合可扩展设计。七、进一步阅读技能目录结构、JS 技能开发契约与ai_edge_gallery_get_result返回格式skills/README.mdrun_js工具完整实现RunJsTool.kt技能 URL 拼接逻辑SkillExtensions.kt技能加载、解析与 DataStore 持久化SkillManager.ktSkillproto 字段定义skill.proto其他同类内置技能如calculate-hash、qr-codeskills/built-in赞分享人工智能大模型本地部署AI 应用移动开发AI AgentAI 技能MCP Clients【免费下载链接】galleryA gallery that showcases on-device ML/GenAI use cases and allows people to try and use models locally.项目地址https://gitcode.com/GitHub_Trending/gallery44/gallery点击查看免费下载相关推荐AI Edge Gallery 技能实战深入解析 text-spinner 的 run_js 调用协议与实时 3D 头部追踪实现AI Edge Gallery 技能实战深入解析 text spinner 的 run_js 调用协议与实时 3D 头部追踪实现 在 AI Edge Gall人工智能大模型本地部署AI 应用移动开发AI AgentAI 技能MCP Clientscompromise-wikipedia 插件实战基于 efrt 压缩词库的维基百科实体识别compromise wikipedia 插件实战基于 efrt 压缩词库的维基百科实体识别 导读 本文以 compromise 生态中的实验性插件 compNLP人工智能AI Edge Gallery 端侧邮件发送技能实战从 send-email 的 SKILL.md 到 run_intent 原生意图的实现链路AI Edge Gallery 端侧邮件发送技能实战从 send email 的 SKILL.md 到 run_intent 原生意图的实现链路 导读 sen人工智能大模型本地部署AI 应用移动开发AI AgentAI 技能MCP Clients上一篇ZenlessZoneZero-OneDragon MCP Tool 实现规范绝区零一条龙项目特化的 tool 编写落地指南下一篇react-jsonschema-form中的表单数据校验规则复用策略创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考