什么是 RAG?
检索增强生成(Retrieval-Augmented Generation, RAG) 是一种结合了检索和生成两种关键技术的机器学习方法。这种方法在自然语言处理任务中特别有效,例如对话系统和问答系统。
RAG 的关键组件
- 检索:
- • RAG 首先从大型数据集或知识库中检索与用户查询相关的文档或数据。
- • 通常使用信息检索技术,如向量搜索或关键词匹配。
- 生成:
- • 在检索到相关信息后,模型生成一个响应或答案,结合检索到的内容和原始查询。
- • 通常使用生成模型,如 GPT(生成式预训练变换器)或类似的架构。
RAG 的工作原理
- 输入:用户提交查询或问题。
- 检索阶段:
- 系统从大型文档库中搜索与查询最相关的信息片段。
- 生成阶段:
- 检索到的信息被输入到生成模型中,生成一个结合查询和检索内容的连贯响应。
- 输出:最终响应返回给用户。
RAG 的优势
- 提高准确性:通过结合检索和生成,RAG 可以提供更准确和上下文相关的答案。
- 知识利用:它可以利用大量外部知识,适用于复杂查询,而简单的生成模型可能无法处理。
- 动态响应:系统可以生成不仅基于预定义响应,还针对特定用户查询和检索信息定制的答案。
应用场景
- • 聊天机器人:RAG 可用于创建提供准确且上下文相关答案的对话代理。
- • 问答系统:它在需要基于大型数据集回答问题的系统中表现出色,例如客户支持或教育平台。
- • 内容生成:RAG 可以通过检索相关信息并将其整合为连贯的叙述来辅助内容生成。
为什么检索增强生成很重要?
大型语言模型(LLM)是驱动智能聊天机器人和其他自然语言处理(NLP)应用的关键人工智能技术。目标是创建能够通过参考权威知识源回答用户问题的机器人。然而,LLM 技术的不确定性可能导致以下问题:
- 提供虚假信息。
- 提供过时或通用信息,而用户需要具体、当前的响应。
- 从非权威来源生成响应。
- 由于术语混淆,不同训练源使用相同术语讨论不同事物,可能导致不准确的响应。
RAG 是解决这些挑战的一种方法。它将 LLM 重定向到从预定的权威知识源中检索相关信息。组织对生成的文本输出有更多控制,用户可以了解 LLM 如何生成响应。
检索增强生成的工作原理
在没有 RAG 的情况下,LLM 根据其训练数据或已知信息生成响应。RAG 引入了一个信息检索组件,该组件使用用户输入从新数据源中提取信息。用户查询和相关信息都被提供给 LLM。LLM 使用新知识和其训练数据来生成更好的响应。
创建外部数据
LLM 原始训练数据集之外的新数据称为外部数据。它可以来自多个数据源,如 API、数据库或文档库。数据可以以各种格式存在,如文件、数据库记录或长文本。另一种称为嵌入语言模型的 AI 技术将数据转换为数字表示并存储在向量数据库中。此过程创建了一个生成式 AI 模型可以理解的知识库。
检索相关信息
下一步是执行相关性搜索。用户查询被转换为向量表示并与向量数据库匹配。例如,考虑一个可以回答组织人力资源问题的智能聊天机器人。如果员工搜索“我有多少年假?”,系统将检索年假政策文件以及员工过去的休假记录。这些特定文档将被返回,因为它们与员工输入的内容高度相关。相关性通过数学向量计算和表示来建立。
增强 LLM 提示
接下来,RAG 模型通过添加上下文中的检索相关数据来增强用户输入(或提示)。此步骤使用提示工程技术来有效地与 LLM 通信。增强的提示允许大型语言模型生成准确的用户查询答案。
更新外部数据
接下来的问题可能是——如果外部数据过时了怎么办?为了保持检索的当前信息,异步更新文档并更新文档的嵌入表示。您可以通过自动实时过程或定期批处理过程来完成此操作。这是数据分析中的常见挑战——可以使用不同的数据科学方法进行变更管理。
什么是 LangChain?
LangChain 是一个为开发使用大型语言模型(LLM)的应用程序而设计的框架。它提供了工具和抽象,简化了将 LLM 集成到各种工作流中的过程,使开发者能够创建更复杂和功能丰富的应用程序。
LangChain 的关键特性
- 1. 模块化架构:
- • LangChain 采用模块化方法,允许开发者根据需要轻松插入不同的组件(如模型、检索器和链)。
- 2. 链:
- • 链是对不同组件(如 LLM、API、数据库)的调用序列,可以组合起来执行复杂任务。例如,链可能首先检索相关文档,然后基于这些文档生成响应。
- 3. 检索:
- • LangChain 提供了与各种检索机制的集成,允许应用程序从不同数据源(如数据库、API 或外部知识库)中获取相关信息。
- 4. 提示管理:
- • 该框架包括管理提示的实用程序,这对于引导 LLM 生成所需输出至关重要。开发者可以轻松定义和自定义提示。
- 5. 记忆:
- • LangChain 可以维护对话记忆,允许应用程序记住过去的交互,并在持续对话中提供更相关的响应。
- 6. 与其他工具的集成:
- • LangChain 可以连接各种数据存储、Web API 和其他工具,使开发者能够构建丰富的交互式应用程序。
- 7. 可扩展性:
- • 该框架设计为可扩展,允许开发者高效处理更大的数据集和更复杂的查询。
代码实现
使用 LangChain 在 Spring Boot Java 中实现 RAG 应用程序。
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.2.1</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>rag</artifactId>
<properties>
<java.version>17</java.version>
<langchain4j.version>0.23.0</langchain4j.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j</artifactId>
<version>${langchain4j.version}</version>
</dependency>
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-open-ai</artifactId>
<version>${langchain4j.version}</version>
</dependency>
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-embeddings</artifactId>
<version>${langchain4j.version}</version>
</dependency>
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-embeddings-all-minilm-l6-v2</artifactId>
<version>${langchain4j.version}</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
Controller
@Controller
@RequiredArgsConstructor
public class SBotController {
private final SBotService sBotService;
@PostMapping("/ask")
public ResponseEntity<String> ask(@RequestBody String question) {
try {
return ResponseEntity.ok(sBotService.askQuestion(question));
} catch (Exception e) {
return ResponseEntity.badRequest().body("Sorry, I can't process your question right now.");
}
}
}
Service
@Service
@RequiredArgsConstructor
@Slf4j
public class SBotService {
private final ConversationalRetrievalChain chain;
public String askQuestion(String question) {
log.debug("======================================================");
log.debug("Question: " + question);
String answer = chain.execute(question);
log.debug("Answer: " + answer);
log.debug("======================================================");
return answer;
}
}
@RequiredArgsConstructor
@Slf4j
public class EmbeddingStoreLoggingRetriever implements Retriever<TextSegment> {
private final EmbeddingStoreRetriever retriever;
@Override
public List<TextSegment> findRelevant(String text) {
List<TextSegment> relevant = retriever.findRelevant(text);
relevant.forEach(segment -> {
log.debug("=======================================================");
log.debug("Found relevant text segment: {}", segment);
});
return relevant;
}
}
@Configuration
@RequiredArgsConstructor
@Slf4j
public class LangChainConfiguration {
@Value("${langchain.api.key}")
private String apiKey;
@Value("${langchain.timeout}")
private Long timeout;
private final List<Document> documents;
@Bean
public ConversationalRetrievalChain chain() {
EmbeddingModel embeddingModel = new AllMiniLmL6V2EmbeddingModel();
EmbeddingStore<TextSegment> embeddingStore = new InMemoryEmbeddingStore<>();
EmbeddingStoreIngestor ingestor = EmbeddingStoreIngestor.builder()
.documentSplitter(DocumentSplitters.recursive(500, 0))
.embeddingModel(embeddingModel)
.embeddingStore(embeddingStore)
.build();
log.info("Ingesting Spring Boot Resources ...");
ingestor.ingest(documents);
log.info("Ingested {} documents", documents.size());
EmbeddingStoreRetriever retriever = EmbeddingStoreRetriever.from(embeddingStore, embeddingModel);
EmbeddingStoreLoggingRetriever loggingRetriever = new EmbeddingStoreLoggingRetriever(retriever);
/*MessageWindowChatMemory chatMemory = MessageWindowChatMemory.builder()
.maxMessages(10)
.build();*/
log.info("Building ConversationalRetrievalChain ...");
ConversationalRetrievalChain chain = ConversationalRetrievalChain.builder()
.chatLanguageModel(OpenAiChatModel.builder()
.apiKey(apiKey)
.timeout(Duration.ofSeconds(timeout))
.build()
)
.promptTemplate(PromptTemplate.from(PROMPT_TEMPLATE_2))
//.chatMemory(chatMemory)
.retriever(loggingRetriever)
.build();
log.info("Spring Boot knowledge base is ready!");
return chain;
}
}
总结
RAG 是一种强大的方法,通过结合信息检索和文本生成的优势,增强了 AI 系统的能力。
没有回复内容