Skip to content

Function Calling 与 RAG:让大模型连接外部系统和私有知识

本文旨在全面、详细地介绍大型语言模型(LLM)中两种关键技术:Function Calling(功能调用)和 Retrieval-Augmented Generation (RAG,检索增强生成)。我们将深入探讨它们的工作原理、构建方法、应用场景以及优化技巧,帮助您理解大模型如何通过这两种技术与外部系统交互并利用私有知识库,从而扩展其能力边界,更好地完成复杂任务。

一、Function Calling(功能调用)

Function Calling 目前似乎还没有一个普遍接受的官方中文翻译,常被称为“工具调用”或“函数调用”。其核心思想是让大语言模型能够自主解析用户意图,判断是否需要以及如何使用外部工具(函数),并结构化地调用这些工具来完成特定任务。

1. Function Calling 的核心能力

Function Calling 的能力主要体现在两个方面:

  • 自主解析内容并结构化填槽 (Slot Filling) :模型能够理解用户输入(可能包含多轮对话),从中提取关键信息,并填充到预定义的“槽位”中。这类似于根据对话内容填写表格。

    • 填槽 (Slot Filling) :AI 领域常用术语,指将非结构化文本(如用户对话)解析为结构化字段(槽位)的过程。例如,在零售场景中,将顾客与店员的对话解析出“商品名称”、“购买数量”、“肤质类型”、“预算范围”等字段。这个“填槽”是在 AI 领域非常常用的一个词。
    • 槽位 (Slot) :预先定义好的、需要模型提取和填充的信息字段。例如,查询天气的槽位可能包括“城市”和“日期”;订票的槽位可能包括“出发地”和“目的地”。槽位都是我们人为写在 Prompt 里面的,模型无法自主确定槽位结构,必须通过 Prompt 明确指定。
    • 技术本质:属于提取任务,模型解析文字段落中是否包含某个或某些重要的、预先定义好的信息。

    示例 - 不同的槽位组合:

    • 样例 1 (出行订票) :出发地、目的地
    • 样例 2 (天气查询) :城市、日期
    • 样例 3 (费用报销) :报销事由、报销金额、发生时间
    • 样例 4 (酒店预订) :目的地城市、酒店单价上限、酒店单价下限、区域偏好
  • 自主决策使用工具并结构化调用:模型根据解析到的用户意图和槽位信息,自主判断是否需要调用外部工具,选择合适的工具,并按照预定义的格式(通常是 JSON)准备调用参数,然后输出这个结构化的调用请求。

    • 分类任务:在这一环节,模型实际上在做一个分类任务——判断为了完成用户的当前任务,下一步应该使用哪个工具(或不使用工具直接回答)。
    • 按格式输出而已,不是什么特别的能力:这是理解 Function Calling 的关键。模型本身并不直接“执行”工具,而是按照约定的格式(如 JSON)输出调用请求。模型的输出本质上仍然是文本。大语言模型目前主要具备“眼睛”(理解文本/图像输入)和“嘴巴”(生成文本输出)的能力,它没有手,它本身不是真的去使用工具。

2. Function Calling 的工作原理

