1. 概述
处理非结构化内容时,数据提取是个常见难题。我们可以利用 大型语言模型 来解决这个问题。
本文将介绍如何使用 Apache Camel 构建集成管道。我们将通过 LangChain4j 将 HTTP 接口与 LLM 集成,并使用 Quarkus 作为框架来运行所有组件。
我们还会探讨如何创建集成路由,将 LLM 作为组件之一来实现数据结构化。
本文基于 Alexandre Gallice 的文章 Unstructured data extraction with Apache Camel Quarkus and LangChain4j。延伸阅读可参考后续文章 Resolving LangChain4j AI services by interface。
2. 组件介绍
让我们先了解集成管道中涉及的关键组件。
2.1. Quarkus
Quarkus 是一款 Kubernetes 原生的 Java 框架,专为构建和部署云原生应用优化。我们可以用它开发高性能、轻量级的应用程序,这些应用启动快、内存占用低。我们将使用 Quarkus 作为运行集成应用的框架。
2.2. LangChain4j
LangChain4j 是一个 Java 库,专为在应用中集成大型语言模型设计。我们将用它向 LLM 发送提示来结构化内容。 此外,LangChain4j 与 Quarkus 有出色的集成能力。
2.3. OpenAI
OpenAI 是专注于人工智能技术研发的公司。我们可以使用其 GPT 等模型执行语言生成、数据分析和对话 AI 等任务。我们将用它从非结构化内容中提取数据。
2.4. Apache Camel
Apache Camel 是一个简化系统与应用集成的框架。通过定义路由在各类接口间移动和转换数据,我们可以用它构建复杂的工作流。
3. HTTP 源同步响应集成
现在构建一个集成应用:处理包含非结构化内容的 HTTP 请求,提取数据并返回结构化响应。
3.1. 依赖配置
首先添加依赖。引入 jsonpath 依赖 帮助在集成管道中提取 JSON 内容:
<dependency>
<groupId>org.apache.camel.quarkus</groupId>
<artifactId>camel-quarkus-jsonpath</artifactId>
<version>${camel-quarkus.version}</version>
</dependency>
接着添加 camel-quarkus-langchain4j 依赖 支持路由中的 LangChain4j 处理器:
<dependency>
<groupId>org.apache.camel.quarkus</groupId>
<artifactId>camel-quarkus-langchain4j</artifactId>
<version>${quarkus-camel-langchain4j.version}</version>
</dependency>
最后添加 camel-quarkus-platform-http 依赖 支持 HTTP 接口作为路由数据输入:
<dependency>
<groupId>org.apache.camel.quarkus</groupId>
<artifactId>camel-quarkus-platform-http</artifactId>
<version>${camel-quarkus.version}</version>
</dependency>
3.2. 结构化服务
创建 StructurizingService 添加提示逻辑:
@RegisterAiService
@ApplicationScoped
public interface StructurizingService {
String EXTRACT_PROMPT = """
从三反引号分隔的文本中提取患者信息:```{text}```。
customerBirthday 字段格式应为 {dateFormat}。
summary 字段应简明描述患者就诊原因。
预期字段:patientName, patientBirthday, visitReason, allergies, medications。
仅返回数据结构,不包含格式名称。
""";
@UserMessage(EXTRACT_PROMPT)
@Handler
String structurize(@JsonPath("$.content") String text, @Header("expectedDateFormat") String dateFormat);
}
我们添加了 structurize() 方法构建聊天模型请求。使用 EXTRACT_PROMPT 作为提示模板,从输入参数提取非结构化文本并添加到聊天消息中。 同时从第二个方法参数获取日期格式。通过 @Handler 注解标记为 Apache Camel 路由处理器,这样在路由构建器中可直接使用无需指定方法名。
3.3. 路由构建器
使用路由定义集成管道。可通过 XML 配置或 Java DSL 的 RouteBuilder 创建路由。
使用 RouteBuilder 配置管道:
@ApplicationScoped
public class Routes extends RouteBuilder {
@Inject
StructurizingService structurizingService;
@Override
public void configure() {
from("platform-http:/structurize?produces=application/json")
.log("收到 camel-quarkus-http 扩展的文档:${body}")
.setHeader("expectedDateFormat", constant("YYYY-MM-DD"))
.bean(structurizingService)
.transform()
.body();
}
}
在路由配置中,我们添加了 HTTP 接口作为数据源。创建预配置的日期格式头部,并将 StructurizingService bean 附加到路由处理请求,同时将输出体转换为路由响应。
3.4. 路由测试
调用新接口测试非结构化数据处理能力:
@QuarkusTest
class CamelStructurizeAPIResourceLiveTest {
Logger logger = LoggerFactory.getLogger(CamelStructurizeAPIResourceLiveTest.class);
String questionnaireResponses = """
操作员:请提供您的姓名?
患者:你好,我叫 Sara Connor。
//后续对话内容...
""";
@Test
void givenHttpRouteWithStructurizingService_whenSendUnstructuredDialog_thenExpectedStructuredDataIsPresent() throws JsonProcessingException {
ObjectWriter writer = new ObjectMapper().writer();
String requestBody = writer.writeValueAsString(Map.of("content", questionnaireResponses));
Response response = RestAssured.given()
.when()
.contentType(ContentType.JSON)
.body(requestBody)
.post("/structurize");
logger.info(response.prettyPrint());
response
.then()
.statusCode(200)
.body("patientName", containsString("Sara Connor"))
.body("patientBirthday", containsString("1986-07-10"))
.body("visitReason", containsString("申报主车辆事故"));
}
}
我们调用了 structurize 接口,发送患者与医疗服务操作员的对话记录。响应中获取结构化数据后,验证预期字段是否包含患者信息。
同时记录完整响应,查看输出结果:
{
"patientName": "Sara Connor",
"patientBirthday": "1986-07-10",
"visitReason": "申报主车辆事故",
"allergies": "青霉素过敏;对某些非处方抗组胺药有轻微反应",
"medications": "赖诺普利 10mg,复合维生素,偶尔服用维生素D"
}
可见所有内容都被结构化并以 JSON 格式返回。
4. 总结
本文介绍了如何使用 Quarkus、Apache Camel 和 LangChain4j 实现内容结构化。通过 Apache Camel 可接入多种数据源,构建内容转换管道;利用 LangChain4j 实现数据结构化流程并集成到管道中。
✅ 关键优势:
- Camel 提供丰富的集成能力
- LangChain4j 简化 LLM 集成
- Quarkus 确保高性能运行
⚠️ 注意事项:
- 提示工程需根据业务场景优化
- 生产环境需考虑 LLM 调用成本和延迟
这种组合为处理非结构化数据提供了简单粗暴的解决方案,特别适合需要快速构建智能数据管道的场景。