Initial commit: Fintec AI Framework with Agent, RAG, and MCP modules

This commit is contained in:
limqsh
2026-04-27 17:23:58 +08:00
parent a9a1441537
commit 69c5aacdc8
85 changed files with 7143 additions and 0 deletions

54
rag-demo/pom.xml Normal file
View File

@@ -0,0 +1,54 @@
<?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">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.ccb.fintec</groupId>
<artifactId>fintec-framework-parent</artifactId>
<version>1.0.0</version>
</parent>
<artifactId>rag-demo</artifactId>
<dependencies>
<!-- Spring Boot Starter -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- RAG Starter -->
<dependency>
<groupId>com.ccb.fintec</groupId>
<artifactId>fintec-framework-rag-spring-boot-starter</artifactId>
<version>${project.version}</version>
</dependency>
<!-- Agent Starter (提供 ChatClient) -->
<dependency>
<groupId>com.ccb.fintec</groupId>
<artifactId>fintec-framework-agent-spring-boot-starter</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${spring-boot.version}</version>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View File

@@ -0,0 +1,12 @@
package com.ccb.fintec.rag.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class RagDemoApplication {
public static void main(String[] args) {
SpringApplication.run(RagDemoApplication.class, args);
}
}

View File

@@ -0,0 +1,130 @@
package com.ccb.fintec.rag.demo.controller;
import com.ccb.fintec.core.dto.AiResponse;
import com.ccb.fintec.rag.demo.service.RagService;
import org.springframework.web.bind.annotation.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* RAG 演示控制器 - 展示封装后的简化用法
*
* 核心优势:
* 1. 一行代码完成文档入库(支持 PDF、文本、Document 列表)
* 2. 自动使用配置的检索参数topK、相似度阈值
* 3. 支持 RAG + 会话记忆组合
*/
@RestController
@RequestMapping("/api/rag")
public class RagController {
private final RagService ragService;
public RagController(RagService ragService) {
this.ragService = ragService;
}
/**
* 1. 初始化示例数据
*
* 示例POST /api/rag/init
*/
@PostMapping("/init")
public Map<String, Object> init() {
ragService.initSampleData();
Map<String, Object> result = new HashMap<>();
result.put("message", "示例数据已初始化");
result.put("note", "使用了 fintec.ai.rag.* 配置的检索参数");
return result;
}
/**
* 2. 添加文本文档(最简单的方式)
*
* 示例:
* POST /api/rag/add-text
* Body: ["这是第一个文档", "这是第二个文档"]
*/
@PostMapping("/add-text")
public Map<String, Object> addTextDocuments(@RequestBody List<String> texts) {
ragService.addTextDocuments(texts);
Map<String, Object> result = new HashMap<>();
result.put("message", "已添加 " + texts.size() + " 个文本文档");
result.put("note", "自动分块、向量化,无需手动处理");
return result;
}
/**
* 3. RAG 问答 - 自动检索相关文档
*
* 示例GET /api/rag/ask?question=什么是Spring AI?
*/
@GetMapping("/ask")
public Map<String, Object> ask(@RequestParam String question) {
// ✅ 自动使用配置的 topK 和相似度阈值
String answer = ragService.ask(question);
Map<String, Object> result = new HashMap<>();
result.put("question", question);
result.put("answer", answer);
result.put("note", "自动从向量数据库检索相关文档,注入 prompt");
return result;
}
/**
* 4. RAG 问答 + 会话记忆
*
* 示例:
* GET /api/rag/ask-with-memory?conversationId=user123&question=什么是RAG?
* GET /api/rag/ask-with-memory?conversationId=user123&question=它有什么优势?
*/
@GetMapping("/ask-with-memory")
public Map<String, Object> askWithMemory(
@RequestParam String conversationId,
@RequestParam String question) {
// ✅ RAG + 记忆组合,多轮对话保持上下文
String answer = ragService.askWithMemory(conversationId, question);
Map<String, Object> result = new HashMap<>();
result.put("conversationId", conversationId);
result.put("question", question);
result.put("answer", answer);
result.put("note", "RAG 检索 + 会话记忆,多轮对话保持上下文");
return result;
}
/**
* 5. RAG 问答(带元数据)
*
* 示例GET /api/rag/ask-with-metadata?question=什么是向量数据库?
*/
@GetMapping("/ask-with-metadata")
public AiResponse askWithMetadata(@RequestParam String question) {
// ✅ 自动收集 Token 使用量、耗时、检索文档数等元数据
return ragService.askWithMetadata(question);
}
/**
* 6. 健康检查
*/
@GetMapping("/health")
public Map<String, Object> health() {
Map<String, Object> result = new HashMap<>();
result.put("status", "UP");
result.put("service", "RAG Demo");
result.put("features", new String[]{
"文本文档入库(一行代码)",
"PDF 文档入库(一行代码)",
"Document 列表入库",
"RAG 问答(自动检索)",
"RAG + 会话记忆",
"元数据收集Token、耗时、检索文档数",
"可配置检索参数topK、相似度阈值"
});
return result;
}
}