Function Calling 并非模型与生俱来的能力,而是通过在微调阶段使用特定数据集进行训练,使其掌握按指令执行任务、特别是按特定格式输出内容的能力。其工作流程大致如下:

  1. System Prompt 中写明了都有哪些工具可以使用,使用的时候要给出什么参数,写成什么格式

    • 这是首要步骤。开发者需要在 System Prompt 中明确告知模型:

      • 可用的工具(函数)列表。
      • 每个工具的详细功能描述。
      • 调用每个工具时必须提供的参数及其数据类型。
      • 参数传递的结构和格式,通常是 JSON 对象。
  2. 意图识别:用户要求做什么任务

    • 模型接收到用户的输入(User Prompt)后,会结合之前的对话历史。
    • 解析并理解用户的真实意图,判断用户当前希望完成的具体任务是什么。
  3. 决策是否使用工具,使用哪个工具

    • 基于对用户意图的理解以及 System Prompt 中定义的可用工具信息,模型进行决策:

      • 当前任务是否需要借助外部工具来完成?
      • 如果需要,应该选择 System Prompt 中定义的哪个工具最为合适?
  4. 调取工具设定的信息传递结构

    • 一旦模型决定使用某个特定的工具,它会“回忆”或调取在 System Prompt 中为该工具预先定义好的信息传递结构,即参数的名称、描述、是否必需以及整体的 JSON 格式。
    json
    // 示例:获取驾驶距离和时长的工具定义
    {
      "name": "get_distance_and_duration",
      "description": "获取从起点到终点的驾车距离和时长", // 这个description非常重要
      "strict": false, 
      "parameters": {
        "type": "object",
        "properties": {
          "origin": {
            "type": "string",
            "description": "驾车的起点(中文描述)" // description指导模型如何解析用户输入
          },
          "destination": {
            "type": "string",
            "description": "驾车的终点(中文描述)"
          }
        },
        "required": ["origin", "destination"] // 声明必填参数
      }
    }
  5. 调取所有上下文内容解析并填槽

    • 模型会仔细审查整个对话历史(上下文)。
    • 依据所选定工具的参数定义中的 description​ 字段(如上述 JSON 示例),模型将这些 description​ 视为一种内部的、针对性的 Prompt。它利用这些描述去理解用户的对话,并从中精确地提取出对应参数所需的值,完成“填槽”操作。因此,description字段描述的是否清楚就决定了语言模型解析用户对话、进行填槽的准确性。
  6. 缺少信息就发起追问,直至全部填完

    • 如果在对话历史中,未能完全获取到工具定义中声明为 required​(必填)的参数信息。
    • 模型会自动生成一个自然的追问,向用户请求提供缺失的必要信息。这种自动发起追问的能力是 Function Calling 非常强大的一点。
  7. 按照槽的格式生成模型回复 (即 Function Call 请求)

    • 当所有必需的参数信息都已通过用户提供或追问补全后。
    • 模型会严格按照该工具预定义的 JSON 格式(或其他指定格式),生成一个包含工具名称 (如 get_distance_and_duration​) 和所有已填充参数 (如 {"origin": "北京", "destination": "上海"}​) 的文本输出。
    • 这个 JSON 输出,就是模型表达“我要调用这个工具,并且参数是这些”的方式。

    总结:Function Calling 是模型经过微调训练后获得的一种按指令执行任务的能力,其核心是利用 LLM 的生成能力,输出某种特定格式的内容(即工具调用请求)。

3. Function Calling 示例:查询天气

让我们通过一个查询天气的例子来理解整个流程。

场景:用户想知道某城市某日期的天气。

步骤

  1. System Prompt 设置: 在 System Prompt 中定义两个工具:

    • get_weather​:根据城市和日期查询天气。

      • 参数:city​ (城市名称), date​ (日期)

      • 输出格式:

        json
        {
          "name": "get_weather",
          "arguments": {
            "city": "要查询的城市",
            "date": "要查询的日期"
          }
        }
    • get_date​:如果用户描述的是相对日期(如“今天”、“明天”),则调用此工具获取实际日期。

      • 参数:query​ (用户对于日期的描述)

      • 输出格式:

        json
        {
          "name": "get_date",
          "arguments": {
            "query": "用户对于日期的描述"
          }
        }
  2. 用户提问 (User Prompt)User: 2024年11月4日北京的天气如何?​(或者 User: 今天北京天气怎么样?​)

  3. 模型处理与响应 (生成 Function Call 请求)

    • 情况一:用户提供明确日期 (2024年11月4日北京的天气如何?​) 模型识别到天气查询意图,且日期和城市信息完整,直接决策调用 get_weather​ 工具。 模型输出:

      json
      {
        "name": "get_weather",
        "arguments": {
          "city": "北京",
          "date": "2024年11月4日"
        }
      }
    • 情况二:用户提供相对日期,且平台无内置日期工具 (今天北京天气?​) 模型首先识别到需要获取“今天”的具体日期,决策调用 get_date​ 工具。 模型输出:

      json
      {
        "name": "get_date",
        "arguments": {
          "query": "今天"
        }
      }
  4. 后端系统/代码/插件执行工具调用

    • 当模型输出上述 JSON 时,后端的应用程序(例如 Coze 平台、或开发者自己编写的代码)会接收到这个 JSON。

    • 应用程序解析 JSON,识别出要调用的工具名称 (get_weather​ 或 get_date​) 和参数。

    • 应用程序实际执行这个工具调用。

      • 对于 get_date​,后端代码可能会查询系统时间,得到“今天”是 2025-02-26​ (假设当前日期)。
      • 对于 get_weather​,后端代码会调用一个真实的天气 API,传入“北京”和“2024 年 11 月 4 日”(或从 get_date ​获取的日期)。
  5. 将工具执行结果返回给模型

    • 工具执行后得到的结果(例如,get_date​ 返回 2025-02-26​;get_weather​ 返回 { "temperature": "5°C", "condition": "晴" }​)会再次作为输入(通常是新的 Prompt,或附加到对话历史中)提供给模型。
    • 例如,如果之前调用了 get_date​ 得到了 2025-02-26​,系统可能会告诉模型:“今天是 2025 年 2 月 26 日”。
  6. 模型根据工具结果生成最终回复

    • 如果上一步是 get_date​ 的结果,模型现在知道了具体日期,它可能会再次发起对 get_weather​ 的调用(如情况一所示)。
    • 如果上一步是 get_weather​ 的结果(例如天气信息为“晴朗,5℃”),模型会基于这些信息,用自然的语言回复用户。Model: 2024年11月4日北京的天气是晴朗,气温5℃。请注意保暖。

