Electron LanguageModelUtility 完全解析:在 Utility 进程中构建本地 AI 语言模型能力
2026/9/7 17:08:50 网站建设 项目流程

Electron LanguageModelUtility 完全解析:在 Utility 进程中构建本地 AI 语言模型能力

【免费下载链接】electron:electron: Build cross-platform desktop apps with JavaScript, HTML, and CSS项目地址: https://gitcode.com/GitHub_Trending/el/electron

Electron 通过实验性的 Prompt API 让渲染进程可以调用本地大语言模型(LLM),而LanguageModelUtility是这条链路上运行在 Utility 进程中的核心类。本文基于当前仓库中 docs/api/language-model-utility.md 的完整 API 定义展开,逐一讲清构造器、静态方法、实例属性与实例方法的语义,结合 结构类型文档 与 lib/utility/api/language-model-utility.ts 的实现源码,说明它如何与 localAIHandler 协作,帮助你在 Electron 应用中落地本地 AI 推理能力。

一、类定位:Utility 进程中的本地 AI 语言模型实现

LanguageModelUtility的官方定位是 “Implement local AI language models”(实现本地 AI 语言模型),其所属进程为Utility 进程(见 glossary 中对 Utility 进程的定义)。

这个设计符合 Electron 的多进程模型:重计算、可能崩溃的模型推理被隔离在主进程与渲染进程之外的独立 Utility 进程中运行,主进程通过session注册本地 AI 处理器,渲染进程通过 Prompt API 发起请求,三者通过 IPC/Mojo 边界解耦。从源码结构看,该类的 JavaScript 侧实现由以下文件组织:

  • lib/utility/api/language-model-utility.ts:LanguageModelUtility类的 TS 实现;
  • lib/utility/api/module-list.ts:将'LanguageModelUtility''localAIHandler'两个模块注册进 Utility 进程的模块清单;
  • lib/utility/api/local-ai-handler.ts:localAIHandler模块,直接包装 C++ 侧绑定electron_utility_local_ai_handler并挂上EventEmitter原型;
  • lib/utility/init.ts:Utility 进程初始化时通过v8Util.setHiddenValue注册isLanguageModel/isLanguageModelClass判断函数,供框架识别传递到各进程中的LanguageModelUtility实例。

二、构造器:new LanguageModelUtility(initialState)

构造器接收一个initialState对象,包含两个数字字段:

字段类型说明
contextUsagenumber当前上下文窗口中已占用的 token 数
contextWindownumber上下文窗口总容量(token 数)

