以下摘要由GPT-4o生成:
自2022年11月ChatGPT发布后,基于Transformer的LLM技术迅速发展,但传统LLM在回答即时性问题时存在局限性,例如无法获取最新信息或容易出现错误回答。为了解决这些问题,Prompt Engineering技术应运而生,用户可以通过提供背景信息来提高AI的回答质量。同时,通过构建检索增强生成(RAG)系统,结合工具调用功能,使AI能够实时访问网络信息或企业内部数据,从而优化回答的准确性与时效性。这一过程涉及数据收集、向量化存储、检索和回答生成等多个步骤。然而,在实践中还面临诸多挑战,如数据处理、相似度检索阈值设置等。未来的分享可能会探讨模块化RAG与Agentic RAG的相关内容。

随着2022年11月chatgpt发布后,以transformer为核心的LLM技术发展火热

我们日常使用Deepseek,Qwen,Kimi等LLM来解答我们疑惑的问题

传统LLM存在的问题的原因

但在最初没有联网搜索功能-WebSearch与RAG的时候,我们可以发现AI在回答我们的问题的时候或多或少会出现幻觉情况。

比如用户提问

  • 1”今天西安天气怎么样”
  • 2”XXX公司XX工具如何使用?”
  • 3”西安2026年5月最新重要新闻都有哪些?”

AI可能回复

  • 1“西安今天天气55度”或者”“你好,我不知道西安今天天气,我的知识库截止时间为2025年5月,你可以询问我2025年5月之前的一些信息””,
  • 2”你好,我不知道XXX公司的具体信息”
  • 3”你好,我无法了解最新的新闻信息,因为我的知识库截止时间为2025年5月”

诸如此类一系列问题的产生,本质上是因为LLM是一个成语接龙工具,它无法实时获取最新的信息,只能基于其训练数据进行回答。

解决的方式就是你可以在询问的时候提供AI可能需要的信息,比如说问题中就添加今天西安的天气,这样AI可以进行词语接龙来与你交流回答,AI就会了解最新信息。

举个例子

1.你问AI“你好,我是mcc”

AI回复“你好,mcc,有什么可以帮助你的吗?”

2.你问AI”你好,我今天准备出去户外玩,今天西安天气31°”

AI回复“今天西安天气有一些小热,温度达到31度,注意避暑以及降温措施”

那么上述的技术被称为Prompt Engineering, 它是一种通过设计提示(Prompt)来引导LLM生成所需输出的技术。一些高阶的Prompt Engineering技术包括

  • 让LLM把大任务拆分为可逐个求解的小任务一步一步执行 (Step By Step)
  • 让LLM在解决任务之前先进行输出思考,基于输出的思考逐步去回答原始问题(CoT)
  • 少样本学习(Few-shot learning)

传统LLM存在的问题的解决方案

我们需要的是AI如何获得最新的网络信息与企业内部的信息然后再回答我们的问题

1.为了解决企业内部数据私有性的问题, 模型在预训练阶段无法训练企业内部私有数据。

我们不可能去先查询到企业内部信息或者最新消息然后去手动喂给AI进行回答。(因果倒置)
我们也不能将整个企业内部文档直接扔给LLM,这会使得LLM 的 Model context爆掉(目前上下文最长的模型是1M)

那么我们就需要在后端程序上进行提前预处理,提前构建知识库,在回答用户问题之前,先进行知识库的知识查询,然后将知识库查询到的相关数据信息拼接到用户的提问的Prompt

再将Prompt喂给AI进行回答,此时AI就可以了解到用户问题的背景知识,从而更好地回答用户问题。

在构建RAG系统时,涉及到四个核心流程

  • 1.数据收集与处理 (提前把企业内部数据库做切块处理)
  • 2.向量转换与存储 (将数据块转换为向量并存储到向量数据库中)
  • 3.向量检索与召回 (根据用户问题的向量检索相关的数据块)
  • 4.回答增强与生成 (将检索到的数据块与用户问题一起输入LLM,生成回答)

经历上述步骤后,你会发现LLM可以回答你关于企业内部信息的问题,但无法解决:

  • “今西安的天气是多少度?”
  • “西安2026年5月最新的重要新闻有哪些?”

2.于是为了解决这类时效性的问题, 我们无法将最新的数据信息提前构建到知识库中去检索

我们采用了工具调用的方式,Function Calling(Tool use),提前给模型提供可能需要的工具(Web-search/get_weather tool)

我们只需要与LLM提前规定好一种交互方式(实际是Post training的结构化输出能力,输出特定要求的json schema)如下

1
2
3
4
5
6
7
8
9
10
11
12
13
{
"type": "function",
"function": {
"name": "NAME",
"description": "DESCRIPTION",
"parameters": {
"type": "object",
"properties": {

}
}
}
}

其中,name、description、parameters.properties 由工具提供方定义,其中 description 描述了工具的具体作用、以及在什么场合需要使用工具,parameters 描述了成功调用工具所需要的具体参数,包括参数类型、参数介绍等;最终,Kimi 大模型会根据 JSON Schema 的定义,生成一个满足定义要求的 JSON Object 作为工具调用的参数(arguments)