流程图示例 (天气查询)

mermaid
graph LR
    A["用户: 今天北京天气如何?"] --> B{模型处理};
    B -- 无内置日期工具时 --> C["生成 get_date 调用请求 <br>{'name':'get_date', 'arguments':{'query':'今天'}}"];
    C --> D["后端执行get_date <br>(查询当前日期)"];
    D -- "返回日期:'2025-02-26'" --> B;
    B -- 获取到日期或日期明确 --> E["生成 get_weather 调用请求 <br>{'name':'get_weather', 'arguments':{'city':'北京', 'date':'2025-02-26'}}"];
    E --> F["后端执行get_weather <br>(调用天气API)"];
    F -- "返回天气信息 <br>例如: 晴, 5℃" --> B;
    B --> G["模型生成最终回复 <br>'今天北京天气晴朗...'"];
    G --> H["用户接收回复"];

    subgraph "第一轮交互 (如果需要)"
        C
        D
    end
    subgraph "第二轮交互"
        E
        F
    end

4. Function Calling 能力的应用场景

Function Calling 可以让模型在特定的小场景中扮演一个智能中枢 (Intelligent Hub) 的角色,协调多个工具来完成复杂任务。

示例:智能故事生成与播放系统

用户需求:“今天是 11 月 6 日,写一个跟最近的节日有关的主题的故事,给 2 岁的小孩,不低于 100 字,不超过 200 字,再给写好的故事生成音频,最后给故事生成配图,每讲述一个场景,就要有一张相应的配图,要适合 2 岁小孩观看的配图。”

模型作为智能中枢的可能执行步骤分解:

  1. 查找日期相关的主题:识别“11 月 6 日”和“最近的节日”,可能需要调用日历工具或知识库查找相关节日(如感恩节、圣诞节临近等)。
  2. 计算适合的字数范围:已明确(100-200 字)。
  3. 生成主题相关的故事:调用自身文本生成能力,创作故事。
  4. 故事文字合成音频:将生成的故事文本,调用语音合成工具 (Text-to-Speech, TTS) 生成音频。
  5. 故事拆解需要配图的段落:分析故事内容,将其划分为若干适合配图的场景或段落。
  6. 给每个段落生成配图:为每个场景/段落生成合适的 Prompt,调用图像生成工具 (Text-to-Image) 生成图片。
  7. 将生成的所有内容组织成一个网页并开始播放(可选高级功能):调用网页生成/内容组织工具,将文字、音频、图片整合到一个页面,并提供播放功能。

所需工具 (通过 Function Calling 调用):

  • 语音合成工具:将文字故事转换为音频。

    • 输入:故事文本,可选音色 ID (speaker_id),语速等。
    • 输出:音频文件链接。
  • 图像生成工具:根据文字描述生成图片。

    • 输入:场景描述文本 (Prompt),可选风格、尺寸等。
    • 输出:图片文件链接。
  • (可选) 网页生成/内容组织工具

System Prompt 设计要点:

  • 明确任务要求(写故事、生成音频、配图)。
  • 详细描述每个可用工具的名称、功能、所需参数(如语音合成工具的 speaker_id​,图像生成工具的风格要求如“迪士尼卡通风格”)。
  • 规定任务执行顺序(如先生成音频并输出链接,再开始生成图片)。
  • 设定约束条件(如故事字数、图片数量、图片风格)。
  • 提供必要的默认参数或固定参数(如默认 speaker_id​)。

调试与优化:

  • 任务复杂度:对于一个 Agent (LLM 实例),如果需要协调多种不同类型的任务(如本例中涉及文本生成、音频合成、图像生成 Prompt 构思、图像生成调用),复杂度较高。过于复杂的任务链条建议使用工作流 (Workflow) 来编排,而不是完全依赖单一 Agent 的 System Prompt。
  • 参数传递:确保工具所需的参数能被正确提取和传递。例如,语音合成工具的 speaker_id​,如果插件描述中有默认值,可以在 Prompt 中再次强调或指定,以确保模型正确调用。
  • 输出格式:明确要求输出内容的格式,如音频链接需要是原始链接,避免模型输出无法直接使用的格式。
  • 错误处理与鲁棒性:在 Prompt 中考虑潜在的调用失败或信息不足的情况,引导模型进行追问或给出友好提示。

通过这样的方式,Function Calling 使得 LLM 不再仅仅是一个文本生成器,而是一个能够理解、规划并借助外部能力来解决问题的智能代理。

