KuiCoding 是一个基于 Spring Boot + LangChain4j + LangGraph4j 的多智能体代码助手。它将意图识别、代码生成/调试、知识检索与 Web 搜索串联成一个可编排的工作流,结合 Redis 会话记忆、PgVector 向量库与 Tavily Web 搜索,为开发者提供可扩展、可自定义的 AI 编程体验。
- 多智能体编排:Intent、Code、Debug、Knowledge、Other、WebSearch 等 Agent 由 LangGraph4j 串联,自动路由用户意图
- LangChain4j 深度集成:统一管理大模型、流式输出、Chat Memory、RAG ContentRetriever
- 流式输出支持:通过
WorkflowService和TextualNormsNode实现实时流式响应,前端可实时接收 AI 生成内容 - Redis 会话记忆:通过自定义
RedisChatMemoryStore持久化多轮对话上下文 - PgVector RAG:把
src/main/resources/content内资料嵌入 PostgreSQL + pgvector,支持检索式回答 - 自动生成/验证代码:
CodeSolveNode同步生成测试用例、代码草案与验证报告 - Tavily Web 搜索:
OtherNode联合网络检索回答开放问题 - 可配置提示词:所有系统 Prompt 以 YAML 形式存放在
src/main/resources/prompt,支持热切换 - REST API:
/kui/chat以 JSON 发送消息,返回结构化意图和回复;/stream/api/workflow支持流式输出 - 可扩展工作流:新增节点、 Agent 或数据源时只需在 Graph 中注册即可
KUI/
├── pom.xml
├── README.md
├── docker指令.md
├── src/
│ ├── main/
│ │ ├── java/com/example/kui/
│ │ │ ├── KuiApplication.java # Spring Boot 入口
│ │ │ ├── agents/ # LangChain4j AI Service 定义
│ │ │ ├── common/dto|enums/ # API DTO & PromptKey
│ │ │ ├── config/ # LangChain4j、Agent、WebSearch 配置
│ │ │ ├── controller/ # REST 控制器
│ │ │ ├── graph/ # LangGraph4j 工作流
│ │ │ │ ├── nodes/ # 各智能体节点
│ │ │ │ ├── state/WorkflowState.java # 状态定义
│ │ │ │ └── workflows/MainWorkflowGraph # 编排入口
│ │ │ ├── memory/RedisChatMemoryStore.java
│ │ │ ├── services/ # 工作流执行服务
│ │ │ │ ├── GraphExecutionService.java
│ │ │ │ └── WorkflowService.java # 流式输出服务
│ │ │ ├── streaming/ # 流式输出模块
│ │ │ │ ├── WorkflowStreamObserver.java # 流式更新观察者接口
│ │ │ │ └── WorkflowStreamRegistry.java # 观察者注册表
│ │ │ └── util/ # Prompt/消息/线程池工具
│ │ └── resources/
│ │ ├── application.yml # 核心配置
│ │ ├── prompt/*.yml # Prompt 模板
│ │ └── content/ # 预置知识库(XCPC 模板等)
│ └── test/java/com/example/kui/ # 单元测试入口
└── target/ # 构建产物
-
agents/
基于@AiService的 LangChain4j Agent,分别负责意图识别 (IntentAgent)、代码生成验证 (CodeAgent)、调试 (DebugAgent)、知识检索 (KnowledgeAgent)、通用聊天 (OtherAgent)、Web 搜索 (WebSearchAgent)。 -
config/AgentConfig:配置 ChatMemory、Redis Memory Provider、PgVector EmbeddingStore、文档加载器。支持kui.content.auto-load-on-startup自动 ingest 文档。LangChainConfig:注册ChatModelListener记录请求/响应。WebSearchConfig:封装 Tavily WebSearchEngine 与 ContentRetriever。
-
graph/state/WorkflowState:扩展MessagesState,记录messages、threadId、intentRecognition。workflows/MainWorkflowGraph:使用 LangGraph4j 构建状态图,从IntentRecognitionNode出发路由到CodeSolveNode/KnowledgeRetrievalNode/DebugNode/OtherNode,最终汇聚到TextualNormsNode进行文本规范化。nodes/*:每个节点对应一个业务 Agent,并负责构造输入/输出。TextualNormsNode负责流式生成最终回复。
-
memory/RedisChatMemoryStore
实现ChatMemoryStore接口,将消息序列化存储到 Redis,支持多线程 ID 以及派生 memory (例如thread-test/thread-chat)。 -
services/GraphExecutionService:接收ChatRequest,组装初始WorkflowState并运行工作流,返回ChatResponse(包含最终回复、识别意图、线程 ID)。WorkflowService:提供流式输出功能,通过ResponseBodyEmitter实现实时推送,注册WorkflowStreamObserver接收TextualNormsNode的流式更新。
-
streaming/WorkflowStreamObserver:流式更新观察者接口,定义onTextualUpdate(content, intent, end)方法。WorkflowStreamRegistry:线程安全的观察者注册表,以threadId为键管理多个会话的观察者。
-
controller/CodeController:暴露 REST API:/kui/chat、/kui/liuyan(访客留言存 Redis)、/kui/search(直接调用 Web 搜索 Agent)。WorkflowController:暴露流式 API:/stream/api/workflow,返回application/x-ndjson格式的流式响应。
-
common/dto
定义ChatRequest(包含单条messages与threadId)、ChatResponse与WorkflowStreamChunk(流式输出数据块,包含 stage、content、intent、threadId、end 等字段)。 -
util/PromptUtil:按PromptKey载入 YAML 片段。ChatMessageUtil:解决 LangChain4j 模板中{{ }}转义问题。ExecutorUtil:提供共享线程池,用于 Code Agent 并发执行测试生成 + 代码求解。PromptKey:描述 prompt 文件及层级 Key。
-
resources/prompt
code-agent.yml、debug-agent.yml、intent-agent.yml、knowledge-agent.yml、other-agent.yml、code-agent.yml等文件保存系统提示,可直接编辑自定义角色。
flowchart TD
%% 核心节点
Start([start]) --> IntentRecognition{IntentRecognition}
%% start到websearch是实线
Start --> WebSearch[WebSearch<br/>(可选)]
%% intentrecognition到其他节点的虚线连接
IntentRecognition -.-> CodeSolve[CodeSolve]
IntentRecognition -.-> CodeDebug[CodeDebug]
IntentRecognition -.-> KnowledgeRetrieval[KnowledgeRetrieval]
IntentRecognition -.-> Other[Other]
%% 所有节点汇聚到文本规范化
WebSearch --> TextNorms[TextNorms]
CodeSolve --> TextNorms
CodeDebug --> TextNorms
KnowledgeRetrieval --> TextNorms
Other --> TextNorms
%% 结束流程
TextNorms --> End([end])
%% 样式设置
style Start fill:#E3F2FD,stroke:#1976D2,stroke-width:2px
style End fill:#E3F2FD,stroke:#1976D2,stroke-width:2px
style IntentRecognition fill:#BBDEFB,stroke:#1565C0,stroke-width:2px
style TextNorms fill:#E8F5E8,stroke:#2E7D32,stroke-width:2px
style WebSearch fill:#FFF3E0,stroke:#EF6C00,stroke-width:2px
style CodeSolve fill:#F3E5F5,stroke:#7B1FA2,stroke-width:2px
style CodeDebug fill:#F3E5F5,stroke:#7B1FA2,stroke-width:2px
style KnowledgeRetrieval fill:#F3E5F5,stroke:#7B1FA2,stroke-width:2px
style Other fill:#F3E5F5,stroke:#7B1FA2,stroke-width:2px
- IntentRecognitionNode:调用
IntentAgent,依据prompt/intent-agent.yml输出PROBLEM_SOLVING / CODE_DEBUGGING / TEMPLATE_RECOMMENDATION / OTHER。 - CodeSolveNode:同一用户问题分别喂给
CodeAgent.chat与CodeAgent.testCases,生成候选答案与测试用例;随后通过codeVerify合并最终回复,保障可执行性。 - DebugNode:面向报错/日志场景,输出问题定位 + 修复建议。
- KnowledgeRetrievalNode:利用
KnowledgeAgent+EmbeddingStoreContentRetriever(PgVector)提供模板/知识推荐。 - OtherNode:先调用
WebSearchAgent获取 Tavily 检索结果,再交给OtherAgent结合本地历史输出自然回答。 - TextualNormsNode:所有业务节点的输出最终汇聚到此节点,通过流式大模型生成规范化文本,并通过
WorkflowStreamObserver实时推送到前端。
如需新增节点,可:
- 在
graph/nodes新增NodeAction; - 注入对应 Agent/资源;
- 在
MainWorkflowGraph中注册节点与路由条件; - 确保新节点输出连接到
TextualNormsNode以支持流式输出。
langchain4j:
open-ai:
chat-model:
base-url: https://dashscope.aliyuncs.com/compatible-mode/v1
api-key: ${DASHSCOPE_CHAT_API_KEY}
model-name: qwen-plus
streaming-chat-model:
base-url: https://dashscope.aliyuncs.com/compatible-mode/v1
api-key: ${DASHSCOPE_CHAT_API_KEY}
model-name: qwen-plus
embedding-model:
base-url: https://dashscope.aliyuncs.com/compatible-mode/v1
api-key: ${DASHSCOPE_EMBED_API_KEY}
model-name: text-embedding-v4
community:
redis:
host: localhost
port: 6379
spring:
datasource:
url: jdbc:postgresql://localhost:5432/embedding
username: postgres
password: root
langchain4j:
web-search-engine:
tavily:
api-key: ${TAVILY_API_KEY}
max-results: 3
kui:
content:
auto-load-on-startup: true # 启动时自动 ingest resources/content
base-path: content
logging.level:
dev.langchain4j: debug
com.example.kui: info关键说明:
- 模型配置:当前默认使用阿里云通义千问兼容接口,可按需替换为 OpenAI、DeepSeek、Minimax 等,只需改
base-url、model-name和api-key。 - Redis:用于
ChatMemoryStore。务必保证实例已启动。 - PostgreSQL + pgvector:
AgentConfig.pgVectorEmbeddingStore()指向embedding_store表,嵌入维度需与模型一致(默认 1024)。 - Tavily:若无需 Web 搜索,可移除
webSearchEngineBean 或留空 API Key。 - 内容自动加载:
kui.content.auto-load-on-startup=true时,会递归加载resources/content/**/*,通过EmbeddingStoreIngestor写入 pgvector(chunk 5000 字符、重叠 50)。
- Java 17+
- Maven 3.9+
- Redis 6+
- PostgreSQL 14+(已安装 pgvector 扩展)
- Tavily API Key(可选)
git clone https://github.com/<your-org>/kui.git
cd kui
mvn clean package-- PostgreSQL
CREATE DATABASE embedding;
\c embedding
CREATE EXTENSION IF NOT EXISTS vector;
CREATE TABLE IF NOT EXISTS embedding_store (
id bigserial PRIMARY KEY,
embedding vector(1024),
text text,
metadata jsonb
);启动 Redis,并确认 application.yml 中的 host/port 正确。
- 在
application.yml中填入模型 / Tavily / 数据库 / Redis 信息,或通过环境变量覆盖。 - 将知识文档放入
src/main/resources/content(支持 Markdown、文本、PDF*)。
mvn spring-boot:run
# 或
java -jar target/KUI-0.0.1-SNAPSHOT.jar启动后访问 POST http://localhost:8080/kui/chat 或 POST http://localhost:8080/stream/api/workflow。
- 方法:POST
- 请求体
{
"threadId": "optional-thread-id",
"messages": {
"content": "请给出二叉树层序遍历模板",
"role": "user"
}
}- 响应
{
"message": "....AI 回复....",
"intent": "TEMPLATE_RECOMMENDATION",
"threadId": "auto-generated-or-reused"
}说明:如果不传 threadId,服务会自动生成并在响应中返回;客户端需保存该 ID 才能继续上下文。
- 直接触发
WebSearchAgent,返回 Tavily 检索结合 LLM 生成的答案。
- 方法:POST
- Content-Type:
application/json - Accept:
application/x-ndjson - 请求体:同
/kui/chat
{
"threadId": "optional-thread-id",
"messages": {
"content": "请给出二叉树层序遍历模板",
"role": "user"
}
}- 响应:流式返回
WorkflowStreamChunkJSON 对象,每行一个 JSON,以\n分隔
{"stage":"IntentRecognitionNode","node":"IntentRecognitionNode","content":"","intent":"TEMPLATE_RECOMMENDATION","threadId":"xxx","end":false,"timestamp":1234567890,"metadata":null}
{"stage":"KnowledgeRetrievalNode","node":"KnowledgeRetrievalNode","content":"检索到相关模板...","intent":"TEMPLATE_RECOMMENDATION","threadId":"xxx","end":false,"timestamp":1234567891,"metadata":null}
{"stage":"TextualNormsNode","node":"TextualNormsNode","content":"以下是","intent":"TEMPLATE_RECOMMENDATION","threadId":"xxx","end":false,"timestamp":1234567892,"metadata":null}
{"stage":"TextualNormsNode","node":"TextualNormsNode","content":"以下是二叉树","intent":"TEMPLATE_RECOMMENDATION","threadId":"xxx","end":false,"timestamp":1234567893,"metadata":null}
{"stage":"TextualNormsNode","node":"TextualNormsNode","content":"以下是二叉树层序遍历模板...","intent":"TEMPLATE_RECOMMENDATION","threadId":"xxx","end":true,"timestamp":1234567894,"metadata":null}说明:TextualNormsNode 阶段会持续推送增量内容(end=false),直到最后一条 end=true 表示流式传输完成。前端可实时渲染实现打字机效果。
- 简单留言接口,
POST文本字符串,服务会写入 Redis List,可用于收集用户反馈。
- 前端请求:客户端发送 POST 请求到
/stream/api/workflow,Accept 头设置为application/x-ndjson。 - 服务端初始化:
WorkflowService.stream()创建ResponseBodyEmitter,并注册一个WorkflowStreamObserver到WorkflowStreamRegistry(以threadId为键)。 - 工作流执行:异步启动 LangGraph4j 工作流,各业务节点(CodeSolve、Debug、KnowledgeRetrieval 等)执行完毕后,状态流转到
TextualNormsNode。 - 流式生成:
TextualNormsNode调用StreamingChatModel.chat(),注册StreamingChatResponseHandler。 - 实时推送:大模型每次返回部分响应时,触发
onPartialResponse(),TextualNormsNode通过WorkflowStreamRegistry.get(threadId)获取 observer,调用onTextualUpdate(content, intent, false)。 - 数据封装:observer 实现(匿名 Lambda)将内容封装为
WorkflowStreamChunk,通过ResponseBodyEmitter.send()发送到前端。 - 前端渲染:前端通过 EventSource 或 Fetch Stream API 接收 NDJSON 流,实时更新 UI,实现打字机效果。
关键组件:
WorkflowStreamRegistry:线程安全的观察者注册表,支持多会话并发。WorkflowStreamObserver:观察者接口,解耦节点与传输层。TextualNormsNode:统一文本规范化节点,所有业务输出最终在此流式生成。
- 文档存放在
src/main/resources/content,支持多级目录(当前包含 XCPC 模板/白皮书等资料)。 - 启动时若
kui.content.auto-load-on-startup=true,AgentConfig#embeddingStore会:- 递归扫描
contentBasePath; - 使用
ClassPathDocumentLoader加载文档; - 使用
DocumentSplitters.recursive(5000, 50)分割; - 写入
PgVectorEmbeddingStore。
- 递归扫描
KnowledgeAgent通过EmbeddingStoreContentRetriever检索,minScore=0.3、maxResults=30,再交给模型生成回答。
如需自定义:
- 可改
contentBasePath指向外部目录; - 调整 chunk 大小/重叠;
- 替换为其他向量存储(Milvus、Pinecone 等)。
- 在
src/main/resources/prompt/xxx-agent.yml中新增条目。 - 修改
PromptKey枚举,定义文件名与 YAML 路径。 - 注入
PromptUtil.getPrompt(PromptKey.XXX)使用。
@AiService(
wiringMode = EXPLICIT,
chatModel = "openAiChatModel",
streamingChatModel = "openAiStreamingChatModel",
chatMemory = "chatMemory",
chatMemoryProvider = "chatMemoryProvider"
)
public interface ReviewAgent {
@SystemMessage("{{systemPrompt}}")
String review(@MemoryId String memoryId,
@UserMessage String message,
@V("systemPrompt") String prompt);
}@Component
public class ReviewNode implements NodeAction<WorkflowState> {
@Autowired ReviewAgent reviewAgent;
@Autowired PromptUtil promptUtil;
@Override
public Map<String, Object> apply(WorkflowState state) {
String threadId = state.threadId().orElseThrow();
String message = state.lastMessage().map(Object::toString).orElse("");
String reply = reviewAgent.review(threadId, message, promptUtil.getPrompt(PromptKey.REVIEW));
return Map.of("messages", reply);
}
}并在 MainWorkflowGraph 注册节点/路由。
- 运行
mvn test验证基础依赖。 - 提升日志级别
logging.level.com.example.kui=debug可查看工作流每步输出。 LangChainConfig#chatModelListener已打印请求/响应,可结合logback输出到文件。
- 框架:Spring Boot 3.5.x、LangChain4j 1.0.1-beta6、LangGraph4j 1.6.0-beta6 ?- 数据存储:Redis(会话记忆)、PostgreSQL + pgvector(嵌入)
- 模型/服务:通义千问 DashScope(兼容 OpenAI API),Tavily WebSearch
- Reactive:Spring WebFlux、LangChain4j Reactor(支持流式输出)
- 工具:Lombok、SnakeYAML、Jackson、PdfBox(用于解析 PDF 文档)
- 使用 Git 分支流:
feature/<name>→ PR - 代码规范:开启 IDE CheckStyle/Spotless(可自行添加),保持空指令
- 提交前至少运行一次
mvn clean verify - Prompt 变更请在 PR 描述中注明,以便评审
若无特殊说明,项目默认遵循仓库根目录中的许可证(可按团队要求更新)。
KuiCoding —— 让 LangChain4j + LangGraph4j 的多智能体编码体验更简单。🚀

