大家好我是Java1234_小锋老师分享一套锋哥原创的基于LangChain4j的RAG医疗健康知识智能问答系统(SpringBoot4Vue3Ollama)项目介绍随着人工智能与大语言模型技术的快速发展智能问答系统在医疗健康领域展现出广阔的应用前景。然而通用大语言模型在回答医疗健康类问题时普遍存在知识更新滞后、易产生“幻觉”以及缺乏可信来源等问题难以直接应用于对准确性要求较高的医疗健康咨询场景。检索增强生成Retrieval-Augmented GenerationRAG技术通过将外部知识库检索与大语言模型生成相结合能够在不重新训练模型的前提下显著提升回答的准确性与可追溯性为构建可信的医疗健康知识问答系统提供了有效途径。本文设计并实现了一个基于LangChain4j的RAG医疗健康知识智能问答系统。系统后端采用Spring Boot 4框架以LangChain4j作为RAG应用编排框架通过Ollama在本地部署qwen3对话模型与qwen3-embedding嵌入模型使用Redis向量数据库存储文档向量并完成相似度检索业务数据持久化采用MySQL与MyBatis-Plus并通过Spring Security与JWT实现无状态的认证授权。前端采用Vue3、Element Plus与ECharts构建用户问答界面与管理后台。系统实现了知识库文档的上传、解析、分块、向量化入库以及基于语义检索与提示词工程的智能问答、引用来源展示、问答历史管理、用户管理、分类管理和数据统计可视化等功能。测试结果表明本系统能够基于本地医疗健康知识库返回准确、可溯源的答案有效缓解了大语言模型的幻觉问题系统运行稳定、交互友好达到了预期的设计目标具有一定的实用价值与推广意义。源码下载链接https://pan.baidu.com/s/185YGwaNf79jPVtScYxdPyA?pwd1234提取码1234系统展示核心代码package com.java1234.rag.controller; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.java1234.rag.common.Result; import com.java1234.rag.security.LoginUserContext; import com.java1234.rag.service.KnowledgeService; import com.java1234.rag.vo.KnowledgeDocVO; import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; /** * 知识库文档控制器 */ RestController RequiredArgsConstructor public class KnowledgeController { private final KnowledgeService knowledgeService; /** * 上传知识库文档(管理员) */ PostMapping(/api/admin/knowledge/upload) public ResultKnowledgeDocVO upload(RequestParam(file) MultipartFile file, RequestParam Long categoryId, RequestParam(required false) String title) { Long uploaderId LoginUserContext.get().getUserId(); return Result.success(knowledgeService.upload(file, categoryId, title, uploaderId)); } /** * 分页查询文档 */ GetMapping(/api/knowledge) public ResultPageKnowledgeDocVO page(RequestParam(defaultValue 1) int page, RequestParam(defaultValue 10) int size, RequestParam(required false) Long categoryId, RequestParam(required false) String keyword) { return Result.success(knowledgeService.pageDocs(page, size, categoryId, keyword)); } /** * 删除文档(管理员) */ DeleteMapping(/api/admin/knowledge/{id}) public ResultVoid delete(PathVariable Long id) { knowledgeService.deleteDoc(id); return Result.success(); } }template div classpage-card div classsearch-bar el-input v-modelkeyword placeholder搜索分类名称 clearable stylewidth:240px keyup.enterloadData / el-button typeprimary clickloadData搜索/el-button el-button typesuccess clickopenDialog()新增分类/el-button /div el-table :datatableData stripe border el-table-column propid labelID min-width80 / el-table-column propname label分类名称 min-width140 / el-table-column propdescription label描述 min-width200 show-overflow-tooltip / el-table-column propsort label排序 min-width80 / el-table-column propstatus label状态 min-width100 template #default{ row } el-tag :typerow.status 1 ? success : info{{ row.status 1 ? 启用 : 禁用 }}/el-tag /template /el-table-column el-table-column propcreateTime label创建时间 min-width180 template #default{ row }{{ formatDateTime(row.createTime) }}/template /el-table-column el-table-column label操作 min-width160 fixedright template #default{ row } el-button typeprimary link clickopenDialog(row)编辑/el-button el-popconfirm title确定删除该分类 confirmhandleDelete(row.id) template #referenceel-button typedanger link删除/el-button/template /el-popconfirm /template /el-table-column /el-table el-pagination classpagination v-model:current-pagepage v-model:page-sizesize :totaltotal layouttotal, prev, pager, next changeloadData / el-dialog v-modeldialogVisible :titleform.id ? 编辑分类 : 新增分类 width480px el-form :modelform label-width80px el-form-item label名称el-input v-modelform.name //el-form-item el-form-item label描述el-input v-modelform.description typetextarea :rows3 //el-form-item el-form-item label排序el-input-number v-modelform.sort :min0 //el-form-item el-form-item label状态 el-select v-modelform.statusel-option label启用 :value1 /el-option label禁用 :value0 //el-select /el-form-item /el-form template #footer el-button clickdialogVisible false取消/el-button el-button typeprimary clickhandleSave保存/el-button /template /el-dialog /div /template script setup import { ref, reactive, onMounted } from vue import { ElMessage } from element-plus import { pageCategories, addCategory, updateCategory, deleteCategory } from /api/category import { formatDateTime } from /utils/format const keyword ref() const page ref(1) const size ref(10) const total ref(0) const tableData ref([]) const dialogVisible ref(false) const form reactive({ id: null, name: , description: , sort: 0, status: 1 }) const loadData async () { const res await pageCategories({ page: page.value, size: size.value, keyword: keyword.value }) tableData.value res.data.records total.value res.data.total } const openDialog (row) { if (row) Object.assign(form, row) else Object.assign(form, { id: null, name: , description: , sort: 0, status: 1 }) dialogVisible.value true } const handleSave async () { if (form.id) await updateCategory(form) else await addCategory(form) ElMessage.success(保存成功) dialogVisible.value false loadData() } const handleDelete async (id) { await deleteCategory(id) ElMessage.success(删除成功) loadData() } onMounted(loadData) /script style scoped .pagination { margin-top: 16px; justify-content: flex-end; } /style
分享一套锋哥原创的基于LangChain4j的RAG医疗健康知识智能问答系统(SpringBoot4+Vue3+Ollama)
大家好我是Java1234_小锋老师分享一套锋哥原创的基于LangChain4j的RAG医疗健康知识智能问答系统(SpringBoot4Vue3Ollama)项目介绍随着人工智能与大语言模型技术的快速发展智能问答系统在医疗健康领域展现出广阔的应用前景。然而通用大语言模型在回答医疗健康类问题时普遍存在知识更新滞后、易产生“幻觉”以及缺乏可信来源等问题难以直接应用于对准确性要求较高的医疗健康咨询场景。检索增强生成Retrieval-Augmented GenerationRAG技术通过将外部知识库检索与大语言模型生成相结合能够在不重新训练模型的前提下显著提升回答的准确性与可追溯性为构建可信的医疗健康知识问答系统提供了有效途径。本文设计并实现了一个基于LangChain4j的RAG医疗健康知识智能问答系统。系统后端采用Spring Boot 4框架以LangChain4j作为RAG应用编排框架通过Ollama在本地部署qwen3对话模型与qwen3-embedding嵌入模型使用Redis向量数据库存储文档向量并完成相似度检索业务数据持久化采用MySQL与MyBatis-Plus并通过Spring Security与JWT实现无状态的认证授权。前端采用Vue3、Element Plus与ECharts构建用户问答界面与管理后台。系统实现了知识库文档的上传、解析、分块、向量化入库以及基于语义检索与提示词工程的智能问答、引用来源展示、问答历史管理、用户管理、分类管理和数据统计可视化等功能。测试结果表明本系统能够基于本地医疗健康知识库返回准确、可溯源的答案有效缓解了大语言模型的幻觉问题系统运行稳定、交互友好达到了预期的设计目标具有一定的实用价值与推广意义。源码下载链接https://pan.baidu.com/s/185YGwaNf79jPVtScYxdPyA?pwd1234提取码1234系统展示核心代码package com.java1234.rag.controller; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.java1234.rag.common.Result; import com.java1234.rag.security.LoginUserContext; import com.java1234.rag.service.KnowledgeService; import com.java1234.rag.vo.KnowledgeDocVO; import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; /** * 知识库文档控制器 */ RestController RequiredArgsConstructor public class KnowledgeController { private final KnowledgeService knowledgeService; /** * 上传知识库文档(管理员) */ PostMapping(/api/admin/knowledge/upload) public ResultKnowledgeDocVO upload(RequestParam(file) MultipartFile file, RequestParam Long categoryId, RequestParam(required false) String title) { Long uploaderId LoginUserContext.get().getUserId(); return Result.success(knowledgeService.upload(file, categoryId, title, uploaderId)); } /** * 分页查询文档 */ GetMapping(/api/knowledge) public ResultPageKnowledgeDocVO page(RequestParam(defaultValue 1) int page, RequestParam(defaultValue 10) int size, RequestParam(required false) Long categoryId, RequestParam(required false) String keyword) { return Result.success(knowledgeService.pageDocs(page, size, categoryId, keyword)); } /** * 删除文档(管理员) */ DeleteMapping(/api/admin/knowledge/{id}) public ResultVoid delete(PathVariable Long id) { knowledgeService.deleteDoc(id); return Result.success(); } }template div classpage-card div classsearch-bar el-input v-modelkeyword placeholder搜索分类名称 clearable stylewidth:240px keyup.enterloadData / el-button typeprimary clickloadData搜索/el-button el-button typesuccess clickopenDialog()新增分类/el-button /div el-table :datatableData stripe border el-table-column propid labelID min-width80 / el-table-column propname label分类名称 min-width140 / el-table-column propdescription label描述 min-width200 show-overflow-tooltip / el-table-column propsort label排序 min-width80 / el-table-column propstatus label状态 min-width100 template #default{ row } el-tag :typerow.status 1 ? success : info{{ row.status 1 ? 启用 : 禁用 }}/el-tag /template /el-table-column el-table-column propcreateTime label创建时间 min-width180 template #default{ row }{{ formatDateTime(row.createTime) }}/template /el-table-column el-table-column label操作 min-width160 fixedright template #default{ row } el-button typeprimary link clickopenDialog(row)编辑/el-button el-popconfirm title确定删除该分类 confirmhandleDelete(row.id) template #referenceel-button typedanger link删除/el-button/template /el-popconfirm /template /el-table-column /el-table el-pagination classpagination v-model:current-pagepage v-model:page-sizesize :totaltotal layouttotal, prev, pager, next changeloadData / el-dialog v-modeldialogVisible :titleform.id ? 编辑分类 : 新增分类 width480px el-form :modelform label-width80px el-form-item label名称el-input v-modelform.name //el-form-item el-form-item label描述el-input v-modelform.description typetextarea :rows3 //el-form-item el-form-item label排序el-input-number v-modelform.sort :min0 //el-form-item el-form-item label状态 el-select v-modelform.statusel-option label启用 :value1 /el-option label禁用 :value0 //el-select /el-form-item /el-form template #footer el-button clickdialogVisible false取消/el-button el-button typeprimary clickhandleSave保存/el-button /template /el-dialog /div /template script setup import { ref, reactive, onMounted } from vue import { ElMessage } from element-plus import { pageCategories, addCategory, updateCategory, deleteCategory } from /api/category import { formatDateTime } from /utils/format const keyword ref() const page ref(1) const size ref(10) const total ref(0) const tableData ref([]) const dialogVisible ref(false) const form reactive({ id: null, name: , description: , sort: 0, status: 1 }) const loadData async () { const res await pageCategories({ page: page.value, size: size.value, keyword: keyword.value }) tableData.value res.data.records total.value res.data.total } const openDialog (row) { if (row) Object.assign(form, row) else Object.assign(form, { id: null, name: , description: , sort: 0, status: 1 }) dialogVisible.value true } const handleSave async () { if (form.id) await updateCategory(form) else await addCategory(form) ElMessage.success(保存成功) dialogVisible.value false loadData() } const handleDelete async (id) { await deleteCategory(id) ElMessage.success(删除成功) loadData() } onMounted(loadData) /script style scoped .pagination { margin-top: 16px; justify-content: flex-end; } /style