对应源码(language-model-utility.ts#L10-L13)中,构造器只是把这两个值直接赋给实例属性:

interface LanguageModelConstructorValues { contextUsage: number; contextWindow: number; } export default class LanguageModelUtility implements Electron.LanguageModelUtility { contextUsage: number; contextWindow: number; constructor(values: LanguageModelConstructorValues) { this.contextUsage = values.contextUsage; this.contextWindow = values.contextWindow; } // ... }

文档中有一条明确的注意事项(NOTE):不要在类之外直接调用该构造器,因为这样创建的实例不会与localAIHandler正确建立连接。创建实例的正确方式是下一节的静态方法LanguageModelUtility.create()

三、静态方法

3.1LanguageModelUtility.create(options)(实验性)

  • options:LanguageModelCreateOptions
  • 返回值:Promise<LanguageModelUtility>

使用提供的options创建一个新的LanguageModelUtility实例。

LanguageModelCreateOptions结构继承自LanguageModelCreateCoreOptions,完整字段如下(结合 language-model-create-options.md 与 language-model-create-core-options.md):

字段类型是否可选说明
signalAbortSignal取消信号,用于中止创建过程
initialPromptsLanguageModelMessage[]创建时注入的初始提示消息列表
expectedInputsLanguageModelExpected[]声明模型预期接收的输入模态
expectedOutputsLanguageModelExpected[]声明模型预期产生的输出模态

其中LanguageModelExpected的字段为:

  • type(string):text/image/audio三者之一;
  • languages(string[],可选):语言列表。

从当前仓库的 JS 侧实现看,create()目前是一个占位实现,返回contextUsage: 0, contextWindow: 0的空上下文实例(language-model-utility.ts#L15-L20):

static async create(): Promise<LanguageModelUtility> { return new LanguageModelUtility({ contextUsage: 0, contextWindow: 0 }); }

这说明 JS 层只是整个调用链的端点之一,真正的模型装载发生在 C++ 侧的 Prompt API 基础设施中,JavaScript 实现负责承载上下文状态并暴露 API 形状。

3.2LanguageModelUtility.availability([options])(实验性)

  • options(可选):LanguageModelCreateCoreOptions
  • 返回值:Promise<string>

探测语言模型的可用性,返回以下四个字符串之一:

返回值含义
available模型已就绪,可立即使用
downloadable模型尚未下载,可以下载
downloading模型正在下载中
unavailable当前环境下模型不可用

该状态机对应用端做 UI 引导非常关键:在展示“开始对话”之前,先调用availability()判断是否需要先触发模型下载流程。当前 JS 侧实现同样为占位逻辑,固定返回'available'(language-model-utility.ts#L22-L24),真实判定逻辑在底层实现中完成。

四、实例属性

languageModelUtility.contextUsage(实验性)

number,表示当前上下文窗口中已使用的 token 数量。

languageModelUtility.contextWindow(实验性)

number,表示上下文窗口总大小(token 数)。

这两个属性与构造器参数一一对应,是衡量“还能再塞多少上下文”的直接依据:可用余量约为contextWindow - contextUsage

五、实例方法

5.1languageModelUtility.prompt(input, options)(实验性)

  • input:LanguageModelMessage[]
  • options:LanguageModelPromptOptions
  • 返回值:Promise<string> | Promise<import('stream/web').ReadableStream<string>>

向模型发起提示并获取响应。返回值是Promise<string>Promise<ReadableStream<string>>的联合类型,即调用方既可以拿到完整的字符串响应,也可以消费一个文本流(适合逐字渲染的对话界面)。

LanguageModelPromptOptions的字段(见 language-model-prompt-options.md):

字段类型是否可选说明
responseConstraintObject | RegExpJSON Schema 对象或正则表达式,用于约束响应必须匹配指定结构(结构化输出)
signalAbortSignal取消信号

LanguageModelMessage的结构(见 language-model-message.md):

字段类型是否可选说明
rolestring取值system/user/assistant
contentLanguageModelMessageContent[]消息内容数组
prefixboolean标记是否为前缀消息

LanguageModelMessageContent则支持多模态(见 language-model-message-content.md):

字段类型说明
typestring取值text/image/audio
valueArrayBuffer | string文本内容用 string,二进制内容用 ArrayBuffer

一个符合上述结构的调用示例(参数形状以文档为准):

const response = await lm.prompt( [ { role: 'system', content: [{ type: 'text', value: 'You are a helpful assistant.' }] }, { role: 'user', content: [{ type: 'text', value: '总结这段话的核心观点。' }] } ], { signal: new AbortController().signal, responseConstraint: { type: 'object', properties: { summary: { type: 'string' } } } } );

5.2languageModelUtility.append(input, options)(实验性)

  • input:LanguageModelMessage[]
  • options:LanguageModelAppendOptions(仅含必选字段signal: AbortSignal
  • 返回值:Promise<undefined>

向模型追加消息但触发响应生成,用于多轮对话中维护上下文(例如把上一轮的 assistant 回复回填进会话历史)。对应 JS 实现为空的 async 方法(language-model-utility.ts#L30)。

5.3languageModelUtility.measureContextUsage(input, options)(实验性)

  • input:LanguageModelMessage[]
  • options:LanguageModelPromptOptions
  • 返回值:Promise<number>

测量给定输入会占用多少 token,但不实际发起推理。这是实现“输入框剩余 token 提示”“上下文超限预警”的配套 API:先measureContextUsage,再决定是否prompt。JS 侧占位实现返回0(language-model-utility.ts#L32-L34)。

5.4languageModelUtility.clone(options)(实验性)

  • options:LanguageModelCloneOptions(仅含必选字段signal: AbortSignal
  • 返回值:Promise<LanguageModelUtility>

克隆一个LanguageModelUtility,克隆出的实例保留原有的上下文与初始提示。从源码实现看,克隆即把当前的contextUsagecontextWindow复制到新实例(language-model-utility.ts#L36-L41):

async clone() { return new LanguageModelUtility({ contextUsage: this.contextUsage, contextWindow: this.contextWindow }); }

典型场景是从一个已预热上下文的会话派生出独立分支(如并行探索多个问题),分支之间互不污染。

5.5languageModelUtility.destroy()(实验性)

销毁模型,同时中止所有正在进行中的执行。JS 侧实现为空操作(language-model-utility.ts#L43),资源释放由底层完成。调用方应在会话结束、窗口关闭时显式调用,避免遗留模型状态占用 Utility 进程资源。

六、与 localAIHandler 的协作关系

LanguageModelUtility不是孤立使用的。文档对构造器的 NOTE 提示它必须与localAIHandler正确连接,而 docs/api/local-ai-handler.md 说明了这条链路的另一半:

  1. 主进程侧:通过ses.registerLocalAIHandler(handler)把一个脚本注册到指定 session,该脚本即运行在 Utility 进程中;
  2. Utility 进程侧:脚本调用localAIHandler.setPromptAPIHandler(promptAPIHandler)注册 Prompt API 绑定处理器,处理器签名为Function<typeof LanguageModelUtility | null>,接收details对象,包含:
    • webContentsId:发起 Prompt API 调用的 WebContents 唯一 id;
    • securityOrigin:调用页面的 origin;
    • frameToken:发起调用 frame 的 frame token;
    • renderProcessId:承载该 frame 的渲染进程 id。
  3. 请求路由:每对webContentsIdsecurityOrigin触发一次绑定请求。处理器返回null即拒绝该渲染进程创建新的 Prompt API 会话;若要使既有 Prompt API 会话失效,则用ses.registerLocalAIHandler(null)清除 handler。
  4. 排队语义:若渲染进程在setPromptAPIHandler()调用之前就调用了 Prompt API,请求会被排队,handler 设置后统一冲刷;排队过多时会丢弃最旧的待处理请求并拒绝渲染进程中的 pending promise。文档因此建议尽早调用setPromptAPIHandler()

从源码结构看,Utility 进程中的localAIHandler模块直接是 C++ 绑定electron_utility_local_ai_handler的 JS 包装(lib/utility/api/local-ai-handler.ts),而 lib/utility/init.ts 中注册的isLanguageModel/isLanguageModelClass隐藏值,则是框架在跨进程传递LanguageModelUtility实例时进行类型识别的机制。仓库中的功能测试 spec/api-local-ai-handler-spec.ts 也表明,localAIHandler模块的行为受 Prompt API 特性开关控制(features.isPromptAPIEnabled()为真时才执行)。

七、API 使用小结

将文档定义的 API 汇总为速查表:

成员签名返回值用途
new LanguageModelUtility(initialState)initialState: { contextUsage, contextWindow }实例仅限框架内部使用,勿直接构造
LanguageModelUtility.create(options)options: LanguageModelCreateOptionsPromise<LanguageModelUtility>创建实例(推荐入口)
LanguageModelUtility.availability([options])options?: LanguageModelCreateCoreOptionsPromise<string>返回available/downloadable/downloading/unavailable
instance.contextUsagenumber当前已用 token 数
instance.contextWindownumber上下文窗口容量(token)
instance.prompt(input, options)消息数组 + Prompt 选项Promise<string> \| Promise<ReadableStream<string>>发起推理,支持结构化响应约束
instance.append(input, options)消息数组 + signalPromise<undefined>仅追加上下文,不触发响应
instance.measureContextUsage(input, options)消息数组 + Prompt 选项Promise<number>预估算力/上下文占用
instance.clone(options)LanguageModelCloneOptionsPromise<LanguageModelUtility>保留上下文与初始提示地克隆
instance.destroy()销毁模型并中止进行中的执行

需要说明的是:该 API 族整体标注为Experimental,当前仓库的 JavaScript 实现(lib/utility/api/language-model-utility.ts)对createavailabilitypromptmeasureContextUsage等均为形状正确的占位实现,真实的模型装载与推理由 C++ 侧 Prompt API 基础设施承担,且相关功能受 Prompt API 特性开关控制。在应用层使用这些 API 时,应以availability()的结果驱动 UI 流程,用contextUsage/contextWindow监控上下文水位,并在会话结束时调用destroy()释放资源。

【免费下载链接】electron:electron: Build cross-platform desktop apps with JavaScript, HTML, and CSS项目地址: https://gitcode.com/GitHub_Trending/el/electron

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询