二、RAG (Retrieval-Augmented Generation)

RAG,全称 Retrieval-Augmented Generation,即检索增强生成。这是一种让大型语言模型在生成回答时,能够参考外部知识库中检索到的相关信息的技术。

1. RAG 的核心思想与必要性

  • In-Context Learning (ICL) 的扩展:将参考资料、样例等信息直接放入 Prompt 中,让模型在当前上下文中学习并据此生成回答,这种方式被称为上下文学习 (In-Context Learning)。
  • 上下文窗口的局限性:LLM 的 Prompt(上下文窗口)长度是有限的(例如,几千到几十万 tokens)。我们无法将所有可能用到的背景知识、文档、数据都预先塞入 Prompt 中。
  • 动态知识注入的需求:用户的问题是多变的,针对不同问题,模型需要参考的知识也不同。因此,需要一种动态的机制,在模型接收到用户问题后,再去检索相关的知识,并将其注入到当前的 Prompt 中。
  • 私有知识与实时信息:模型预训练的知识截止于某个时间点,并且不包含特定组织或个人的私有数据。RAG 使得模型可以利用最新的、私有的、或领域特定的知识库来回答问题。

RAG 的目标:构建一个知识库,当用户提问时,模型能从中检索到有用的信息片段,并将这些片段作为上下文补充到 Prompt 中,从而生成更准确、更相关、基于特定知识的回答。

核心关系:私有知识库/外部知识源 <--检索--> Prompt <--输入--> 大语言模型。模型本身不直接与知识库交互,知识是通过 Prompt 这个桥梁传递给模型的。

2. RAG 的工作流程

RAG 的实现通常包含两大步骤:

  1. 构建可检索的知识库 (Indexing / Knowledge Base Construction)
  2. 模型调用知识库完成用户任务 (Retrieval & Generation)

2.1. 构建可检索的知识库

这一阶段的目标是将原始的各种格式的知识文档处理成适合机器检索的格式,并存入专门的数据库中。

  1. 知识整理 (Knowledge Acquisition & Curation)

    • 收集来源:以文件格式存储的知识,如 PDF、Word、PPT、Excel、TXT、Markdown(.md)等。也可能包括网页内容、数据库记录、甚至是专家经验(需要转化为文本)。
    • 内容选择:挑选与应用场景相关的、高质量的知识。
  2. 数据清理及格式化 (Data Cleaning & Formatting)

    • 提取纯文本:将不同格式的数据内容(如从 PDF、Word 中)提取为纯文本。去除不相关的元数据、格式标记等。
    • 核心要求:进入知识库的核心内容必须是纯文字的。
  3. 内容切分 (Chunking)

    • 目的:将长文本内容按照段落、主题、逻辑单元或固定长度切分成较小的知识片段 (Chunk) 。切分的粒度对后续检索效果至关重要。

    • 方法:

      • 按固定长度切分(如每 200 个字符一切片)。
      • 按文档结构切分(如按章节、段落)。
      • 语义切分(更高级,试图保持语义完整性)。
      • 交叠切分 (Overlapping Chunking) :相邻的两个知识片段之间有一部分内容是重合的(例如,重叠 50 个字符)。这有助于避免关键信息在切分边界被割裂,提高信息完整性。
      • 多粒度混合切分:针对不同类型的文档或内容,采用不同大小的切片策略。
  4. 向量化 (Vectorization / Embedding)

    • 目的:将每个文本知识片段转化为计算机能够理解和比较的数学表示——向量 (Vector)
    • 工具:使用专门的 Embedding 模型。Embedding 模型能将具有相似语义的文本映射到向量空间中相近的位置。
    • 过程:将每个知识片段输入到 Embedding 模型,输出一个高维(如几百到上千维)的浮点数向量。
  5. 关联元数据 (Metadata Association)

    • 目的:为每个向量(即其对应的知识片段)关联一些描述性的信息,以便后续筛选、过滤或在展示结果时提供上下文。

    • 常见元数据:

      • 文档名称、来源 URL
      • 创建时间、作者
      • 章节、页码
      • 关联的图片、视频链接:如果某个知识片段有对应的图片或视频进行解释说明,可以将这些多媒体资源的链接作为元数据存储。
      • 标签 (Tags) :为知识片段打上分类标签(如产品名称、生效日期、主题类别等),这对于后续知识库的维护、更新、版本管理以及在特定场景下进行精确筛选至关重要。
  6. 载入向量数据库并建立索引 (Loading into Vector Database & Indexing)

    • 向量数据库:专门用于存储和高效检索向量的数据库。常见的有 FAISS (Facebook AI Similarity Search), Pinecone, Weaviate, Milvus, ChromaDB 等。
    • 存储内容:主要存储知识片段的向量表示,同时也会存储知识片段的原文和关联的元数据。
    • 索引:向量数据库会对存储的向量建立索引,以加速相似度检索过程。
  7. 部署集成 (Deployment & Integration)

    • 将构建好的向量数据库集成到 AI 应用的整体流程中,使其能够被大语言模型在需要时调用。

