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

相关推荐
顾青12 小时前
在 Electron 中引入本地谷歌插件
前端·electron
顾青12 小时前
Electron自定义安装脚本
前端·electron
佩奇的技术笔记13 小时前
桌面端开发技术栈选型:开启高效开发之旅
electron
Rudon滨海渔村14 小时前
【Tauri】桌面程序exe开发 - Tauri+Vue开发Windows应用 - 比Electron更轻量!8MB!
javascript·electron·tauri·桌面应用
培根芝士16 小时前
electron-updater实现自动更新
javascript·electron
朝阳3916 小时前
Electron Forge【实战】桌面应用 —— AI聊天(下)
人工智能·electron
亭台烟雨中1 天前
【前端记事】关于electron的入门使用
前端·javascript·electron