FastGPT源码解析 Agent 大模型对接接口和使用详解

FastGPT 大模型对接核心代码分析

核心架构概览

FastGPT 采用统一模型抽象层设计,通过标准化接口对接多种大模型,支持 LLM、Embedding、ReRank、TTS、STT 等多种 AI 能力。

支持各种大模型能力的配置,包括本地ollama、各个AI云厂商的API接入配置,支持知识库的分词、排序、向量化处理,支持Agent的对话和业务逻辑处理,完成完整的Agent可视化配置支撑。

核心文件主要主要在packages/global/core/ai/目录,有model.ts、model.d.ts、config.ts、index.ts、ReRank.ts等

1. 模型管理架构

全局模型映射

typescript 复制代码
// 全局模型存储结构
declare global {
  var llmModelMap: Map<string, LLMModelItemType>;
  var embeddingModelMap: Map<string, EmbeddingModelItemType>;
  var reRankModelMap: Map<string, ReRankModelItemType>;
  var ttsModelMap: Map<string, TTSModelType>;
  var sttModelMap: Map<string, STTModelType>;
  var systemDefaultModel: {
    llm: LLMModelItemType;
    embedding: EmbeddingModelItemType;
    rerank?: ReRankModelItemType;
    tts?: TTSModelType;
    stt?: STTModelType;
  };
}

模型获取接口

typescript 复制代码
// 统一的模型获取接口
export const getLLMModel = (model?: string) => {
  if (!model) return getDefaultLLMModel();
  return global.llmModelMap.get(model) || getDefaultLLMModel();
};

export const getEmbeddingModel = (model?: string) => {
  if (!model) return getDefaultEmbeddingModel();
  return global.embeddingModelMap.get(model) || getDefaultEmbeddingModel();
};

export const getReRankModel = (model?: string) => {
  if (!model) return getDefaultRerankModel();
  return global.reRankModelMap.get(model) || getDefaultRerankModel();
};

// 通用模型查找
export const findAIModel = (model: string) => {
  return (
    global.llmModelMap.get(model) ||
    global.embeddingModelMap.get(model) ||
    global.ttsModelMap.get(model) ||
    global.sttModelMap.get(model) ||
    global.reRankModelMap.get(model)
  );
};

2. LLM 模型对接

模型配置结构

typescript 复制代码
export type LLMModelItemType = {
  provider: ModelProviderIdType;           // 提供商: OpenAI/Claude/GLM等
  model: string;                           // 模型名称
  name: string;                            // 显示名称
  
  // 能力参数
  maxContext: number;                      // 最大上下文长度
  maxResponse: number;                     // 最大响应长度
  quoteMaxToken: number;                   // 最大引用Token
  maxTemperature?: number;                 // 最大温度值
  
  // 功能支持
  vision?: boolean;                        // 视觉能力
  reasoning?: boolean;                     // 推理能力
  functionCall: boolean;                   // 函数调用
  toolChoice: boolean;                     // 工具选择
  
  // 专用功能
  datasetProcess?: boolean;                // 知识库处理
  usedInClassify?: boolean;               // 问题分类
  usedInExtractFields?: boolean;          // 内容提取
  usedInToolCall?: boolean;               // 工具调用
  
  // 自定义配置
  defaultSystemChatPrompt?: string;        // 默认系统提示词
  defaultConfig?: Record<string, any>;     // 默认请求配置
  fieldMap?: Record<string, string>;       // 字段映射
  
  // 直连配置
  requestUrl?: string;                     // 自定义请求URL
  requestAuth?: string;                    // 自定义认证
};

统一 API 客户端

typescript 复制代码
export const getAIApi = (props?: { 
  userKey?: OpenaiAccountType; 
  timeout?: number 
}) => {
  const { userKey, timeout } = props || {};
  
  // 优先级: 用户配置 > 全局配置 > 环境变量
  const baseUrl = userKey?.baseUrl || 
                  global?.systemEnv?.oneapiUrl || 
                  openaiBaseUrl;
  const apiKey = userKey?.key || 
                 global?.systemEnv?.chatApiKey || 
                 openaiBaseKey;
  
  return new OpenAI({
    baseURL: baseUrl,
    apiKey,
    httpAgent: global.httpsAgent,
    timeout,
    maxRetries: 2
  });
};

聊天完成接口

typescript 复制代码
export const createChatCompletion = async ({
  body, userKey, timeout, options
}) => {
  const modelConstantsData = getLLMModel(body.model);
  
  const ai = getAIApi({ userKey, timeout });
  
  // 支持自定义请求路径和认证
  const response = await ai.chat.completions.create(body, {
    ...options,
    ...(modelConstantsData.requestUrl ? { 
      path: modelConstantsData.requestUrl 
    } : {}),
    headers: {
      ...options?.headers,
      ...(modelConstantsData.requestAuth ? { 
        Authorization: `Bearer ${modelConstantsData.requestAuth}` 
      } : {})
    }
  });
  
  // 判断响应类型
  const isStreamResponse = 
    typeof response === 'object' && 
    response !== null && 
    ('iterator' in response || 'controller' in response);
  
  return { response, isStreamResponse };
};

