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

相关推荐
fellow9920 小时前
DSH Desktop:把 DeepSeek Harness 变成真正的桌面应用
electron·agent·ai编程·deepseek
CDwenhuohuo2 天前
electron pc项目打包成桌面端
前端·javascript·electron
不可能片场3 天前
命令行中文变问号 我用环境变量救了场
前端·electron
不可能片场3 天前
AI视频口型对齐 用音频驱动说话镜头
前端·electron
Zoom4 天前
【开源】7 天,我用 Rust 复刻了 FinalShell!Rhost v1.0.0 发布
rust·electron·shell
爱丶不疚5 天前
Electron: Sentry 都采集了什么?你知道吗
前端·electron
格数致用5 天前
03- Luckysheet与Vue3+Electron集成实战指南
electron·vue3·luckysheet
fellow997 天前
Electron + pnpm 在鸿蒙应用里跑起来
electron·harmonyos·openharmony·deepseek·deepseekharness
记得开心一点嘛7 天前
Trellora:基于 Electron、React 和本地知识库的 AI 知识工作台
人工智能·react.js·electron
500847 天前
React Native for OpenHarmony 实战:三方库 react-native-url-polyfill 的鸿蒙化适配指南
javascript·react native·react.js·性能优化·electron·harmonyos