Tool use详细技术可以查看[https://platform.kimi.com/docs/guide/use-kimi-api-to-complete-tool-calls]

举个Web-search的例子

来查询最新西安5月重要新闻

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
{
"type": "function", # 约定的字段 type,目前支持 function 作为值
"function": { # 当 type 为 function 时,使用 function 字段定义具体的函数内容
"name": "search", # 函数的名称,请使用英文大小写字母、数据加上减号和下划线作为函数名称
"description": """
通过搜索引擎搜索互联网上的内容。

当你的知识无法回答用户提出的问题,或用户请求你进行联网搜索时,调用此工具。请从与用户的对话中提取用户想要搜索的内容作为 query 参数的值。
搜索结果包含网站的标题、网站的地址(URL)以及网站简介。
""", # 函数的介绍,在这里写上函数的具体作用以及使用场景,以便 Kimi 大模型能正确地选择使用哪些函数
"parameters": { # 使用 parameters 字段来定义函数接收的参数
"type": "object", # 固定使用 type: object 来使 Kimi 大模型生成一个 JSON Object 参数
"required": ["query"], # 使用 required 字段告诉 Kimi 大模型哪些参数是必填项
"properties": { # properties 中是具体的参数定义,你可以定义多个参数
"query": { # 在这里,key 是参数名称,value 是参数的具体定义
"type": "string", # 使用 type 定义参数类型
"description": """
用户搜索的内容,请从用户的提问或聊天上下文中提取。
""" # 使用 description 描述参数以便 Kimi 大模型更好地生成参数
}
}
}
}
}

简单来说LLM使用工具整个过程:

  • 1.第一轮问答:

User:2026年5月西安最新新闻有哪些?

AI :tool use(web_search(query=”2026年5月西安最新新闻”))

User:Tool result(
1.(data:事件1,某某地方20号线通车了,方便出行, URL:www.example.com)

2.(data:事件2,西安未来投资20亿着重发展互联网企业, URL:www.example2.com )

  • 2.拿到工具调用的信息后,第二轮将工具调用的信息以及前面消息全部扔给LLM:

User:2026年5月西安最新新闻有哪些?

AI :tool use(web_search(query=”2026年5月西安最新新闻”))

User:Tool result(
1.(data:事件1,某某地方20号线通车了,方便出行, URL:www.example.com)
2.(data:事件2,西安未来投资20亿着重发展互联网企业, URL:www.example2.com )

AI: 工具已获得信息,西安5月新事件有:1. 某某地方20号线通车了,方便出行
2. 西安未来投资20亿着重发展互联网企业

总结

通过RAG知识库与Tool Use功能,我们可以在发送给LLM 一段prompt的时候,添加问题的背景信息,确保AI回答的时效性与准确性,降低回答的幻觉度。

但实践过程中还有很多问题:

RAG

  • 1.数据收集与处理 (提前把企业内部数据库做切块处理)

    • 文档的处理过程中,有一些是PDF,一些是word,一些是MD文件,我们的程序需要根据文件类型进行不同的处理。
    • 如何进行文档的智能切块,比如说文档信息里面有https://www.example.com,我们的程序不会把这个URL切断。
    • 两个chunk块可能有一定重叠度,overlap的大小如何设置
  • 2.向量转换与存储 (将数据块转换为向量并存储到向量数据库中)

    • 向量转换的维度如何设置,1024还是2048?
    • 存储在pgsql还是milvus专门向量数据库?
    • embedding model如何选择?知识库中文偏多可能需要中文友好型embedding model去做向量转换
  • 3.向量检索与召回 (根据用户问题的向量检索相关的数据块)

    • 向量检索的相似度阈值如何设置?是0.6还是0.5
    • 用户的query描述不清楚如何改写rewrite?
    • 用户的query如何expand 多个方向的问题去并行检索
    • 用户的query是英文,知识库是中文,如何提前做一次转换?
    • 多路并行检索如何去重,如何确保多样性与相关性?MMR
    • 父子块如何检索确保顺序正确
    • 一个知识库A是回答XX工具使用教程,一个知识库B是回答”入职流程“,入职后可能设计到某个工具的使用,用户的问题是“入职流程”,如何处理歧义用途,排序无关项。
    • 如何reranker精排chunk块。
  • 4.回答增强与生成 (将检索到的数据块与用户问题一起输入LLM,生成回答)

    • 检索到chunk A,但是AI没有基于chunk AI去回答, 比如说上下文过长导致了干扰
    • 检索阈值设置太低,导致召回不足,AI是会基于不知道背景信息的情况下去做回答吗?

Tool use

  • 工具调用失败的处理情况?因为模型本质是词语接龙,有可能指令遵循能力不强,会输出非结构化数据
  • 用户提问“最新新闻情况”,但LLM一直不去调用web_search工具,是不是tool description没有描述使用时机?tool parameter description是不是描述存在歧义?
  • 如果工具太多的情况,太多了tool description 加载到模型上下文中,LLM如何快速选择调用哪一个工具呢?

下一期可以分享模块化 RAG 与Agentic RAG,后续可能会有Agent memory,long running task的产生背景与解决方案。