3. Embedding 模型对接

Embedding 配置

typescript 复制代码
export type EmbeddingModelItemType = {
  provider: ModelProviderIdType;
  model: string;
  name: string;
  
  // Token 配置
  defaultToken: number;                    // 默认分块Token
  maxToken: number;                        // 最大Token
  weight: number;                          // 训练权重
  
  // 处理配置
  normalization?: boolean;                 // 归一化处理
  hidden?: boolean;                        // 是否隐藏
  
  // 自定义配置
  defaultConfig?: Record<string, any>;     // 通用配置
  dbConfig?: Record<string, any>;          // 存储配置
  queryConfig?: Record<string, any>;       // 查询配置
};

向量化实现

typescript 复制代码
export async function getVectorsByText({ 
  model, input, type 
}: GetVectorProps) {
  const ai = getAIApi();
  
  // 根据类型选择配置
  const config = {
    ...model.defaultConfig,
    ...(type === EmbeddingTypeEnm.db && model.dbConfig),
    ...(type === EmbeddingTypeEnm.query && model.queryConfig),
    model: model.model,
    input: [input]
  };
  
  const result = await ai.embeddings.create(
    config,
    model.requestUrl ? {
      path: model.requestUrl,
      headers: model.requestAuth ? {
        Authorization: `Bearer ${model.requestAuth}`
      } : undefined
    } : {}
  );
  
  // 处理向量数据
  const vectors = await Promise.all(
    result.data
      .map(item => unityDimensional(item.embedding))  // 统一维度
      .map(item => {
        if (model.normalization) return normalization(item);  // 归一化
        return item;
      })
  );
  
  return { tokens: await countPromptTokens(input), vectors };
}

// 统一向量维度到1536
function unityDimensional(vector: number[]) {
  if (vector.length > 1536) {
    return vector.slice(0, 1536);
  }
  const zeroVector = new Array(1536 - vector.length).fill(0);
  return vector.concat(zeroVector);
}

// L2归一化处理
function normalization(vector: number[]) {
  if (vector.some(item => item > 1)) {
    const norm = Math.sqrt(vector.reduce((sum, val) => sum + val * val, 0));
    return vector.map(val => val / norm);
  }
  return vector;
}

4. ReRank 模型对接

ReRank 实现

typescript 复制代码
export function reRankRecall({
  model = getDefaultRerankModel(),
  query,
  documents
}: {
  model?: ReRankModelItemType;
  query: string;
  documents: { id: string; text: string }[];
}): Promise<ReRankCallResult> {
  
  const { baseUrl, authorization } = getAxiosConfig();
  
  return POST<PostReRankResponse>(
    model.requestUrl ? model.requestUrl : `${baseUrl}/rerank`,
    {
      model: model.model,
      query,
      documents: documents.map(doc => doc.text)
    },
    {
      headers: {
        Authorization: model.requestAuth ? 
          `Bearer ${model.requestAuth}` : 
          authorization
      },
      timeout: 30000
    }
  ).then(data => {
    return data?.results?.map(item => ({
      id: documents[item.index].id,
      score: item.relevance_score
    }));
  });
}

5. 模型配置管理

配置文件结构

json 复制代码
{
  "llmModels": [
    {
      "provider": "OpenAI",
      "model": "gpt-4o-mini",
      "name": "gpt-4o-mini",
      "maxContext": 128000,
      "maxResponse": 16000,
      "quoteMaxToken": 120000,
      "vision": true,
      "datasetProcess": true,
      "usedInClassify": true,
      "usedInExtractFields": true,
      "usedInToolCall": true,
      "toolChoice": true,
      "functionCall": false,
      "defaultConfig": {},
      "fieldMap": {}
    }
  ],
  "vectorModels": [
    {
      "provider": "OpenAI",
      "model": "text-embedding-3-small",
      "name": "text-embedding-3-small",
      "defaultToken": 512,
      "maxToken": 3000,
      "weight": 100
    }
  ],
  "reRankModels": [],
  "audioSpeechModels": [
    {
      "provider": "OpenAI",
      "model": "tts-1",
      "name": "OpenAI TTS1",
      "voices": [
        { "label": "Alloy", "value": "alloy" },
        { "label": "Echo", "value": "echo" }
      ]
    }
  ],
  "whisperModel": {
    "provider": "OpenAI",
    "model": "whisper-1",
    "name": "Whisper1"
  }
}

动态模型管理

typescript 复制代码
// 模型配置更新
export const updateModelConfig = async (modelData: any) => {
  // 验证模型配置
  const validatedModel = validateModelConfig(modelData);
  
  // 更新全局映射
  if (validatedModel.type === 'llm') {
    global.llmModelMap.set(validatedModel.model, validatedModel);
  } else if (validatedModel.type === 'embedding') {
    global.embeddingModelMap.set(validatedModel.model, validatedModel);
  }
  
  // 持久化配置
  await saveModelConfig(validatedModel);
};

