Electron Forge【实战】百度智能云千帆大模型 —— AI聊天

1. 获取 Access Key 与 Secret Key

登录百度智能云
https://login.bce.baidu.com/



2. 安装node.js sdk

ts 复制代码
npm install @baiducloud/qianfan

3. src/main.ts

ts 复制代码
import { setupIPC } from "./ipc";

在 const mainWindow 之后

ts 复制代码
 setupIPC(mainWindow);

4. src/ipc.ts

ts 复制代码
import { ipcMain, BrowserWindow } from "electron";
import { createProvider } from "./providers/createProvider";

interface CreateChatProps {
  messages: {
    role: string;
    content: string;
    imagePath?: string;
  }[];
  providerName: string;
  selectedModel: string;
  messageId: number;
}

export function setupIPC(mainWindow: BrowserWindow) {
  ipcMain.on("start-chat", async (event, data: CreateChatProps) => {
    const { providerName, messages, messageId, selectedModel } = data;

    try {
      const provider = createProvider(providerName);
      const stream = await provider.chat(messages, selectedModel);
      for await (const chunk of stream) {
        const content = {
          messageId,
          data: chunk,
        };
        mainWindow.webContents.send("update-message", content);
      }
    } catch (error) {
      const errorContent = {
        messageId,
        data: {
          is_end: true,
          result:
            error instanceof Error ? error.message : "与AI服务通信时发生错误",
          is_error: true,
        },
      };
      mainWindow.webContents.send("update-message", errorContent);
    }
  });
}

5. src/providers/createProvider.ts

下方代码中,留意更改为第1步得到的 accessKey 和 secretKey

ts 复制代码
import { QianfanProvider } from "./QianfanProvider";

export function createProvider(providerName: string) {
  // 定义 QianfanConfig 接口
  interface QianfanConfig {
    accessKey: string;
    secretKey: string;
  }

  // 定义完整的配置接口
  interface Config {
    qianfan: QianfanConfig;
  }

  const providerConfigs: Config = {
    qianfan: {
      accessKey: "填第1步获取的accessKey",
      secretKey: "填第1步获取的secretKey",
    },
  };

  const providerConfig = providerConfigs[providerName as keyof Config] || {};
  switch (providerName) {
    case "qianfan":
      if (!providerConfig.accessKey || !providerConfig.secretKey) {
        throw new Error(
          "缺少千帆API配置:请在设置中配置 accessKey 和 secretKey"
        );
      }
      return new QianfanProvider(
        providerConfig.accessKey,
        providerConfig.secretKey
      );
    default:
      throw new Error(`不支持的AI服务提供商: ${providerName}`);
  }
}

6. src/providers/QianfanProvider.ts

ts 复制代码
import { ChatCompletion } from "@baiducloud/qianfan";

interface ChatMessageProps {
  role: string;
  content: string;
  imagePath?: string;
}

export class QianfanProvider {
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  private client: any;
  constructor(accessKey: string, secretKey: string) {
    this.client = new ChatCompletion({
      QIANFAN_ACCESS_KEY: accessKey,
      QIANFAN_SECRET_KEY: secretKey,
      ENABLE_OAUTH: true,
    });
  }
  async chat(messages: ChatMessageProps[], model: string) {
    const stream = await this.client.chat(
      {
        messages,
        stream: true,
      },
      model
    );
    return {
      async *[Symbol.asyncIterator]() {
        for await (const chunk of stream) {
          yield chunk;
        }
      },
    };
  }
}

7. src/preload.ts

ts 复制代码
import { ipcRenderer, contextBridge } from "electron";

contextBridge.exposeInMainWorld("electronAPI", {
  startChat: (data: CreateChatProps) => ipcRenderer.send("start-chat", data),
  onUpdateMessage: (callback: OnUpdatedCallback) =>
    ipcRenderer.on("update-message", (_event, value) => callback(value)),
});

interface CreateChatProps {
  messages: {
    role: string;
    content: string;
    imagePath?: string;
  }[];
  providerName: string;
  selectedModel: string;
  messageId: number;
}

interface UpdatgedStreamData {
  messageId: number;
  data: {
    is_end: boolean;
    result: string;
    is_error?: boolean;
  };
}

type OnUpdatedCallback = (data: UpdatgedStreamData) => void;

8. 页面中使用

ts 复制代码
// 访问 AI 模型,获取答案
const get_AI_answer = async (answerIndex: number) => {
  await (window as any).electronAPI.startChat({
    messageId: answerIndex,
    providerName: convsersation.value!.AI_providerName,
    selectedModel: convsersation.value!.AI_modelName,
    // 发给AI模型的消息需移除最后一条加载状态的消息,使最后一条消息为用户的提问
    messages: convsersation
      .value!.msgList.map((message) => ({
        role: message.type === "question" ? "user" : "assistant",
        content: message.content,
      }))
      .slice(0, -1),
  });
};

完整使用范例见
https://blog.csdn.net/weixin_41192489/article/details/146472170

相关推荐
瑞码空间3 天前
Web应用的多端部署之道:浏览器 · Electron · Docker
前端·docker·electron·浏览器·web
upgrador12 天前
桌面应用开发:Electron 与 NSIS 的关系、打包流程及 Windows 本地构建实战
javascript·windows·electron
盒子里的加菲猫12 天前
什么?不会C语言也可以搭建窗口级应用程序?(Electron)
c语言·开发语言·electron
薛定谔的猫-菜鸟程序员14 天前
基于 Electron 的本地短视频解析与下载工具:架构设计与工程实践
java·electron·音视频
imber15 天前
别把多平台发布当复制粘贴:一套可复用的内容工程工作流
electron
imber15 天前
Visual Muse 三平台真实发布验收
electron
前端逗比逗15 天前
Electron 全维度完整配置手册(最新稳定版,适配 Electron 25+)
前端·electron
寒水馨19 天前
Windows下载、安装electron-v43.2.0(附安装包electron-v43.2.0-win32-x64.zip)
javascript·windows·typescript·electron·跨平台·桌面应用·chromium
寒水馨19 天前
macOS下载、安装electron-v43.2.0(附安装包electron-v43.2.0-darwin-arm64.zip)
javascript·macos·electron·node.js·跨平台·桌面应用开发·开源框架
devlei21 天前
Electron原理初探
electron