View File

@@ -0,0 +1,102 @@
package com.ccb.fintec.rag.demo.service;
import com.ccb.fintec.core.dto.AiResponse;
import com.ccb.fintec.rag.autoconfigure.template.RagTemplate;
import org.springframework.ai.document.Document;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Map;
/**
* RAG 服务示例 - 展示封装后的简化用法
*
* 核心优势:
* 1. 一行代码完成文档入库PDF、文本、Document 列表)
* 2. 自动使用配置的检索参数topK、相似度阈值
* 3. 支持 RAG + 会话记忆组合
* 4. 元数据包含检索文档数,便于监控
*/
@Service
public class RagService {
private final RagTemplate ragTemplate;
public RagService(RagTemplate ragTemplate) {
this.ragTemplate = ragTemplate;
}
/**
* 方式1直接传入纯文本入库最简单
*/
public void addTextDocuments(List<String> texts) {
for (String text : texts) {
// ✅ 一行代码完成文本入库,自动分块、向量化
ragTemplate.ingest(text, "sample-source");
}
System.out.println("已添加 " + texts.size() + " 个文本文档");
}
/**
* 方式2传入 Document 列表入库(支持自定义元数据)
*/
public void addDocumentList(List<Document> documents) {
// ✅ 一行代码完成 Document 列表入库,自动分块
ragTemplate.ingest(documents);
System.out.println("已添加 " + documents.size() + " 个 Document");
}
/**
* 方式3PDF 文档入库(需要引入 spring-ai-pdf-document-reader 依赖)
*
* 示例ragTemplate.ingest(new ClassPathResource("docs/manual.pdf"));
*/
public void addPdfDocument(org.springframework.core.io.Resource pdfResource) {
// ✅ 一行代码完成 PDF 入库,自动读取、分块、向量化
ragTemplate.ingest(pdfResource);
System.out.println("已添加 PDF 文档");
}
/**
* RAG 问答 - 自动使用配置的 topK 和相似度阈值
*/
public String ask(String question) {
// ✅ 自动从向量数据库检索相关文档,注入 prompt
return ragTemplate.ask(question);
}
/**
* RAG 问答 + 会话记忆
*/
public String askWithMemory(String conversationId, String question) {
// ✅ RAG + 记忆组合,多轮对话保持上下文
return ragTemplate.ask(question, conversationId);
}
/**
* RAG 问答(带元数据)
*/
public AiResponse askWithMetadata(String question) {
// ✅ 自动收集 Token 使用量、耗时、检索文档数等元数据
return ragTemplate.askWithMetadata(question);
}
/**
* 初始化示例数据
*/
public void initSampleData() {
List<String> sampleTexts = List.of(
"Spring AI 是一个用于构建 AI 应用的框架,它提供了统一的 API 来访问不同的 AI 模型。",
"RAG (Retrieval-Augmented Generation) 是一种结合信息检索和文本生成的技术,可以提高 AI 回答的准确性。",
"向量数据库用于存储和检索高维向量数据,常见的向量数据库有 Chroma、Milvus、Pinecone 等。",
"Ollama 是一个本地运行大语言模型的工具,支持 Llama、Mistral 等多种模型。",
"OpenRouter 是一个提供多种 AI 模型访问的 API 服务平台,支持按量付费。"
);
// ✅ 使用新的 ingest 方法,更简洁
for (String text : sampleTexts) {
ragTemplate.ingest(text, "sample-source");
}
System.out.println("已初始化 " + sampleTexts.size() + " 条示例数据");
}
}

View File

@@ -0,0 +1,42 @@
# ============================================
# 服务器配置
# ============================================
server.port=8082
# ============================================
# 模型配置(使用 OpenRouter与 agent-demo 一致)
# ============================================
spring.ai.openai.api-key=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
spring.ai.openai.base-url=https://openrouter.ai/api
spring.ai.openai.chat.options.model=openrouter/free
# Embedding 模型也使用 OpenRouter通过 OpenAI 兼容接口)
spring.ai.openai.embedding.options.model=text-embedding-3-small
# ============================================
# RAG 模块配置
# ============================================
# 文档分块大小(字符数):影响检索精度和上下文长度
fintec.ai.rag.chunk-size=800
# 分块重叠大小:保证上下文连贯性
fintec.ai.rag.chunk-overlap=100
# 检索返回的最相关文档数量
fintec.ai.rag.top-k=5
# 相似度阈值:低于此值的文档不会被使用
fintec.ai.rag.similarity-threshold=0.7
# ============================================
# 重试策略配置(可选)
# ============================================
# fintec.ai.retry.enabled=true
# fintec.ai.retry.max-attempts=3
# fintec.ai.retry.backoff-ms=1000
# ============================================
# 日志配置
# ============================================
logging.level.root=INFO
logging.level.com.ccb.fintec=DEBUG
# 启用 Spring Boot 自动配置的调试信息
debug=true
# 启用更详细的日志
logging.level.org.springframework.boot.autoconfigure=DEBUG