2.2. 模型调用知识库完成用户任务

当用户提出问题后,系统会执行以下步骤来利用知识库生成回答:

  1. System Prompt 中指明知识库使用规则

    • 告知模型在何种情况下应该调用知识库。
    • 如果存在多个知识库,可能需要指明优先使用哪个或如何选择。
    • (在 Coze 等平台,通常是在 Agent 配置中直接关联知识库,模型会自动判断是否使用。)
  2. 模型解析用户意图,判断是否需要调用知识库

    • LLM 分析用户的提问 (User Prompt)。
    • 判断该问题是否适合通过查询已关联的知识库来获取答案。
  3. 将用户提问 (User Prompt) 转换为向量

    • 使用与构建知识库时相同的 Embedding 模型,将用户的提问文本也转换为一个查询向量。
  4. 在向量数据库中进行相似度检索 (Similarity Search)

    • 将用户的查询向量与向量数据库中存储的所有知识片段向量进行比较,计算相似度得分(常用的有余弦相似度、点积等)。
    • 召回 (Recall) :选取相似度得分最高的一条或多条(例如 Top-K,K 通常为 3-10)知识片段作为候选。
    • 重排序 (Re-ranking) (可选但推荐):对召回的 K 个候选片段,可以使用更复杂的模型或规则进行重新排序,以选出最相关、最有用的片段。例如,可以考虑知识片段的时效性、权威性等元数据。
  5. 提取知识片段原文及元数据

    • 从向量数据库中取出在检索和重排序后选中的知识片段的原始文本内容
    • 同时也可以取出其关联的元数据(如图片链接、文档来源等)。
  6. 将检索出的知识片段与原 Prompt 合并,构建增强 Prompt (Augmented Prompt)

    • 将检索到的知识片段原文(可能是一段或几段文本)作为上下文信息,与用户的原始提问、以及可能的 System Prompt 指令,共同组合成一个新的、内容更丰富的 Prompt。

    • 格式示例:

      plaintext
      System: 你是一个乐于助人的AI助手。请根据以下提供的参考资料来回答用户的问题。
      参考资料:
      [从知识库检索到的知识片段1的原文]
      [从知识库检索到的知识片段2的原文]
      ...
      用户问题:[用户的原始提问]
      AI回答:
  7. 模型基于增强 Prompt 生成最终回复

    • 将这个增强后的 Prompt 输入给大语言模型。
    • 模型会综合用户问题和提供的参考资料(即检索到的知识片段)来生成回答。

RAG 流程图

mermaid
graph TD
    subgraph "阶段一:构建知识库 [Indexing]"
        A["原始文档<br>(PDF, Word, TXT等)"] --> B["数据清理与格式化"]
        B --> C["内容切分<br>Chunking"]
        C --> D["知识片段<br>(Chunks)"]
        D --> E["向量化<br>Embedding Model"]
        E --> F["向量 + 元数据"]
        F --> G["向量数据库<br>Vector Database"]
    end

    subgraph "阶段二:检索与生成 [Retrieval & Generation]"
        H["用户提问<br>(Query)"] --> I["问题向量化<br>Same Embedding Model"]
        I --> J{"向量数据库检索<br>(Similarity Search)"}
        G --> J
        J --> K["相关知识片段<br>(Relevant Contexts)"]
        K --> L["构建增强Prompt<br>Query + Contexts"]
        H --> L
        L --> M{"大语言模型<br>(LLM)"}
        M --> N["生成的回复<br>(Response)"]
        N --> O["用户"]
    end

3. RAG 的关键考量与优化

3.1. 检索效率

  • 通常不是瓶颈:现代向量数据库和检索引擎经过大量优化,即使在不使用 GPU 的情况下,对于千万级别的知识片段,也能实现毫秒级的检索返回。
  • GPU 加速:对于更大规模或对延迟要求极高的场景,使用 GPU 可以进一步提升检索速度。

3.2. 检索准确率

RAG 相对于模型微调的一个主要优势在于其可解释性和可调试性。如果 RAG 效果不佳,可以逐步排查问题所在。

