xiaohongshu
xiaohongshu
ai-langchain4j
基于若依-vue-plus框架的LangChain4j AI大模型集成标准规范。全面规范模型配置管理、类型安全服务定义、RAG(检索增强生成)实现、流式响应处理及安全性保障。 触发场景: - 开发智能客服系统、文档问答助手、代码生成工具 - 集成LLM大模型接口(OpenAI、智谱AI、通义千问等) - 实现知识库问答、文档检索、语义搜索功能 - 开发需要流式响应的AI交互界面 - 构建RAG(检索增强生成)应用 触发词:AI集成、LangChain4j、大模型、RAG、流式输出、智谱AI、通义千问、OpenAI、向量检索、嵌入模型、Prompt工程
Full skill instructions
本规范基于LangChain4j框架,为若依-vue-plus项目定义统一的AI大模型集成标准。确保代码的可维护性、安全性和扩展性。
目标:实现模型配置的集中管理和类型安全的AI服务定义。
详细说明:
ChatLanguageModel构建器配置大模型,严禁在代码中硬编码API Keyapplication.yml读取AiServices接口定义模式,将系统提示词(System Message)与业务逻辑解耦实现要点:
@ConfigurationProperties绑定配置// ============ 配置属性类 ============
@Data
@Component
@ConfigurationProperties(prefix = "ai.model")
public class AiProperties {
private String provider; // openai/zhipu/qwen
private String baseUrl;
private String apiKey;
private String modelName;
private Double temperature = 0.7;
private Integer maxTokens = 2000;
private Integer timeout = 60; // 秒
}
// ============ 配置类:动态初始化模型 ============
@Configuration
@EnableConfigurationProperties(AiProperties.class)
public class LangChain4jConfig {
@Bean
public ChatLanguageModel chatLanguageModel(AiProperties properties) {
// 根据provider动态选择模型
return switch (properties.getProvider()) {
case "openai" -> OpenAiChatModel.builder()
.baseUrl(properties.getBaseUrl())
.apiKey(properties.getApiKey())
.modelName(properties.getModelName())
.temperature(properties.getTemperature())
.maxTokens(properties.getMaxTokens())
.timeout(Duration.ofSeconds(properties.getTimeout()))
.logRequests(true)
.logResponses(true)
.build();
case "zhipu" -> ZhipuAiChatModel.builder()
.apiKey(properties.getApiKey())
.modelName(properties.getModelName())
.temperature(properties.getTemperature())
.build();
// 其他模型...
default -> throw new IllegalArgumentException("不支持的模型提供商: " + properties.getProvider());
};
}
// 流式模型配置
@Bean
public StreamingChatLanguageModel streamingChatLanguageModel(AiProperties properties) {
return OpenAiStreamingChatModel.builder()
.baseUrl(properties.getBaseUrl())
.apiKey(properties.getApiKey())
.modelName(properties.getModelName())
.temperature(properties.getTemperature())
.build();
}
}
// ============ 定义类型安全的AI服务接口 ============
public interface AiAssistant {
/**
* 通用对话接口
* @param userMessage 用户消息
* @return AI响应
*/
@SystemMessage("""
你是一个专业的若依框架助手。
- 回答必须简洁、准确、专业
- 使用Java代码示例时,遵循阿里巴巴Java开发规范
- 涉及若依框架时,优先使用框架提供的工具类
""")
String chat(@UserMessage String userMessage);
/**
* 实体提取接口
* @param text 待提取文本
* @return JSON格式的实体列表
*/
@SystemMessage("""
提取以下文本中的关键实体(人名、地名、组织、时间等)。
返回格式:{"entities": [{"type": "人名", "value": "张三"}]}
""")
String extractEntities(@UserMessage String text);
/**
* 代码审查接口
* @param code 待审查的代码
* @return 审查建议
*/
@SystemMessage("""
你是一个资深Java代码审查专家。
审查以下代码,关注:
1. 代码规范性
2. 性能问题
3. 安全隐患
4. 可维护性
返回格式化的审查报告。
""")
String reviewCode(@UserMessage String code);
}
// ============ 服务实现:通过AiServices自动生成代理 ============
@Service
public class AiAssistantService {
private final AiAssistant aiAssistant;
public AiAssistantService(ChatLanguageModel chatLanguageModel) {
this.aiAssistant = AiServices.create(AiAssistant.class, chatLanguageModel);
}
public String chat(String message) {
return aiAssistant.chat(message);
}
}
目标:构建高效的知识库问答系统,实现精准的语义检索。
详细说明:
EmbeddingModel将文本转换为向量表示EmbeddingStore(内存/Redis/Milvus)DocumentSplitter合理切分长文档(推荐500-1000字符/片段)ContentRetriever检索相关片段,支持Top-K和相似度阈值实现要点:
// ============ RAG配置类 ============
@Configuration
public class RagConfig {
/**
* 嵌入模型配置
*/
@Bean
public EmbeddingModel embeddingModel(AiProperties properties) {
return OpenAiEmbeddingModel.builder()
.baseUrl(properties.getBaseUrl())
.apiKey(properties.getApiKey())
.modelName("text-embedding-ada-002") // 或使用国产模型
.build();
}
/**
* 向量存储(示例:内存存储,生产环境建议使用Redis/Milvus)
*/
@Bean
public EmbeddingStore<TextSegment> embeddingStore() {
return new InMemoryEmbeddingStore<>();
}
/**
* 文档切分器
*/
@Bean
public DocumentSplitter documentSplitter() {
return DocumentSplitters.recursive(
500, // 每个片段最大字符数
100, // 片段间重叠字符数(保持上下文连贯)
new OpenAiTokenizer() // Token计数器
);
}
}
// ============ RAG服务实现 ============
@Service
@Slf4j
public class AiRagService {
private final StreamingChatLanguageModel streamingModel;
private final EmbeddingModel embeddingModel;
private final EmbeddingStore<TextSegment> embeddingStore;
private final ContentRetriever contentRetriever;
public AiRagService(StreamingChatLanguageModel streamingModel,
EmbeddingModel embeddingModel,
EmbeddingStore<TextSegment> embeddingStore) {
this.streamingModel = streamingModel;
this.embeddingModel = embeddingModel;
this.embeddingStore = embeddingStore;
// 构建检索器:Top-3相关片段,相似度阈值0.7
this.contentRetriever = EmbeddingStoreContentRetriever.builder()
.embeddingStore(embeddingStore)
.embeddingModel(embeddingModel)
.maxResults(3)
.minScore(0.7)
.build();
}
/**
* 导入文档到知识库
* @param filePath 文档路径
*/
public void ingestDocument(String filePath) {
try {
// 1. 加载文档
Document document = FileSystemDocumentLoader.loadDocument(filePath);
// 2. 切分文档
DocumentSplitter splitter = DocumentSplitters.recursive(500, 100);
List<TextSegment> segments = splitter.split(document);
// 3. 向量化并存储
List<Embedding> embeddings = embeddingModel.embedAll(segments).content();
embeddingStore.addAll(embeddings, segments);
log.info("成功导入文档: {}, 切分为{}个片段", filePath, segments.size());
} catch (Exception e) {
log.error("文档导入失败: {}", filePath, e);
throw new BusinessException("文档导入失败");
}
}
/**
* 流式问答 + RAG
* @param query 用户问题
* @return 流式响应
*/
public Flux<String> streamChatWithRag(String query) {
// 1. 检索相关上下文
List<Content> relevantContents = contentRetriever.retrieve(Query.from(query));
// 2. 构建包含上下文的Prompt
String context = relevantContents.stream()
.map(Content::textSegment)
.map(TextSegment::text)
.collect(Collectors.joining("\n\n"));
String enhancedPrompt = String.format("""
基于以下知识库内容回答用户问题:
【知识库内容】
%s
【用户问题】
%s
【要求】
- 优先使用知识库内容回答
- 如果知识库无相关内容,明确告知用户
- 回答要准确、简洁、专业
""", context, query);
// 3. 流式调用模型
return Flux.create(sink -> {
streamingModel.generate(enhancedPrompt, new StreamingResponseHandler<AiMessage>() {
@Override
public void onNext(String token) {
sink.next(token);
}
@Override
public void onComplete(Response<AiMessage> response) {
sink.complete();
log.info("流式响应完成,Token使用: {}", response.tokenUsage());
}
@Override
public void onError(Throwable error) {
log.error("流式响应错误", error);
sink.error(error);
}
});
});
}
/**
* 普通问答(非流式)
*/
public String chatWithRag(String query) {
List<Content> relevantContents = contentRetriever.retrieve(Query.from(query));
String context = relevantContents.stream()
.map(Content::textSegment)
.map(TextSegment::text)
.collect(Collectors.joining("\n\n"));
Prompt prompt = Prompt.from(
SystemMessage.from("你是知识库问答助手,基于提供的上下文回答问题"),
UserMessage.from("上下文:\n" + context + "\n\n问题:" + query)
);
Response<AiMessage> response = chatLanguageModel.generate(prompt);
return response.content().text();
}
}
// ============ Controller层:SSE流式响应 ============
@RestController
@RequestMapping("/ai/chat")
@Slf4j
public class AiChatController {
@Resource
private AiRagService aiRagService;
/**
* 流式问答接口(SSE)
*/
@GetMapping(value = "/stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public Flux<ServerSentEvent<String>> streamChat(@RequestParam String query) {
return aiRagService.streamChatWithRag(query)
.map(token -> ServerSentEvent.<String>builder()
.data(token)
.build())
.doOnComplete(() -> log.info("流式响应完成: {}", query))
.doOnError(e -> log.error("流式响应异常", e));
}
/**
* 普通问答接口
*/
@PostMapping("/ask")
public R<String> ask(@RequestBody AiChatRequest request) {
String answer = aiRagService.chatWithRag(request.getQuery());
return R.ok(answer);
}
}
目标:优化用户体验,避免长时间等待。
详细说明:
前端对接示例:
// Vue3 + EventSource 接收SSE流式响应
const streamChat = async (query) => {
const eventSource = new EventSource(`/ai/chat/stream?query=${encodeURIComponent(query)}`);
let fullResponse = '';
eventSource.onmessage = (event) => {
const token = event.data;
fullResponse += token;
// 实时更新UI
chatMessage.value = fullResponse;
};
eventSource.onerror = (error) => {
console.error('流式响应错误:', error);
eventSource.close();
ElMessage.error('AI响应异常,请重试');
};
eventSource.addEventListener('done', () => {
eventSource.close();
console.log('流式响应完成');
});
};
目标:提升模型输出质量和稳定性。
详细说明:
Prompt模板示例:
@SystemMessage("""
【角色】你是一个资深Java后端开发专家,熟悉Spring Boot和若依框架
【任务】根据用户需求生成符合规范的代码
【要求】
1. 代码必须遵循阿里巴巴Java开发规范
2. 使用若依框架提供的BaseController、BaseEntity等基类
3. 添加详细的中文注释
4. 包含必要的参数校验和异常处理
【禁止】
- 不要生成硬编码的配置信息
- 不要使用已废弃的API
- 不要省略异常处理代码
【输出格式】
返回完整的Java类代码,包含package、import和类定义
""")
String generateCode(@UserMessage String requirement);
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-spring-boot-starter</artifactId>
<version>0.35.0</version>
</dependency>
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-open-ai</artifactId>
<version>0.35.0</version>
</dependency>
<!-- RAG相关依赖 -->
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-embeddings</artifactId>
<version>0.35.0</version>
</dependency>
ai:
model:
provider: openai # 可选:openai/zhipu/qwen
base-url: https://api.openai.com/v1
api-key: ${AI_API_KEY} # 从环境变量读取
model-name: gpt-4o-mini
temperature: 0.7
max-tokens: 2000
timeout: 60
初始化配置类:参考"规范1"中的LangChain4jConfig
定义AI服务接口:参考"规范1"中的AiAssistant
实现业务逻辑:参考"规范2"中的AiRagService
ruoyi-ai/
├── config/
│ ├── LangChain4jConfig.java # 模型配置
│ ├── RagConfig.java # RAG配置
│ └── AiProperties.java # 配置属性类
├── service/
│ ├── AiAssistant.java # AI服务接口定义
│ ├── AiAssistantService.java # 通用对话服务
│ ├── AiRagService.java # RAG服务
│ └── AiCodeGeneratorService.java # 代码生成服务
├── controller/
│ ├── AiChatController.java # 对话接口
│ └── AiKnowledgeController.java # 知识库管理接口
└── domain/
├── dto/
│ ├── AiChatRequest.java
│ └── AiChatResponse.java
└── vo/
└── TokenUsageVO.java
ruoyi-ai/src/main/java/com/ruoyi/ai/config/LangChain4jConfig.javaruoyi-ai/src/main/java/com/ruoyi/ai/service/AiRagService.javaruoyi-ai/src/main/java/com/ruoyi/ai/controller/AiChatController.javaruoyi-ui/src/views/ai/chat/index.vue(SSE流式接收示例)ruoyi-ai/src/main/resources/application-ai.yml配置管理
服务定义
RAG实现(如果需要)
流式响应
数据安全
输出安全
并发控制
成本控制
缓存优化
错误处理
日志记录
监控告警
单元测试
集成测试
压力测试
A:
InMemoryEmbeddingStore(简单快速)RedisEmbeddingStore(易维护)MilvusEmbeddingStore或PineconeEmbeddingStore(专业向量数据库)A:
A:
// 在Flux中添加超时控制
return aiRagService.streamChatWithRag(query)
.timeout(Duration.ofSeconds(60))
.onErrorResume(TimeoutException.class, e ->
Flux.just("响应超时,请稍后重试")
);
A:
TokenUsageRecorder记录每次调用的Token消耗成本 = (inputTokens * 输入单价 + outputTokens * 输出单价) / 1000A:
.env文件(已加入.gitignore)版本:v1.0.0
最后更新:2026-01-26
维护者:AI开发团队
xiaohongshu
technical spec
product ux expert
database patterns
Conduct multi-agent task orchestration and workflow coordination.
Initialize project with Conductor artifacts (product definition,
Expert in web animations, transitions, and motion design using Framer Motion and CSS
Creates Mermaid and ASCII diagrams for flowcharts, architecture, ERDs, state machines, mindmaps, and more. Use when user mentions diagram, flowchart, mermaid, ASCII diagram, text diagram, terminal diagram, visualize, C4, mindmap, architecture diagram, sequence diagram, ERD, or needs visual docume...
PostgreSQL bindings for H3 hexagonal grid system. Use when working with H3 cells in Postgres, including spatial indexing, geometry/geography integration, and raster analysis.
Context-Driven Development skill for projects using Conductor. Use this skill when you detect a `conductor/` directory in the project, when working on tasks defined in a `plan.md` file, or when the user asks about tracks, specs, or plans. Automatically applies TDD workflow, tracks task completion...
Display project status, active tracks, and next actions
Official Stakpak application containerization standard operating procedure, a step-by-step guidline to properly dockerize applications. This is a rule book curated by the Stakpak Team.
Generate, edit, and beat-sync AI video with leading models in one workspace.
The world's fastest calendar for remote work
Transform Your Design with AI Designer by ImgCreator.ai
Revolutionizing Video Production with AI-Powered Creativity
Extend an image past the frame and let AI fill the new aspect ratio.
Discover your celebrity doppelgänger with StarByFace!
ChainClarity explains 700+ crypto whitepapers in plain English, with layered summaries, comparisons, research tools, alerts, and a $4.99 Pro plan.
Opus.ai: Revolutionize Your Web Experience