// 模型测试
export const testModel = async (modelConfig: any) => {
  try {
    if (modelConfig.type === 'llm') {
      const response = await createChatCompletion({
        body: {
          model: modelConfig.model,
          messages: [{ role: 'user', content: 'Hello' }],
          max_tokens: 10
        }
      });
      return { success: true, response };
    }
    
    if (modelConfig.type === 'embedding') {
      const result = await getVectorsByText({
        model: modelConfig,
        input: 'test text'
      });
      return { success: true, vectors: result.vectors };
    }
  } catch (error) {
    return { success: false, error: error.message };
  }
};

6. 多提供商支持

提供商适配

typescript 复制代码
// 支持的模型提供商
export enum ModelProviderIdType {
  OpenAI = 'OpenAI',
  Anthropic = 'Anthropic',
  Google = 'Google',
  Baidu = 'Baidu',
  ByteDance = 'ByteDance',
  Moonshot = 'Moonshot',
  DeepSeek = 'DeepSeek',
  Other = 'Other'
}

// 提供商特殊处理
const providerAdapters = {
  [ModelProviderIdType.OpenAI]: {
    formatRequest: (body) => body,
    formatResponse: (response) => response
  },
  [ModelProviderIdType.Anthropic]: {
    formatRequest: (body) => ({
      ...body,
      // Claude 特殊格式转换
    }),
    formatResponse: (response) => ({
      // 响应格式标准化
    })
  }
};

字段映射处理

typescript 复制代码
// 处理不同模型的字段差异
const applyFieldMapping = (body: any, fieldMap: Record<string, string>) => {
  const mappedBody = { ...body };
  
  Object.entries(fieldMap).forEach(([from, to]) => {
    if (mappedBody[from] !== undefined) {
      mappedBody[to] = mappedBody[from];
      delete mappedBody[from];
    }
  });
  
  return mappedBody;
};

// 示例: o1 模型字段映射
const o1FieldMap = {
  "max_tokens": "max_completion_tokens"
};

7. 错误处理与监控

统一错误处理

typescript 复制代码
const handleModelError = (error: any, modelConfig: any) => {
  addLog.error(`Model ${modelConfig.model} error`, {
    error: error.message,
    provider: modelConfig.provider,
    requestUrl: modelConfig.requestUrl
  });
  
  // 根据错误类型返回友好提示
  if (error.code === 'insufficient_quota') {
    return '模型配额不足,请检查账户余额';
  }
  if (error.code === 'model_not_found') {
    return '模型不存在,请检查模型配置';
  }
  
  return `模型调用失败: ${error.message}`;
};

性能监控

typescript 复制代码
const monitorModelPerformance = async (modelCall: () => Promise<any>) => {
  const startTime = Date.now();
  
  try {
    const result = await modelCall();
    const duration = Date.now() - startTime;
    
    addLog.info('Model call success', {
      duration,
      tokens: result.tokens,
      cost: result.cost
    });
    
    return result;
  } catch (error) {
    const duration = Date.now() - startTime;
    
    addLog.error('Model call failed', {
      duration,
      error: error.message
    });
    
    throw error;
  }
};

总结

FastGPT 大模型对接核心实现了统一、灵活、可扩展的模型管理架构:

  1. 统一抽象: 通过标准化接口屏蔽不同模型的差异
  2. 多模型支持: LLM、Embedding、ReRank、TTS、STT 全覆盖
  3. 灵活配置: 支持自定义请求路径、认证、字段映射
  4. 动态管理: 运行时模型配置更新和测试
  5. 错误处理: 完善的错误处理和性能监控
  6. 提供商适配: 支持主流 AI 服务提供商

这套架构为 FastGPT 提供了强大的 AI 能力集成基础,支持快速接入新的模型和提供商。

相关推荐
大熊猫侯佩16 小时前
冰火岛 Tech 传:Apple Foundation Models 心法解密(上集)
llm·ai编程·swift
大熊猫侯佩16 小时前
冰火岛 Tech 传:Apple Foundation Models 心法解密(下集)
llm·ai编程·apple
程序员X小鹿17 小时前
Trae SOLO实战分享:3小时上线一个网站,全栈开发 + 自动部署,吊打Claude Code?(附保姆级教程)
ai编程·trae·solo
SamDeepThinking18 小时前
Cursor集成MCP MySQL服务器完整配置指南
后端·ai编程·cursor
302AI1 天前
Claude 断供中国之际,Kimi-K2-0905 低调上线:时势造英雄
人工智能·llm·ai编程
用户4099322502121 天前
如何在 FastAPI 中优雅地模拟多模块集成测试?
后端·ai编程·trae
玲小珑1 天前
LangChain.js 完全开发手册(六)Vector 向量化技术与语义搜索
前端·langchain·ai编程
yaocheng的ai分身1 天前
Andrej Karpathy的最新帖子:分层的大模型辅助编程实践
ai编程