常见效果不佳原因:

  1. 文档处理和切分问题

    • 切分粒度不当:切片过大可能包含过多无关信息,导致噪声;切片过小可能丢失上下文,导致语义不完整。
    • 切分边界问题:关键信息被错误地切分到不同片段。
  2. 检索召回不准

    • 最希望被检索到的知识片段,在相似度排序中得分不高,未能进入 Top-K 候选。
    • Embedding 模型对特定领域术语或细微语义差异不敏感。
  3. 整合生成问题

    • 即使检索到了正确的知识片段,模型在结合这些片段生成最终回答时,可能出现概括不当、信息遗漏或逻辑混乱。

提高检索准确率的常见方法

  1. 优化知识片段质量

    • 确保每个知识片段有明确主题
    • 采用交叠切分 (Overlapping Chunks) ,让相邻片段有部分内容重合。
    • 尝试多粒度混合切分 (Mixed Granularity Chunking) ,对不同类型内容采用不同切分策略。
  2. 扩展上下文信息

    • 检索到某个知识片段时,将其上下文相邻的片段(如前一个和后一个)也一并取出,提供更完整的信息给模型。 (Coze 平台可能不直接支持此操作,需代码实现)
  3. 多阶段检索与重排序 (Multi-stage Retrieval & Re-ranking)

    • 初次检索时多召回一些结果(例如 Top-20 或 Top-50)。
    • 然后使用一个独立的、可能更强大的(或针对排序优化的)重排序模型 (Re-ranker Model) 对这些候选结果进行更精细的排序。
  4. 向量 + 关键词混合检索 (Hybrid Search)

    • 结合向量检索(基于语义相似度)和传统的关键词检索(基于字面匹配)。

    • 流程

      1. 让 LLM 从用户问题中提取核心关键词。
      2. 同时进行向量检索和基于这些关键词的文本检索。
      3. 合并两路检索结果,并进行重排序。
    • 优势:对于某些专业术语、产品型号、人名地名等,关键词检索可能更精确。尤其在医疗、金融等领域,一个字的差异(差几个字就差别非常大)可能导致语义巨大变化,此时关键词检索能提供很好的补充。

  5. 查询重写/扩展 (Query Rewriting/Expansion)

    • 让 LLM 将用户的原始提问重写成几种不同的表述方式
    • 对原始问题和所有改写后的问题都进行向量检索。
    • 合并所有检索结果,进行去重和排序。这有助于克服用户原始表述可能存在的不明确或不规范问题。

3.3. 不同 Embedding 模型对 RAG 的影响

Embedding 模型的选择对 RAG 效果有直接影响。

  • 多语言支持:某些 Embedding 模型(如 OpenAI 的)支持多种语言,而另一些(如早期的部分中文模型)可能只针对单一语言优化。需要根据知识库和用户群体的语言选择合适的模型。
  • 向量长度控制:不同模型输出的向量维度不同。通常维度越高,能编码的信息越丰富,但也可能增加存储和计算开销。部分模型允许一定程度的向量长度调整。
  • 定制 Embedding 模型:如果通用 Embedding 模型在特定专业领域效果不佳(例如,无法很好地区分领域内的细微语义差别),可以考虑基于一个开源的 Embedding 模型,使用领域相关的语料进行微调,以提升其在该领域的表示能力。

3.4. 表格处理效果不佳怎么办?

表格数据是 RAG 中较难处理的一类,因为简单的文本提取会丢失表格的行列结构信息。

常见处理策略:

  1. Markdown 格式转换

    • 对于结构相对简单的表格,可以尝试将其转换为 Markdown 表格格式存储。LLM 对 Markdown 格式有一定的理解能力。
    • 局限:复杂表格(如含合并单元格、多层表头等)难以用 Markdown 完美表示。
  2. 图片化 + 多模态模型描述 (Screenshot & Multimodal Description)

    • 步骤 1:表格截图:在文档预处理阶段,将文档中的表格识别出来,并单独截取为图片。
    • 步骤 2:用 GPT-4o(或其他多模态模型)给图片写一段文字描述:让模型为这张表格图片生成一段详细的文字描述,内容可以包括表格的主题、表头、列名、行名、关键数据点、数据间的关系等。
    • 步骤 3:用这段文字生成向量,加入向量数据库:将这段由多模态模型生成的文字描述作为知识片段,进行向量化并存入向量数据库。
    • 步骤 4:如果这个向量被检索到,再取出这张(原始)图片:当用户问题与某个表格相关时,其对应的文字描述向量会被检索到。此时,系统不仅取回文字描述,更重要的是取回该表格的原始图片(作为元数据关联存储)。
    • 步骤 5:将图片作为参考资料,跟所有的 Prompt 一起给模型:将用户的原始问题和这张表格图片一起提供给一个多模态 LLM,让模型直接看着图片回答问题。
    • 优势:能较好地处理复杂表格,保留视觉结构信息。
    • 成本:涉及多模态模型调用,成本可能较高。
  3. OCR + 结构化解析

    • 使用 OCR 技术提取表格中的文字,并尝试通过算法解析其行列结构,将其转换为结构化数据(如 CSV、JSON)。
    • 这种结构化数据可以被特定工具或代码处理。

