本地 AI 处理器¶
此 API 是实验性的。 它可能会在后续 Electron 版本中更改或被移除。
Electron 通过允许你将调用路由到运行在 utility 进程 中的本地 LLM,支持 Chromium 的实验性 Prompt API
(LanguageModel)Web API。Web 内容会像在任意浏览器中一样调用
LanguageModel.create() 和 LanguageModel.prompt(),而你的 Electron 应用决定由哪个模型处理请求。
工作原理¶
本地 AI 处理器架构涉及三个进程:
- 主进程 — 创建
UtilityProcess,然后通过ses.registerLocalAIHandler()将其注册为处理指定会话的 Prompt API 调用。 - utility 进程 — 运行一个脚本,该脚本调用
localAIHandler.setPromptAPIHandler()以提供一个LanguageModelUtility子类。 - 渲染进程 — Web 内容使用来自 Chromium 实验性 Prompt API 的
LanguageModelAPI (例如LanguageModel.create()、model.prompt())。
当渲染进程调用 Prompt API 时,Electron 会通过主进程将请求代理到已注册的 utility 进程,该进程会调用你的
LanguageModel 实现,并将结果直接发送回渲染进程。
前提条件¶
任何将使用 Prompt API 的 BrowserWindow 都必须通过 AIPromptAPI 功能启用 Prompt API Blink 功能。若要启用多模态输入,还需添加
AIPromptAPIMultimodalInput。
快速开始¶
1. 创建 utility 进程脚本¶
utility 进程脚本会注册你的 LanguageModelUtility 子类。处理函数会接收一个包含调用者信息的 details 对象,并且必须返回一个继承自 LanguageModelUtility 的类。
const { localAIHandler, LanguageModelUtility } = require('electron/utility')
localAIHandler.setPromptAPIHandler((details) => {
// details.webContentsId — ID of the calling WebContents
// details.securityOrigin — origin of the calling page
return class MyLanguageModel extends LanguageModelUtility {
static async create (options) {
// options.signal - AbortSignal to cancel the creation of the model
// options.initialPrompts - initial prompts to pass to the language model
return new MyLanguageModel({
contextUsage: 0,
contextWindow: 4096
})
}
static async availability () {
// Return 'available', 'downloadable', 'downloading', or 'unavailable'
return 'available'
}
async prompt (input) {
// input is a LanguageModelMessage[]
// Return a string response from your model, or a ReadableStream
// to return a streaming response.
return 'This is a response from your local LLM!'
}
async clone () {
return new MyLanguageModel({
contextUsage: this.contextUsage,
contextWindow: this.contextWindow
})
}
destroy () {
// Clean up model resources
}
}
})
2. 在主进程中注册处理器¶
分叉 utility 进程,并将其注册为某个会话的 AI 处理器:
const { app, BrowserWindow, utilityProcess } = require('electron')
const path = require('node:path')
app.whenReady().then(() => {
// Fork the utility process running your AI handler script
const aiHandler = utilityProcess.fork(path.join(__dirname, 'ai-handler.js'))
// Create a window with the Prompt API enabled
const win = new BrowserWindow({
webPreferences: {
enableBlinkFeatures: 'AIPromptAPI'
}
})
// Connect the AI handler to this session
win.webContents.session.registerLocalAIHandler(aiHandler)
win.loadFile('index.html')
})
3. 在渲染进程中使用 Prompt API¶
你的 Web 内容现在可以使用标准的 LanguageModel API,它是渲染进程中可用的全局对象:
<script>
async function askAI () {
const model = await LanguageModel.create()
const response = await model.prompt('What is Electron?')
document.getElementById('response').textContent = response
}
</script>
<button onclick="askAI()">Ask AI</button>
<p id="response"></p>
实现真实模型¶
快速开始示例返回一个硬编码字符串。真实实现会与本地模型集成。有关使用 node-llama-cpp 连接 GGUF(GPT-Generated Unified Format)模型的示例,请参阅 electron/llm。
清除处理器¶
要将 AI 处理器与会话断开连接,请传入 null:
js @ts-type={win:Electron.BrowserWindow}
win.webContents.session.registerLocalAIHandler(null)
清除后,使用该会话的渲染进程发出的任何 LanguageModel.create() 调用都将失败。
延迟注册处理器¶
如果渲染进程在 ses.registerLocalAIHandler() 已被调用之后、但在 utility 进程中 localAIHandler.setPromptAPIHandler() 被调用之前使用 Prompt API,请求不会立即被拒绝。相反,Electron 会将待处理请求排队。一旦调用 setPromptAPIHandler(),所有排队的请求都会被刷新并按正常方式处理。
如果在处理器设置之前到达的请求过多,最旧的待处理请求会被丢弃,并且渲染进程中的待处理 Promise 会被拒绝。请在 utility 进程脚本中尽早调用 setPromptAPIHandler(),以避免出现这种情况。
安全注意事项¶
传递给处理器的 details 对象包含 webContentsId 和 securityOrigin。请使用这些信息来决定是否处理某个请求,以及何时复用模型实例,何时提供新实例,以便在源之间提供适当的隔离。
延伸阅读¶
本页原文 Markdown:在 AtomGit 查看·内容源自开源项目 el/electron