1. 引言:为什么金融场景需要 LangChain4j
金融行业是 LLM 落地最积极、也最谨慎的领域之一。一方面,客服问答、投研摘要、合同要素抽取、合规审查等场景天然适合大模型;另一方面,金融业务对准确性、可追溯性、数据安全与合规的要求远高于一般行业。
LangChain4j 是 Java 生态中成熟的 LLM 应用开发框架,它把「模型接入、提示词模板、工具调用、RAG 检索、对话记忆、结构化输出」等能力封装成统一的 Java API,非常适合已经以 Spring Boot 为主栈的金融系统做增量集成。
本文以一个「金融智能助手」为例,演示如何用 LangChain4j 搭建包含知识库问答、工具调用(查利率/查账户)、结构化信息抽取的完整链路,并给出金融场景下的工程与合规实践建议。
2. 金融场景的能力拆解
在动手写代码前,先把业务需求拆成可落地的技术能力:
| 业务场景 | 技术能力 | LangChain4j 对应组件 |
|---|---|---|
| 产品条款问答 | RAG 检索增强 | EmbeddingStore + ContentRetriever |
| 账户/利率查询 | 工具调用(Function Calling) | @Tool + AiServices |
| 合同要素抽取 | 结构化输出 | AiServices 返回 POJO |
| 多轮业务咨询 | 对话记忆 | ChatMemory |
| 合规留痕 | 日志与审计 | 自定义 ChatModelListener |
金融场景的第一原则是:模型只做理解与生成,事实数据必须来自可信系统。因此工具调用与 RAG 是核心,而不是让模型「凭记忆回答」。
3. 环境准备与依赖
以 Maven 为例,引入 LangChain4j 核心与 OpenAI 兼容模型(国内多数金融私有化部署都提供 OpenAI 兼容接口):
<properties>
<langchain4j.version>1.0.0</langchain4j.version>
</properties>
<dependencies>
<!-- 核心 API -->
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j</artifactId>
<version>${langchain4j.version}</version>
</dependency>
<!-- OpenAI 兼容模型接入 -->
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-open-ai</artifactId>
<version>${langchain4j.version}</version>
</dependency>
<!-- 本地向量库(示例用内存版,生产可换 Milvus/PgVector) -->
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-embeddings-all-minilm-l6-v2</artifactId>
<version>${langchain4j.version}</version>
</dependency>
</dependencies>
版本说明:LangChain4j 在 1.x 之后 API 有较大调整(如
ChatLanguageModel更名为ChatModel)。请以项目实际引入的版本为准,本文示例基于 1.0.x 系列。
4. 模型接入:统一封装与安全配置
金融系统通常不允许把密钥写死在代码里,也不允许业务数据直连公网模型。建议统一封装一个模型 Bean:
@Configuration
public class LlmConfig {
@Bean
public ChatModel chatModel(
@Value("${llm.base-url}") String baseUrl,
@Value("${llm.api-key}") String apiKey,
@Value("${llm.model-name}") String modelName) {
return OpenAiChatModel.builder()
.baseUrl(baseUrl) // 指向行内网关或私有化部署地址
.apiKey(apiKey) // 从配置中心/密钥管理服务注入
.modelName(modelName)
.temperature(0.2) // 金融场景降低随机性
.timeout(Duration.ofSeconds(60))
.logRequests(true)
.logResponses(true)
.build();
}
@Bean
public EmbeddingModel embeddingModel() {
return new AllMiniLmL6V2EmbeddingModel();
}
}
关键点:
temperature调低(0.1~0.3),减少「自由发挥」;baseUrl指向行内 LLM 网关,便于统一鉴权、限流与审计;- 开启请求/响应日志,但日志脱敏后再落盘。
5. 知识库问答:RAG 检索增强
金融产品条款、监管文件、内部制度更新频繁,必须用 RAG 让模型「看着资料回答」。
5.1 文档切分与入库
@Service
public class KnowledgeBaseService {
private final EmbeddingStore<TextSegment> store;
private final EmbeddingModel embeddingModel;
public KnowledgeBaseService(EmbeddingModel embeddingModel) {
this.embeddingModel = embeddingModel;
this.store = new InMemoryEmbeddingStore<>();
}
/** 导入制度/条款文档 */
public void ingest(String docId, String content) {
DocumentSplitter splitter = DocumentSplitters.recursive(500, 80);
Document document = Document.from(content,
Metadata.from(Map.of("docId", docId, "type", "policy")));
List<TextSegment> segments = splitter.split(document);
List<Embedding> embeddings = embeddingModel.embedAll(segments).content();
store.addAll(embeddings, segments);
}
public EmbeddingStore<TextSegment> store() {
return store;
}
}
切分参数建议:金融条款语义密度高,maxSegmentSize 取 400~600 字符,overlap 保留 10%~15%,避免条款被切断导致语义丢失。
5.2 构建带检索的助手
@Configuration
public class AssistantConfig {
@Bean
public Assistant assistant(ChatModel chatModel,
KnowledgeBaseService kbService,
EmbeddingModel embeddingModel) {
ContentRetriever retriever = EmbeddingStoreContentRetriever.builder()
.embeddingStore(kbService.store())
.embeddingModel(embeddingModel)
.maxResults(4)
.minScore(0.7)
.build();
return AiServices.builder(Assistant.class)
.chatModel(chatModel)
.contentRetriever(retriever)
.chatMemory(MessageWindowChatMemory.withMaxMessages(10))
.build();
}
}
minScore 是金融场景的重要闸门:低于阈值说明知识库没有可靠依据,此时应让助手明确回答「未找到相关条款」,而不是编造。
6. 工具调用:让模型访问可信业务系统
利率、账户余额、汇率这类实时且强一致的数据,必须通过工具调用查询真实系统。
6.1 定义工具
@Component
public class FinanceTools {
private final RateService rateService;
private final AccountService accountService;
public FinanceTools(RateService rateService, AccountService accountService) {
this.rateService = rateService;
this.accountService = accountService;
}
@Tool("根据产品代码查询当前年化利率,例如产品代码 LC2024")
public String queryRate(@P("产品代码") String productCode) {
BigDecimal rate = rateService.currentRate(productCode);
return rate == null
? "未查询到该产品的利率信息"
: "产品 " + productCode + " 当前年化利率为 " + rate + "%";
}
@Tool("查询指定客户编号的账户余额,仅返回脱敏结果")
public String queryBalance(@P("客户编号") String customerId) {
BigDecimal balance = accountService.balanceOf(customerId);
return "客户 " + mask(customerId) + " 的账户余额为 " + balance + " 元";
}
private String mask(String id) {
return id.length() <= 4 ? "****" : id.substring(0, 2) + "****" + id.substring(id.length() - 2);
}
}
6.2 绑定到助手
public interface FinanceAssistant {
@SystemMessage("""
你是某银行的智能金融助手。
规则:
1. 涉及利率、余额、汇率等实时数据,必须调用工具查询,禁止凭记忆回答;
2. 不提供任何投资建议、收益承诺或风险判断;
3. 无法确认的信息,明确告知用户并建议转人工;
4. 回答简洁,使用中文。
""")
String chat(@MemoryId String sessionId, @UserMessage String message);
}
FinanceAssistant assistant = AiServices.builder(FinanceAssistant.class)
.chatModel(chatModel)
.tools(new FinanceTools(rateService, accountService))
.chatMemoryProvider(id -> MessageWindowChatMemory.withMaxMessages(20))
.build();
@SystemMessage 中的约束是金融场景的「护栏」,比在用户提示词里反复强调更可靠。
7. 结构化输出:合同与凭证要素抽取
金融业务大量存在「非结构化文本 → 结构化字段」的需求,例如合同要素抽取。LangChain4j 支持直接返回 POJO:
public record ContractInfo(
String contractNo,
String partyA,
String partyB,
String amount,
String signDate,
String term
) {}
public interface ContractExtractor {
@SystemMessage("从合同文本中抽取要素。字段缺失时返回 null,不要推测。")
@UserMessage("合同文本如下:\n{{text}}")
ContractInfo extract(@V("text") String text);
}
ContractExtractor extractor = AiServices.create(ContractExtractor.class, chatModel);
ContractInfo info = extractor.extract(contractText);
工程建议:
- 抽取结果必须做二次校验(金额格式、日期合法性、合同编号规则);
- 关键字段建议用规则引擎或正则兜底,模型结果仅作候选;
- 抽取失败或置信度低时进入人工复核队列。
8. 整体架构与调用链路
9. 金融场景的工程与合规实践
9.1 数据安全
- 私有化部署优先:敏感数据不出行内网络,模型走内网网关;
- 输入脱敏:身份证、卡号、手机号在进入模型前替换为占位符;
- 输出过滤:对生成内容做敏感词与合规规则校验。
9.2 可追溯性
通过 ChatModelListener 记录每次调用的提示词、模型版本、检索命中的文档 ID,形成完整审计链:
public class AuditListener implements ChatModelListener {
@Override
public void onResponse(ChatModelResponseContext ctx) {
auditLog.record(
ctx.request().messages(),
ctx.response().aiMessage(),
ctx.response().tokenUsage()
);
}
}
9.3 稳定性与成本
- 设置超时与重试上限,避免长尾请求拖垮线程池;
- 对高频问题做语义缓存,降低模型调用量;
- 用
maxResults与minScore控制检索规模,减少 token 消耗。
9.4 人机协同
金融场景不建议全自动闭环。对于涉及资金、合同、风险判断的结论,应设计「AI 建议 + 人工确认」的流程,并保留人工干预入口。
10. 常见问题与排查
| 问题现象 | 可能原因 | 处理方式 |
|---|---|---|
| 回答与条款不符 | 检索未命中或 minScore 过低 | 提高阈值、优化切分粒度 |
| 工具未被调用 | 工具描述不清或模型能力不足 | 完善 @Tool 描述,换更强模型 |
| 结构化输出解析失败 | 字段类型不匹配 | 使用 record + 明确字段说明 |
| 响应慢 | 检索结果过多、上下文过长 | 限制 maxResults,压缩历史消息 |
| 偶发超时 | 模型侧限流 | 增加重试与降级策略 |
11. 总结
用 LangChain4j 对接金融领域应用,核心不是「把模型接进来」,而是围绕可信数据、明确边界、可审计链路做工程化设计:
- 用 RAG 让回答有据可依,用
minScore守住「不知道就说不知道」; - 用工具调用把实时数据交给业务系统,模型只负责理解与表达;
- 用结构化输出承接抽取类任务,并配合规则校验;
- 用系统提示词、脱敏、审计日志构建合规护栏。
把这四件事做扎实,LangChain4j 就能在金融场景中稳定落地,而不是停留在 Demo 阶段。
转载自 CSDN-专业IT技术社区
原文链接:https://blog.csdn.net/zhangchen124/article/details/169068699