3.5. 打通搜索引擎也是一种 RAG

广义上讲,利用搜索引擎(如 Google, Bing)获取外部信息来辅助 LLM 回答,也可以视为一种 RAG。

  • 搜索引擎作为外部资料库:搜索引擎可以访问广阔的互联网实时信息。

  • 向量数据库作为内部资料库:存储的是组织内部的、私有的、或领域特定的知识。

  • 配合使用

    1. 模型判断用户问题是需要通用知识还是内部知识。
    2. 调用搜索引擎或内部向量数据库(或两者都调用)。
    3. 整合检索到的信息,形成增强 Prompt,再由 LLM 生成回答。

3.6. 向量数据库与常规数据库的配合

在实际应用中,RAG 系统往往需要同时与向量数据库和常规关系型数据库(如 MySQL, PostgreSQL)或 NoSQL 数据库进行交互。

  • 向量数据库:通过文本语义相似度进行检索,适用于非结构化知识的查找。
  • 常规数据库:通过 SQL 语句或特定查询语言进行精确检索,适用于结构化数据(如用户信息、订单记录、产品参数等)的查找。
  • 结合方式:LLM 通过 Function Calling 能力,可以生成调用向量数据库的检索请求(通常是转换用户问题为向量),也可以生成 SQL 查询语句去常规数据库中提取数据。然后整合多方数据来回答用户。

4. RAG 应用案例:企业知识库与智能助手

4.1. 企业规章制度助手

  • 知识库构建:将公司的请假制度、报销制度、办公用品申领制度等 PDF 或 Word 文档上传,进行切片和向量化。

    • 切片策略

      • 自动分段:平台(如 Coze)提供的默认按段落切分。可能出现不理想的切分,如将一个条款的编号和内容切开。
      • 自定义分段:例如,可以设置按“一个换行符”切分(如果源文件格式配合),或按特定标记切分。
      • 分段重叠度:设置切片间的重叠字数,以缓解边界切割问题。
  • Agent 配置

    • 在 Agent 中关联此知识库。
    • System Prompt 中强调:“只要遇到与制度相关的问题,都必须严格按照文件知识库中的内容进行回复,切记不可以没有根据地生成内容。”
  • 用户交互与调试

    • 用户提问:“婚假怎么休?”
    • Agent 检索知识库,找到相关切片(如包含婚假天数、申请流程、有效期等信息的段落)。
    • Agent 基于检索到的信息生成回答。
    • 调试:查看 Agent 实际检索到的知识切片、相似度得分(score,0 到 1 之间,越高越相关)。如果回答不准,首先检查检索到的切片是否正确、相关度是否足够高。

4.2. 骑手招聘助手 (进阶案例)

这个案例展示了如何通过优化知识库内容和组织方式来显著提升 RAG 效果,并服务于特定的业务目标。

  • 场景与目标:在线招聘平台(如 BOSS 直聘)上,招聘专员主动与外卖骑手候选人沟通,目标是尽快引导候选人添加微信,以便后续跟进,提高转化率。这是核心业务目标,直接影响知识库的设计思路。

  • 知识库 V1 (基于规章制度的简单处理)

    • 内容来源与处理:直接上传外卖公司的骑手政策、福利待遇、薪资结构等官方文档。
    • 切片方式:例如,每行一个知识点(如“电动车不需要驾驶证”,“首月单价 XX 元”),通过自定义切片规则(如一个换行符切一片)实现。
    • 效果评估:能回答基本问题(如“包吃住吗?”“可以兼职吗?”),但回答往往较为刻板、官方,缺乏吸引力,导致加微信的转化效果一般。相关度得分可能在 0.6-0.8 之间。
  • 知识库 V2 (基于 Top 招聘专员经验,以业务目标为导向重构)

    • 核心思路不是简单罗列规定,而是模拟优秀招聘专员的沟通方式和话术,以达成“加微信”的业务目标。

    • 内容收集与“再创作”

      • 深入观察 Top 招聘专员的真实对话,收集他们针对候选人常见问题的优质回答和高效话术。
      • 将这些经验重构为“问题-回答”对 (FAQ 格式)。这些回答通常更口语化、更具亲和力和引导性,并巧妙地嵌入添加微信的邀约。
      • 例如,对于“可以兼职吗?”,官方回答可能是“不可以”。但 V2 知识库中的回答可能是:“我们主要是全职岗位哈,待遇很不错的!不过每个区域的情况可能略有不同,您可以加我微信 [微信号]​ 详细聊聊您的情况,我帮您具体确认下,说不定有机会呢~ [愉快表情]” 这种以业务成果为导向的知识“再创作”是提升效果的关键。
    • 切片方式:每个精心设计的“问题-回答”对作为一个完整的知识切片。例如,可以通过设置“连续两个换行符”作为切片分隔符,确保问答的完整性。

    • 效果评估

      • 回答更自然、口语化,能有效建立信任并引导候选人添加微信。
      • 显著提升加微信的转化率,其表现能够接近甚至持平 Top 级别的人工招聘专员。
  • 关键洞察 (Insights)

    • 目标驱动的知识库构建:知识库的内容、结构和表述方式,都应紧密围绕最终的业务目标来设计和优化。

    • 用户问题预测与理解:深入了解目标用户(如此处的候选人)通常会问什么问题,以及他们提问的真实意图和潜在顾虑,是构建有效知识库的前提。这通常需要结合业务经验、用户调研、以及系统上线后对真实查询日志的分析来不断完善和扩充问题列表。

    • 知识的“处理”与“再创作”远比单纯的“切片”更重要:对于许多应用场景,尤其是需要达成特定业务目标的场景,简单地对原始文档进行技术性切片往往效果有限。更重要的是对知识内容本身进行符合业务逻辑的提炼、改写、组织和“再创作”(如 V2 中的 FAQ 式对话设计)。

    • 数据闭环与持续迭代

      • 系统上线后,必须建立机制,持续收集用户问题、模型的检索行为(是否召回、召回了哪些片段、相关度得分)以及最终的回答效果。
      • 定期分析这些数据,特别是未检索到知识、检索不准确、或用户反馈不佳的案例。
      • 基于分析结果,不断补充新知识、优化现有知识的表述和组织方式、调整切片策略和元数据标签。这是一个没有终点的优化过程。
    • 场景选择的智慧:优先选择那些沟通内容相对聚焦和规范(窄场景) 、且背后具有显著商业价值或能大幅提升效率的场景进行 RAG 投入,这样更容易获得高投入产出比。

三、总结与展望

Function Calling 和 RAG 是扩展大型语言模型能力、使其能够与外部世界交互并利用特定知识的关键技术。

  • Function Calling 赋予模型调用外部 API 和工具的能力,使其能够执行查询、获取实时信息、操作其他软件等,成为一个智能任务的调度中枢。
  • RAG 通过动态检索外部知识库,为模型提供生成回答所需的上下文,解决了模型知识陈旧、缺乏领域特有知识以及上下文窗口有限的问题。

要成功应用这两种技术,需要:

  1. 清晰定义场景与目标:明确 AI 助手需要完成什么任务,达到什么业务效果。

  2. 精心设计 Prompt 与工具/知识库

    • 对于 Function Calling,需要准确描述工具功能、参数和调用格式。
    • 对于 RAG,需要高质量地整理、清洗、切分知识,并选择合适的 Embedding 模型和向量数据库。
  3. 关注细节与调试:无论是 Function Calling 的参数解析,还是 RAG 的知识检索,都需要细致地调试和优化,确保每一步都按预期工作。

  4. 建立数据闭环与持续迭代机制:通过收集用户反馈和系统运行数据,不断改进 Prompt、工具定义、知识库内容和检索策略。

随着技术的发展,我们可以期待更智能的工具选择、更高效的知识检索方法以及更无缝的人机协作体验。掌握并善用 Function Calling 和 RAG,将能极大地释放大型语言模型在各种实际应用中的潜力。

附录:关键术语表

  • Function Calling:功能调用/工具调用/函数调用
  • RAG (Retrieval-Augmented Generation) :检索增强生成
  • LLM (Large Language Model) :大型语言模型
  • Prompt:提示词,给模型的输入指令和上下文
  • System Prompt:系统级提示词,通常用于设定模型的角色、行为准则、可用工具等
  • User Prompt:用户输入的具体问题或指令
  • Slot Filling:填槽,从非结构化文本中提取结构化信息
  • Chunking:内容切分,将长文本切分为小知识片段
  • Embedding:向量化,将文本转换为数学向量的过程
  • Embedding Model:执行向量化任务的模型
  • Vector Database:向量数据库,用于存储和检索向量
  • Similarity Search:相似度检索,在向量空间中查找与查询向量最相似的向量
  • In-Context Learning (ICL) :上下文学习,模型根据 Prompt 中提供的示例或信息进行学习和推理
  • Metadata:元数据,描述数据的数据,如文档来源、创建日期等
  • Hybrid Search:混合检索,结合向量检索和关键词检索
  • Re-ranking:重排序,对初步检索结果进行更精细的排序
  • Multimodal Model:多模态模型,能处理多种类型输入(如文本、图像)的模型