diff --git a/modules/cms-ai/README.md b/modules/cms-ai/README.md new file mode 100644 index 00000000..51bbec4e --- /dev/null +++ b/modules/cms-ai/README.md @@ -0,0 +1,132 @@ + +## 技术交流 + +* 官方网站: +* 使用文档: +* 问题反馈: [【新手必读】](https://gitee.com/thinkgem/jeesite5/issues/I18ARR) +* 需求收集: +* 联系我们: +* 关注微信公众号,了解最新动态: + +

   + JeeSite微信公众号 +

+ +* QQ 群:`127515876`、`209330483`、`223507718`、`709534275`、`730390092`、`1373527`、`183903863(外包)` +* 微信群:如果二维码过期,请尝试刷新图片,或者添加客服微信 jeesitex 邀请您进群 + +

   + JeeSite微信群 +

+ +* 源码仓库地址: + [Gitee](https://gitee.com/thinkgem/jeesite5)、 + [GitCode](https://gitcode.com/thinkgem/jeesite5)、 + [GitHub](https://github.com/thinkgem/jeesite5) +* 分离版源码仓库地址: + [Gitee](https://gitee.com/thinkgem/jeesite-vue)、 + [GitCode](https://gitcode.com/thinkgem/jeesite-vue)、 + [GitHub](https://github.com/thinkgem/jeesite-vue) +* 源码合集仓库地址: + [GVP](https://gitee.com/thinkgem/jeesite/tree/v5.springboot3)、 + [G-Star](https://gitcode.com/thinkgem/jeesite/overview?ref=v5.springboot3)、 + [GitHub](https://github.com/thinkgem/jeesite/tree/v5.springboot3) + +## 模块简介 + +本模块基于 Spring AI 和 JeeSite 内容管理系统(CMS)并结合了检索增强生成(Retrieval-Augmented Generation, RAG)技术 +和先进的人工智能算法(AI),打造了一个强大的企业级知识管理和智能对话平台。该模块专为企业设计,旨在通过高效的知识获取和精准的对话能力, +提升企业的信息管理效率和员工的工作效能。 + +检索增强生成 RAG 技术使系统能够自动从海量的企业文档中检索最相关的信息,并将其融入到生成的回答中,确保每一次查询都 +能获得最新且准确的结果。这种检索与生成相结合的方式,不仅提高了信息检索的准确性,还增强了回答的上下文关联性, +特别适合处理复杂的企业知识库。 + +此外该模块,支持云上大模型和本地部署的大模型,如:DeepSeek、通义千问,理论上支持所有 OpenAPI 标准接口的 AI 提供商。 +并能无缝集成多种嵌入式 AI 模型的向量数据库,如 PGVector、Elasticsearch、Milvus 等,实现高效的数据存储、检索及分析。 +无论是大规模数据集还是高度专业化的领域知识,JeeSite CMS + RAG + AI 都能提供定制化解决方案,满足企业多样化的业务需求和技术要求。 +企业可以轻松管理和访问复杂的信息资源,促进内部知识共享和创新,从而在竞争激烈的市场环境中保持领先地位。 + +优势:本模块结构清晰,代码简洁易懂,不管是正式项目、或是学习 AI 技术、都能轻松应对读懂源代码。 + +## AI 模型配置 + +支持的 AI 模型列表: + +* 线上模型:理论上支持所有 [OpenAPI](https://help.aliyun.com/zh/model-studio/developer-reference/use-qwen-by-calling-api) 标准接口的 AI 提供商。 + +* 本地模型:使用 [Ollama](https://ollama.com) 安装方法,本文不多赘述,网上有很多安装资料。 + +* 模型类型包括:聊天对话模型和嵌入式向量库模型,需注意 dimensions 维度参数,要和模型要求的匹配。 + +具体配置项详见 `jeesite-cms-ai.yml` 文件,有注释。 + +## 向量数据库配置 + +支持的向量库列表: + +* PGVector +* Elasticsearch +* Milvus +* ... + +具体配置项详见 `jeesite-cms-ai.yml` 文件,有注释。 + +### PGVector 建表语句 + +```sql +CREATE EXTENSION IF NOT EXISTS vector; +CREATE EXTENSION IF NOT EXISTS hstore; +CREATE EXTENSION IF NOT EXISTS "uuid-ossp"; + +-- 使用 all-minilm 模型时创建 +DROP TABLE IF EXISTS vector_store_384; +CREATE TABLE IF NOT EXISTS vector_store_384 ( + id varchar(64) DEFAULT uuid_generate_v4() PRIMARY KEY, + content text, + metadata json, + embedding vector(384) +); +CREATE INDEX ON vector_store_384 USING HNSW (embedding vector_cosine_ops); + +-- 使用 nomic-embed-text 模型时创建 +DROP TABLE IF EXISTS vector_store_786; +CREATE TABLE IF NOT EXISTS vector_store_786 ( + id varchar(64) DEFAULT uuid_generate_v4() PRIMARY KEY, + content text, + metadata json, + embedding vector(768) +); +CREATE INDEX ON vector_store_786 USING HNSW (embedding vector_cosine_ops); + +-- 使用 bge-m3 模型时创建 +DROP TABLE IF EXISTS vector_store_1024; +CREATE TABLE IF NOT EXISTS vector_store_1024 ( + id varchar(64) DEFAULT uuid_generate_v4() PRIMARY KEY, + content text, + metadata json, + embedding vector(1024) +); +CREATE INDEX ON vector_store_1024 USING HNSW (embedding vector_cosine_ops); +``` + +## 授权协议声明 + +1. 基于 Apache License Version 2.0 协议发布,可用于商业项目,但必须遵守以下补充条款。 +2. 不得将本软件应用于危害国家安全、荣誉和利益的行为,不能以任何形式用于非法为目的的行为。 +3. 在使用本软件时,由于它集成了众多第三方开源软件,请共同遵守这些开源软件的使用许可条款规定。 +4. 在延伸的代码中(修改和有源代码衍生的代码中)需要带有原来代码中的协议、版权声明和其他原作者 + 规定需要包含的说明(请尊重原作者的著作权,不要删除或修改文件中的`Copyright`和`@author`信息) + 更不要,全局替换源代码中的 jeesite 或 ThinkGem 等字样,否则你将违反本协议条款承担责任。 +5. 您若套用本软件的一些代码或功能参考,请保留源文件中的版权和作者,需要在您的软件介绍明显位置 + 说明出处,举例:本软件基于 JeeSite 快速开发平台,并附带链接:http://jeesite.com +6. 任何基于本软件而产生的一切法律纠纷和责任,均于我司无关。 +7. 如果你对本软件有改进,希望可以贡献给我们,共同进步。 +8. 本项目已申请软件著作权,请尊重开源,感谢阅读。 +9. 无用户数限制,无在线人数限制,放心使用。 + +## 技术支持与服务 + +* 本软件免费,我们也提供了相应的收费服务,因为: +* 没有资金的支撑就很难得到发展,特别是一个好的产品,如果 JeeSite 帮助了您,请为我们点赞。支持我们,您可以获得更多回馈,我们会把公益事业做的更好,开放更多资源,回报社区和社会。请给我们一些动力吧,在此非常感谢已支持我们的朋友! +* **联系我们**:请访问技术支持与服务页面: diff --git a/modules/cms-ai/bin/deploy.bat b/modules/cms-ai/bin/deploy.bat new file mode 100644 index 00000000..f4258bf5 --- /dev/null +++ b/modules/cms-ai/bin/deploy.bat @@ -0,0 +1,22 @@ +@echo off +rem /** +rem * Copyright (c) 2013-Now http://jeesite.com All rights reserved. +rem * No deletion without permission, or be held responsible to law. +rem * +rem * Author: ThinkGem@163.com +rem */ +echo. +echo [Ϣ] 𹤳̵Maven +echo. + +%~d0 +cd %~dp0 + +call mvn -v +echo. + +cd .. +call mvn clean deploy -Dmaven.test.skip=true -Pdeploy + +cd bin +pause \ No newline at end of file diff --git a/modules/cms-ai/bin/deploy.sh b/modules/cms-ai/bin/deploy.sh new file mode 100644 index 00000000..f8696c71 --- /dev/null +++ b/modules/cms-ai/bin/deploy.sh @@ -0,0 +1,18 @@ +#!/bin/sh +# /** +# * Copyright (c) 2013-Now http://jeesite.com All rights reserved. +# * No deletion without permission, or be held responsible to law. +# * +# * Author: ThinkGem@163.com +# */ +echo "" +echo "[信息] 部署工程到Maven服务器。" +echo "" + +mvn -v +echo "" + +cd .. +mvn clean deploy -Dmaven.test.skip=true -Pdeploy + +cd bin \ No newline at end of file diff --git a/modules/cms-ai/bin/package.bat b/modules/cms-ai/bin/package.bat new file mode 100644 index 00000000..a6b29c2c --- /dev/null +++ b/modules/cms-ai/bin/package.bat @@ -0,0 +1,22 @@ +@echo off +rem /** +rem * Copyright (c) 2013-Now http://jeesite.com All rights reserved. +rem * No deletion without permission, or be held responsible to law. +rem * +rem * Author: ThinkGem@163.com +rem */ +echo. +echo [Ϣ] װ̣jarļ +echo. + +%~d0 +cd %~dp0 + +call mvn -v +echo. + +cd .. +call mvn clean install -Dmaven.test.skip=true -Ppackage + +cd bin +pause \ No newline at end of file diff --git a/modules/cms-ai/bin/package.sh b/modules/cms-ai/bin/package.sh new file mode 100644 index 00000000..8deff508 --- /dev/null +++ b/modules/cms-ai/bin/package.sh @@ -0,0 +1,18 @@ +#!/bin/sh +# /** +# * Copyright (c) 2013-Now http://jeesite.com All rights reserved. +# * No deletion without permission, or be held responsible to law. +# * +# * Author: ThinkGem@163.com +# */ +echo "" +echo "[信息] 打包安装工程,生成jar包文件。" +echo "" + +mvn -v +echo "" + +cd .. +mvn clean install -Dmaven.test.skip=true -Ppackage + +cd bin \ No newline at end of file diff --git a/modules/cms-ai/db/cms-ai.erm b/modules/cms-ai/db/cms-ai.erm new file mode 100644 index 00000000..cab48ffb --- /dev/null +++ b/modules/cms-ai/db/cms-ai.erm @@ -0,0 +1,3590 @@ + + + + true + 100 + A4 210 x 297 mm + 30 + 30 + 30 + 30 + + 0 + 1.0 + 0 + 0 + + 128 + 128 + 192 + + + 255 + 255 + 255 + + Arial + 14 + + StandardSQL + false + + + 0 + true + 2 + 1 + 1 + false + true + false + false + + + db/cms-ai.sql + UTF-8 + CR+LF + false + 7be191506f9daa8070b3ac14921dffd44063d2bb + null + + true + false + true + false + true + false + false + false + false + false + false + false + false + false + false + true + false + true + false + false + + + + + null + db/cms-ai.xls + + + en + + true + true + true + + + + true + true + true + + + db/cms-ai.png + + true + true + + + + + + + false + + + + + 0 + + + + false + false + + + + + false + + + + + + -1 + -1 + Arial + 14 + 50 + 50 + + 255 + 255 + 255 + + + + false + 2016-12-25 17:25:00 + + Project Name + + + + Model Name + + + + Version + + + + Company + + + + Author + + + + + + + + + 7be191506f9daa8070b3ac14921dffd44063d2bb + Default + + + + + + 136ca02f1b3a96a8f2e242d5dd64d48f566143ef + 64 + null + false + null + false + false + false + + false + 租户代码 + 租户代码 + corp_code + varchar(n) + + + f116706ac00cd3a3ee88b2a88debf7ebc3eeb12d + 100 + null + false + null + false + false + false + + false + 租户名称 + 租户名称 + corp_name + nvarchar(n) + + + 1a3b3f8bccfce8894d117d6bdb0a6b104bfb80ef + 64 + null + false + null + false + false + false + + false + + 创建者 + create_by + varchar(n) + + + dba1aec0c72d79ea73ed4ebde07696cf4df174b7 + null + null + false + null + false + false + false + + false + + 创建时间 + create_date + datetime + + + f01926071736b56b898949cc0720149c71504324 + null + null + false + null + false + false + false + + false + + 扩展 Date 1 + extend_d1 + datetime + + + 942700093ab61c3be0bdf6b23bcba210bcc30281 + null + null + false + null + false + false + false + + false + + 扩展 Date 2 + extend_d2 + datetime + + + f221902bf89fe94dece8ccf309f59cc2c479d63f + null + null + false + null + false + false + false + + false + + 扩展 Date 3 + extend_d3 + datetime + + + c8d21e24bc69aac295703b0bae56269035b729f0 + null + null + false + null + false + false + false + + false + + 扩展 Date 4 + extend_d4 + datetime + + + 4c0cc4ae32f8774cc319f516784430204aef0bdb + 19 + 4 + false + null + false + false + false + + false + + 扩展 Float 1 + extend_f1 + decimal(p,s) + + + 2e958c528620621985af4394590198feed57cdf9 + 19 + 4 + false + null + false + false + false + + false + + 扩展 Float 2 + extend_f2 + decimal(p,s) + + + 7c25ad75662553c7d4a58fa66eb50ca7c0ffee59 + 19 + 4 + false + null + false + false + false + + false + + 扩展 Float 3 + extend_f3 + decimal(p,s) + + + 1f81990c9694963f032c302d1834b972a6f2eb74 + 19 + 4 + false + null + false + false + false + + false + + 扩展 Float 4 + extend_f4 + decimal(p,s) + + + a1d747cd40768ac9f85176518ee48cb513bae110 + 19 + null + false + null + false + false + false + + false + + 扩展 Integer 1 + extend_i1 + decimal(p) + + + a9f0e14d6691c397990abe4ef1ff21674dccf401 + 19 + null + false + null + false + false + false + + false + + 扩展 Integer 2 + extend_i2 + decimal(p) + + + 2ce06c5cf87d93bb1e3f47268dbc679be4b6dd8d + 19 + null + false + null + false + false + false + + false + + 扩展 Integer 3 + extend_i3 + decimal(p) + + + 53d8c730fcec69d341f44089817ae06eb4844278 + 19 + null + false + null + false + false + false + + false + + 扩展 Integer 4 + extend_i4 + decimal(p) + + + 80cd53da9d5a1b19676537e590e20fa2793e902c + 1000 + null + false + null + false + false + false + + false + + 扩展 JSON + extend_json + varchar(n) + + + ad6f9eff50476669df62b7601cbc3a2e0c905d36 + 500 + null + false + null + false + false + false + + false + + 扩展 String 1 + extend_s1 + nvarchar(n) + + + 3a24133d2be4831e99d1319983e5393bcf964ff9 + 500 + null + false + null + false + false + false + + false + + 扩展 String 2 + extend_s2 + nvarchar(n) + + + 40e1afbbad28d28e371dd1ab77fb56640b1cb66b + 500 + null + false + null + false + false + false + + false + + 扩展 String 3 + extend_s3 + nvarchar(n) + + + a2d6b5a494fc1a3d29360d922296521c6640856b + 500 + null + false + null + false + false + false + + false + + 扩展 String 4 + extend_s4 + nvarchar(n) + + + 29f701cc6a308fbfc5b12b80fee621ceeb231dcc + 500 + null + false + null + false + false + false + + false + + 扩展 String 5 + extend_s5 + nvarchar(n) + + + c9a37a7b6a5451930ca63e36814767f742cd1393 + 500 + null + false + null + false + false + false + + false + + 扩展 String 6 + extend_s6 + nvarchar(n) + + + 8c26203d310a4e602cf0c0fc8a7b2c818219c1dc + 500 + null + false + null + false + false + false + + false + + 扩展 String 7 + extend_s7 + nvarchar(n) + + + 54448f19b0f5d1630bf29f9f99787802c36ebddb + 500 + null + false + null + false + false + false + + false + + 扩展 String 8 + extend_s8 + nvarchar(n) + + + 869fc70cf3a4e92e8056b40814df8e03f9f9efde + 64 + null + false + null + false + false + false + + false + + 编号 + id + varchar(n) + + + b18ce64a2a72d00b26515583d8bbfea282f30ea8 + 64 + null + false + null + false + false + false + + false + + 父级编号 + parent_code + varchar(n) + + + 5887f9db78a9ebc7b23b9a163c6f68100257c0e5 + 767 + null + false + null + false + false + false + + false + + 所有父级编号 + parent_codes + varchar(n) + + + 8f7d3761c17a1b8632d186a3c67cb08dca18c498 + 500 + null + false + null + false + false + false + + false + + 备注信息 + remarks + nvarchar(n) + + + ba0fb53af3ccc8b0e5d73baa58ec27fbb7973097 + 1 + null + false + null + false + false + false + + false + + 状态(0正常 1删除 2停用 3冻结 4审核 5驳回 9草稿) + status + character(n) + + + 17718c2364a2368c2072da279c927d7ad3bfcf08 + 1 + null + false + null + false + false + false + + false + + 状态(0正常 1删除 2停用) + status + character(n) + + + 23b25e48c87be0e4f3952f7a8330594e9d511a4e + 64 + null + false + null + false + false + false + + false + + 区域选择 + test_area_code + varchar(n) + + + 8bc627205b6e55931d09079fcd07bfacbbd38f41 + 100 + null + false + null + false + false + false + + false + + 区域名称 + test_area_name + nvarchar(n) + + + cdc46f802299958a2b3140200410caf5cbeb8a27 + 200 + null + false + null + false + false + false + + false + + 复选框 + test_checkbox + varchar(n) + + + d829e707316a49d39e5a11da5f5d36030a856b86 + 64 + null + false + null + false + false + false + + false + + 父表主键 + test_data_id + varchar(n) + + + a27ebfd109532e2f551b101a0c78b3f50a3d58dd + null + null + false + null + false + false + false + + false + + 日期选择 + test_date + datetime + + + 95ec23c1b2704817cca94d169aed5e11deb0adbb + null + null + false + null + false + false + false + + false + + 日期时间 + test_datetime + datetime + + + ac02f2d1fff63fa66db583735eb1c8e9b466872f + 200 + null + false + null + false + false + false + + false + + 单行文本 + test_input + varchar(n) + + + e2270df5e0974bf471fdfe36e29bc9a8aa1774cb + 64 + null + false + null + false + false + false + + false + + 机构选择 + test_office_code + varchar(n) + + + 791691b791efedc2d14867a152b4de58f4567326 + 10 + null + false + null + false + false + false + + false + + 单选框 + test_radio + varchar(n) + + + 6697b12cf2f6d7135570c2a581212ee067c13206 + 10 + null + false + null + false + false + false + + false + + 下拉框 + test_select + varchar(n) + + + 68b9381c1fb6668186fef70f52fc0c14b1bd6f1c + 200 + null + false + null + false + false + false + + false + + 下拉多选 + test_select_multiple + varchar(n) + + + ae103dc1fb50094552e56afd72015481271913db + null + null + false + null + false + false + false + + false + + 排序号 + test_sort + integer + + + 2fed92437d28f1427e913aba1251fe0807c7b209 + 200 + null + false + null + false + false + false + + false + + 多行文本 + test_textarea + nvarchar(n) + + + 2eda719a62fb7e1d3face62555046d938abddda9 + 64 + null + false + null + false + false + false + + false + + 用户选择 + test_user_code + varchar(n) + + + 70e9482ae432d16e734a730100e366ddab33564c + 64 + null + false + null + false + false + false + + false + + 节点编码 + tree_code + varchar(n) + + + 40b63ab3e485fd55370d6d04b063c4397483ebc1 + 1 + null + false + null + false + false + false + + false + + 是否最末级 + tree_leaf + character(n) + + + 3b9c3307b7140f27edeb47ffe307a662b2856627 + 4 + null + false + null + false + false + false + + false + + 层次级别 + tree_level + decimal(p) + + + 5356a60d0801c47941dd2fb4565cf785bb58e2d3 + 200 + null + false + null + false + false + false + + false + + 节点名称 + tree_name + nvarchar(n) + + + bf5e60dee567b3ed0f12e8f3ffa1f74e43012b3a + 767 + null + false + null + false + false + false + + false + + 全节点名 + tree_names + varchar(n) + + + 16c9c333062ea3614d2e044803b872676c8a5377 + 10 + null + false + null + false + false + false + + false + + 排序号(升序) + tree_sort + decimal(p) + + + a886757c87fb1e04c5f84b6a802e129baaec2ca6 + 767 + null + false + null + false + false + false + + false + + 所有排序号 + tree_sorts + varchar(n) + + + 2c6b290f30c6f9e100f6c77eab0cba7bb3386768 + 64 + null + false + null + false + false + false + + false + + 更新者 + update_by + varchar(n) + + + f0bdbc4002f4a1b7fb7c5026bc21a7689c549728 + null + null + false + null + false + false + false + + false + + 更新时间 + update_date + datetime + + + + + + + e553474c37270813e70025e433a4cf8a64653e13 + 438 + 387 + Arial + 14 + 864 + 36 + + 128 + 128 + 192 + + + + test_tree + 测试树表 + + + + + + + 70e9482ae432d16e734a730100e366ddab33564c + 7e417ee9d0dd69c767a5853922621946ed4fb2d8 + + + + + varchar(n) + + + false + false + true + true + false + + + + + + + + + + + false + false + false + + + 0 + + + a535b6c506004a7fdf4d48984c9ff2cfa59c157a + + 5356a60d0801c47941dd2fb4565cf785bb58e2d3 + 39f501890586173d229e83610cfbfaa6e3a85374 + + + + + nvarchar(n) + + + false + false + true + false + false + + + + + + + + + + + false + false + false + + + 0 + + + 35ae805d1da92afdb99b2fe8c536d1649356fccd + + + + + + + + +
+ + 5435ef11ea53f170fe3491b199c113e47932e175 + 401 + 320 + Arial + 14 + 36 + 36 + + 128 + 128 + 192 + + + + test_data + 测试数据 + + + + + + + 869fc70cf3a4e92e8056b40814df8e03f9f9efde + d82778c36626013cd39fd790da6f55a9762f0c76 + + + + + varchar(n) + + + false + false + true + true + false + + + + + + + + + + + false + false + false + + + 0 + + + + ac02f2d1fff63fa66db583735eb1c8e9b466872f + 3e14b40dc07c134329a40752973acfad2ffdc48b + + + + + varchar(n) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + 2fed92437d28f1427e913aba1251fe0807c7b209 + 8050d948828b16267482e9e3716219321f206b81 + + + + + nvarchar(n) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + 6697b12cf2f6d7135570c2a581212ee067c13206 + 3664605e054c39531ca8e91aa4463c955a993357 + + + + + varchar(n) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + 68b9381c1fb6668186fef70f52fc0c14b1bd6f1c + f7b189ecdc92c78bfaae9c736318ab6a5aedd396 + + + + + varchar(n) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + 791691b791efedc2d14867a152b4de58f4567326 + 6e4837ab55b592669ccc7ebfc8b1ed96a00607b3 + + + + + varchar(n) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + cdc46f802299958a2b3140200410caf5cbeb8a27 + 9fb81bdc12ed017f62e9dd4529025e536eff7f08 + + + + + varchar(n) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + a27ebfd109532e2f551b101a0c78b3f50a3d58dd + 9d9478798ed2766a81b0e5a8a022eb89d9c5cc34 + + + + + datetime + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + 95ec23c1b2704817cca94d169aed5e11deb0adbb + c131dc5cb7ce6f1aa5e8d5f86f2002c8ae1bb8f6 + + + + + datetime + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + 2eda719a62fb7e1d3face62555046d938abddda9 + cfe3c330968a9a824c2cf933b227887d3e9615ac + + + + + varchar(n) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + e2270df5e0974bf471fdfe36e29bc9a8aa1774cb + 23041cb30875514136904ea11043c7ea1924f048 + + + + + varchar(n) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + 23b25e48c87be0e4f3952f7a8330594e9d511a4e + b6d5dc8745c0fa484ed6f14e90a42282ca1b285d + + + + + varchar(n) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + 8bc627205b6e55931d09079fcd07bfacbbd38f41 + d244401ff7302bb5b75092016531952d093b238b + + + + + nvarchar(n) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + 35ae805d1da92afdb99b2fe8c536d1649356fccd + + + + + + + + +
+ + 5a836e654b7b7d19f102e87336fefa079d98a2e6 + 438 + 346 + Arial + 14 + 468 + 36 + + 128 + 128 + 192 + + + + test_data_child + 测试数据子表 + + + + + + + 869fc70cf3a4e92e8056b40814df8e03f9f9efde + 34477707bcf8a7810e12e9565aff085f6fb1e0ad + + + + + varchar(n) + + + false + false + true + true + false + + + + + + + + + + + false + false + false + + + 0 + + + + ae103dc1fb50094552e56afd72015481271913db + ec8a047dffe3cf2e4d95ba3e26c3bac0382d95c9 + + + + + integer + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + d829e707316a49d39e5a11da5f5d36030a856b86 + b095c44611ed08156277676d9a3a0ce52b9b05ef + + + + + varchar(n) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + ac02f2d1fff63fa66db583735eb1c8e9b466872f + 78715aa66a10a9b190ad69b8ed792e9a2f4946e3 + + + + + varchar(n) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + 2fed92437d28f1427e913aba1251fe0807c7b209 + 693f8af2fe6cf45255b6f2bc7e9077f3630c3dd8 + + + + + nvarchar(n) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + 6697b12cf2f6d7135570c2a581212ee067c13206 + 04216c384533b70b8e86b571fa2beef7157bab5a + + + + + varchar(n) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + 68b9381c1fb6668186fef70f52fc0c14b1bd6f1c + 0b6f63094be90aa8674460cce26be10327827ceb + + + + + varchar(n) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + 791691b791efedc2d14867a152b4de58f4567326 + 363e8cfcf4a6b228e656decadacba29280906555 + + + + + varchar(n) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + cdc46f802299958a2b3140200410caf5cbeb8a27 + 7875aa5fee3d6f9587180fb8fce9343a56cdc34e + + + + + varchar(n) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + a27ebfd109532e2f551b101a0c78b3f50a3d58dd + 61c49a2f7807c55c8f85110c30889d5b403e4b04 + + + + + datetime + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + 95ec23c1b2704817cca94d169aed5e11deb0adbb + b91171b99f3628aadb0e6986fbfa30cc547b280e + + + + + datetime + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + 2eda719a62fb7e1d3face62555046d938abddda9 + 9f33d190101e56f93f5ece0fd7c5cdda3e704b4c + + + + + varchar(n) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + e2270df5e0974bf471fdfe36e29bc9a8aa1774cb + 16121b5aa08fc170883408ec2d0487281a132d9d + + + + + varchar(n) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + 23b25e48c87be0e4f3952f7a8330594e9d511a4e + 1afc7f146271f5c90ea811aa24c08ce25d12552e + + + + + varchar(n) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + 8bc627205b6e55931d09079fcd07bfacbbd38f41 + 343f0db997b913f299b0496c4306d3617ad708de + + + + + nvarchar(n) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + + + + + + + +
+
+ + + 845c82ebd869d5620b1ef2c2b6f438b11a045082 + BaseEntity + + + 869fc70cf3a4e92e8056b40814df8e03f9f9efde + 02ecedc0de5850cba25bc91919ed39d414b74111 + + + + + varchar(n) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + ba0fb53af3ccc8b0e5d73baa58ec27fbb7973097 + 2fe6a36385238c1b21c76deae00a7afa00ff5538 + + + + + character(n) + + + false + false + true + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + + + ea920cba2fe0eaee64a2310ece7cda4b198b37ec + BaseEntityCorp + + + 136ca02f1b3a96a8f2e242d5dd64d48f566143ef + b8ea4b73d6d32a222e5abfd453287575ae518480 + + + + + varchar(n) + + 0 + false + false + true + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + f116706ac00cd3a3ee88b2a88debf7ebc3eeb12d + b94f5fe344185c40739cf93d1090686001bb11e0 + + + + + nvarchar(n) + + JeeSite + false + false + true + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + + + 35ae805d1da92afdb99b2fe8c536d1649356fccd + DataEntity + + + 17718c2364a2368c2072da279c927d7ad3bfcf08 + f0036584bd8711715579d21994a0105935605a7e + + + + + character(n) + + 0 + false + false + true + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + 1a3b3f8bccfce8894d117d6bdb0a6b104bfb80ef + c391a15752a8eb58bc558a39d1b431f7ee125e0e + + + + + varchar(n) + + + false + false + true + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + dba1aec0c72d79ea73ed4ebde07696cf4df174b7 + e2e82ba86e15fd67397355e711255b1625078ae1 + + + + + datetime + + + false + false + true + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + 2c6b290f30c6f9e100f6c77eab0cba7bb3386768 + fd0546fc2d4e01c35dcbc23913add68a99fabd73 + + + + + varchar(n) + + + false + false + true + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + f0bdbc4002f4a1b7fb7c5026bc21a7689c549728 + f8ea4fc4a778a0b94398a661a1ed8608f0e8d28d + + + + + datetime + + + false + false + true + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + 8f7d3761c17a1b8632d186a3c67cb08dca18c498 + 69e01b6d4f42df40a09540ef4ba10ed8e006abaa + + + + + nvarchar(n) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + + + 85024a2953cf3e3c9c1cce49b2351853ab0d125b + DataEntityNoStatus + + + 1a3b3f8bccfce8894d117d6bdb0a6b104bfb80ef + e5355faba5ec3c9128507dd4c48ea9230631cf83 + + + + + varchar(n) + + + false + false + true + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + dba1aec0c72d79ea73ed4ebde07696cf4df174b7 + 6bed374c39d181003a4f92d76d79a4119176ba0c + + + + + datetime + + + false + false + true + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + 2c6b290f30c6f9e100f6c77eab0cba7bb3386768 + f9db19bb567760bbdd554d75bbfdc891c89f9da9 + + + + + varchar(n) + + + false + false + true + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + f0bdbc4002f4a1b7fb7c5026bc21a7689c549728 + ee78b079f7d319bf8119fd01439cd97424ff49fa + + + + + datetime + + + false + false + true + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + 8f7d3761c17a1b8632d186a3c67cb08dca18c498 + f7b88ecec0ef386bb384c228842a7587432112fb + + + + + nvarchar(n) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + + + 118dab95fc1f792cd468b9f66af2d4fabd98c39b + ExtendEntity + + + ad6f9eff50476669df62b7601cbc3a2e0c905d36 + 6ccadddab6ce48441ca7abd798cda6f3debf4a0c + + + + + nvarchar(n) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + 3a24133d2be4831e99d1319983e5393bcf964ff9 + 93ab0ba3b47b01934614dbd3e572358c9f99e6ea + + + + + nvarchar(n) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + 40e1afbbad28d28e371dd1ab77fb56640b1cb66b + a78c7961910a5e697027d1a3530b1afaa8ea8c94 + + + + + nvarchar(n) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + a2d6b5a494fc1a3d29360d922296521c6640856b + 40085364ec7a58653e96f8659aadd258d7556bc7 + + + + + nvarchar(n) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + 29f701cc6a308fbfc5b12b80fee621ceeb231dcc + 9787d7fe93ee31c5b4979fd620ff6e4b2777eccf + + + + + nvarchar(n) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + c9a37a7b6a5451930ca63e36814767f742cd1393 + 95c55b81b7e9e1a9bb01aa3d88fb90c648641c4e + + + + + nvarchar(n) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + 8c26203d310a4e602cf0c0fc8a7b2c818219c1dc + 16f44dfc7964796f109293bc49afd58dcb4eec1f + + + + + nvarchar(n) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + 54448f19b0f5d1630bf29f9f99787802c36ebddb + 39b1dffa083f74afc30df621845cf7f0ed71394f + + + + + nvarchar(n) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + a1d747cd40768ac9f85176518ee48cb513bae110 + 7584cc6360ae7edc99e1f619042eba5865b2c4c7 + + + + + decimal(p) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + a9f0e14d6691c397990abe4ef1ff21674dccf401 + f0b5383e05c6b3f6e5f65b33b33009826c83d014 + + + + + decimal(p) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + 2ce06c5cf87d93bb1e3f47268dbc679be4b6dd8d + 260d5f31009fff18000d1e64f4f877926e621306 + + + + + decimal(p) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + 53d8c730fcec69d341f44089817ae06eb4844278 + a83144f40e7ae64e46a4b4ed651379774a953b17 + + + + + decimal(p) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + 4c0cc4ae32f8774cc319f516784430204aef0bdb + 2a5203a275171a250870cf6cb224a910aa9354ec + + + + + decimal(p,s) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + 2e958c528620621985af4394590198feed57cdf9 + 3ef5bd65a7dcd74b9a9d8a292ec395f66b7de32b + + + + + decimal(p,s) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + 7c25ad75662553c7d4a58fa66eb50ca7c0ffee59 + 01d0849bdda56a8d8f24befdadc3fc9b007ae92b + + + + + decimal(p,s) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + 1f81990c9694963f032c302d1834b972a6f2eb74 + 1c8ed63d72f40f0fe2f05815675771bdf3f824f8 + + + + + decimal(p,s) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + f01926071736b56b898949cc0720149c71504324 + 2b49e875138bfb329aaa352629650b7881435123 + + + + + datetime + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + 942700093ab61c3be0bdf6b23bcba210bcc30281 + 5c6ec16226d85b0411b7077cb9a6e0c7aa8d74d1 + + + + + datetime + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + f221902bf89fe94dece8ccf309f59cc2c479d63f + d92b8f7fa7a2be49c7f00c447a603b136e84261d + + + + + datetime + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + c8d21e24bc69aac295703b0bae56269035b729f0 + 095a76f07a3cd2bdc6cc442757c11012e1974f4a + + + + + datetime + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + 80cd53da9d5a1b19676537e590e20fa2793e902c + 42c5d8f490f69b93e77698efa030ca23988ae696 + + + + + varchar(n) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + + + a535b6c506004a7fdf4d48984c9ff2cfa59c157a + TreeEntity + + + b18ce64a2a72d00b26515583d8bbfea282f30ea8 + 394369b90c0a5b6efeed3cf823c642605d7a1653 + + + + + varchar(n) + + + false + false + true + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + 5887f9db78a9ebc7b23b9a163c6f68100257c0e5 + e8d877396943acfec73023dba2c1c6e3d7802d62 + + + + + varchar(n) + + + false + false + true + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + 16c9c333062ea3614d2e044803b872676c8a5377 + 23f973124aedd0244533f4e7b3b103c548b966be + + + + + decimal(p) + + + false + false + true + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + a886757c87fb1e04c5f84b6a802e129baaec2ca6 + 984d5eac2b3221118a61655e4a5a49c78e0f0151 + + + + + varchar(n) + + + false + false + true + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + 40b63ab3e485fd55370d6d04b063c4397483ebc1 + b2f246a3f0ade317eaa9915e2fd539abae5a5ec8 + + + + + character(n) + + + false + false + true + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + 3b9c3307b7140f27edeb47ffe307a662b2856627 + f5a9968479420f08da2e98d21136b3ed4b6e396f + + + + + decimal(p) + + + false + false + true + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + bf5e60dee567b3ed0f12e8f3ffa1f74e43012b3a + 618194ebfc8c6c42efcef3a4af0b8054f6af209b + + + + + varchar(n) + + + false + false + true + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + + + + + + + + + + +
\ No newline at end of file diff --git a/modules/cms-ai/pom.xml b/modules/cms-ai/pom.xml new file mode 100644 index 00000000..6e727534 --- /dev/null +++ b/modules/cms-ai/pom.xml @@ -0,0 +1,117 @@ + + + 4.0.0 + + + com.jeesite + jeesite-parent + 5.11.0.springboot3-SNAPSHOT + ../../parent/pom.xml + + + jeesite-module-cms-ai + jar + + JeeSite Module CMS+RAG+AI 向量数据库及人工智能对话知识库 + http://jeesite.com + 2013-Now + + + + 1.0.0-M6 + + + + + + + com.jeesite + jeesite-module-core + ${project.parent.version} + + + + com.jeesite + jeesite-module-cms + ${project.parent.version} + + + + + org.springframework.ai + spring-ai-openai-spring-boot-starter + + + + + org.springframework.ai + spring-ai-ollama-spring-boot-starter + + + + + org.springframework.ai + spring-ai-pgvector-store-spring-boot-starter + + + + + + + + + com.vladsch.flexmark + flexmark-html2md-converter + 0.64.8 + + + + + + + + org.springframework.ai + spring-ai-bom + ${spring-ai.version} + pom + import + + + + + + + thinkgem + WangZhen + thinkgem at 163.com + Project lead + +8 + + + + + JeeSite + http://jeesite.com + + + \ No newline at end of file diff --git a/modules/cms-ai/src/main/java/com/jeesite/modules/cms/ai/config/CmsAiChatConfig.java b/modules/cms-ai/src/main/java/com/jeesite/modules/cms/ai/config/CmsAiChatConfig.java new file mode 100644 index 00000000..db887705 --- /dev/null +++ b/modules/cms-ai/src/main/java/com/jeesite/modules/cms/ai/config/CmsAiChatConfig.java @@ -0,0 +1,54 @@ +/** + * Copyright (c) 2013-Now http://jeesite.com All rights reserved. + * No deletion without permission, or be held responsible to law. + */ +package com.jeesite.modules.cms.ai.config; + +import com.jeesite.common.datasource.DataSourceHolder; +import org.springframework.ai.chat.client.ChatClient; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Primary; +import org.springframework.jdbc.core.JdbcTemplate; + +import javax.sql.DataSource; +import java.sql.SQLException; + +/** + * AI 聊天配置类 + * @author ThinkGem + */ +@Configuration +public class CmsAiChatConfig { + + /** + * PG向量库数据源 + * @author ThinkGem + */ + @Bean + @Primary + @ConditionalOnProperty(name = "jdbc.ds_pgvector.type") + public JdbcTemplate pgVectorStoreJdbcTemplate() throws SQLException { + DataSource dataSource = DataSourceHolder.getRoutingDataSource() + .createDataSource("ds_pgvector"); + return new JdbcTemplate(dataSource); + } + + /** + * 聊天对话客户端 + * @author ThinkGem + */ + @Bean + public ChatClient chatClient(ChatClient.Builder builder) { + return builder + .defaultSystem("你是我的知识库AI助手,请帮我解答我提出的相关问题。") + .build(); + } + +// @Bean +// public BatchingStrategy batchingStrategy() { +// return new TokenCountBatchingStrategy(EncodingType.CL100K_BASE, Integer.MAX_VALUE, 0.1); +// } + +} diff --git a/modules/cms-ai/src/main/java/com/jeesite/modules/cms/ai/service/ArticleVectorStoreImpl.java b/modules/cms-ai/src/main/java/com/jeesite/modules/cms/ai/service/ArticleVectorStoreImpl.java new file mode 100644 index 00000000..6e73b5d9 --- /dev/null +++ b/modules/cms-ai/src/main/java/com/jeesite/modules/cms/ai/service/ArticleVectorStoreImpl.java @@ -0,0 +1,113 @@ +/** + * Copyright (c) 2013-Now http://jeesite.com All rights reserved. + * No deletion without permission, or be held responsible to law. + */ +package com.jeesite.modules.cms.ai.service; + +import com.jeesite.common.collect.ListUtils; +import com.jeesite.common.collect.MapUtils; +import com.jeesite.common.lang.StringUtils; +import com.jeesite.common.lang.TimeUtils; +import com.jeesite.common.utils.PageUtils; +import com.jeesite.modules.cms.entity.Article; +import com.jeesite.modules.cms.service.ArticleVectorStore; +import com.jeesite.modules.cms.utils.CmsUtils; +import com.vladsch.flexmark.html2md.converter.FlexmarkHtmlConverter; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.ai.document.Document; +import org.springframework.ai.transformer.splitter.TokenTextSplitter; +import org.springframework.ai.vectorstore.VectorStore; +import org.springframework.ai.vectorstore.filter.FilterExpressionBuilder; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.Map; + +/** + * CMS 文章向量库存储 + * @author ThinkGem + */ +@Service +public class ArticleVectorStoreImpl implements ArticleVectorStore { + + protected Logger logger = LoggerFactory.getLogger(getClass()); + + @Autowired + private VectorStore vectorStore; + + /** + * 保存文章到向量库 + * @author ThinkGem + */ + @Override + public void save(Article article) { + Map metadata = MapUtils.newHashMap(); + metadata.put("id", article.getId()); + metadata.put("siteCode", article.getCategory().getSite().getSiteCode()); + metadata.put("categoryCode", article.getCategory().getCategoryCode()); + metadata.put("categoryName", article.getCategory().getCategoryName()); + metadata.put("title", article.getTitle()); + metadata.put("href", article.getHref()); + metadata.put("keywords", article.getKeywords()); + metadata.put("description", article.getDescription()); + metadata.put("url", article.getUrl()); + metadata.put("status", article.getStatus()); + metadata.put("createBy", article.getCreateBy()); + metadata.put("createDate", article.getCreateDate()); + metadata.put("updateBy", article.getUpdateBy()); + metadata.put("updateDate", article.getUpdateDate()); + String content = article.getTitle() + ", " + article.getKeywords() + ", " + + article.getDescription() + ", " + StringUtils.toMobileHtml( + article.getArticleData().getContent()); + String markdown = FlexmarkHtmlConverter.builder().build().convert(content); + List documents = List.of(new Document(article.getId(), markdown, metadata)); + List splitDocuments = new TokenTextSplitter().apply(documents); + this.delete(article); // 删除原数据 + ListUtils.pageList(splitDocuments, 64, params -> { + vectorStore.add((List)params[0]); // 增加新数据 + return null; + }); + } + + /** + * 删除向量库文章 + * @author ThinkGem + */ + @Override + public void delete(Article article) { + if (StringUtils.isNotBlank(article.getId())) { + vectorStore.delete(new FilterExpressionBuilder().eq("id", article.getId()).build()); + } + } + + /** + * 重建向量库文章 + * @author ThinkGem + */ + public String rebuild(Article article) { + logger.debug("开始重建向量库。 siteCode: {}, categoryCode: {}", + article.getCategory().getSite().getSiteCode(), + article.getCategory().getCategoryCode()); + long start = System.currentTimeMillis(); + try{ + article.setIsQueryArticleData(true); // 查询文章内容 + PageUtils.findList(article, null, e -> { + List
list = CmsUtils.getArticleService().findList((Article) e); + if (!list.isEmpty()) { + list.forEach(this::save); + return true; + } + return false; + }); + }catch(Exception ex){ + logger.error("重建向量库失败", ex); + return "重建向量库失败:" + ex.getMessage(); + } + String message = "重建向量库完成! 用时" + TimeUtils.formatTime(System.currentTimeMillis() - start) + "。"; + logger.debug(message); + return message; + } + +} diff --git a/modules/cms-ai/src/main/java/com/jeesite/modules/cms/ai/service/CacheChatMemory.java b/modules/cms-ai/src/main/java/com/jeesite/modules/cms/ai/service/CacheChatMemory.java new file mode 100644 index 00000000..3255204c --- /dev/null +++ b/modules/cms-ai/src/main/java/com/jeesite/modules/cms/ai/service/CacheChatMemory.java @@ -0,0 +1,45 @@ +/** + * Copyright (c) 2013-Now http://jeesite.com All rights reserved. + * No deletion without permission, or be held responsible to law. + */ +package com.jeesite.modules.cms.ai.service; + +import com.jeesite.common.cache.CacheUtils; +import com.jeesite.common.collect.ListUtils; +import org.springframework.ai.chat.memory.ChatMemory; +import org.springframework.ai.chat.messages.Message; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + * AI 对话消息存储 + * @author ThinkGem + */ +@Service +public class CacheChatMemory implements ChatMemory { + + private static final String CMS_CHAT_MSG_CACHE = "cmsChatMsgCache"; + + @Override + public void add(String conversationId, List messages) { + List conversationHistory = CacheUtils.get(CMS_CHAT_MSG_CACHE, conversationId); + if (conversationHistory == null) { + conversationHistory = ListUtils.newArrayList(); + } + conversationHistory.addAll(messages); + CacheUtils.put(CMS_CHAT_MSG_CACHE, conversationId, conversationHistory); + } + + @Override + public List get(String conversationId, int lastN) { + List all = CacheUtils.get(CMS_CHAT_MSG_CACHE, conversationId); + return all != null ? all.stream().skip(Math.max(0, all.size() - lastN)).toList() : List.of(); + } + + @Override + public void clear(String conversationId) { + CacheUtils.remove(CMS_CHAT_MSG_CACHE, conversationId); + } + +} diff --git a/modules/cms-ai/src/main/java/com/jeesite/modules/cms/ai/service/CmsAiChatService.java b/modules/cms-ai/src/main/java/com/jeesite/modules/cms/ai/service/CmsAiChatService.java new file mode 100644 index 00000000..b2aad2ba --- /dev/null +++ b/modules/cms-ai/src/main/java/com/jeesite/modules/cms/ai/service/CmsAiChatService.java @@ -0,0 +1,115 @@ +/** + * Copyright (c) 2013-Now http://jeesite.com All rights reserved. + * No deletion without permission, or be held responsible to law. + */ +package com.jeesite.modules.cms.ai.service; + +import com.jeesite.common.cache.CacheUtils; +import com.jeesite.common.collect.MapUtils; +import com.jeesite.common.idgen.IdGen; +import com.jeesite.common.lang.DateUtils; +import com.jeesite.common.lang.StringUtils; +import com.jeesite.common.service.BaseService; +import com.jeesite.modules.sys.utils.UserUtils; +import org.springframework.ai.chat.client.ChatClient; +import org.springframework.ai.chat.client.advisor.MessageChatMemoryAdvisor; +import org.springframework.ai.chat.client.advisor.QuestionAnswerAdvisor; +import org.springframework.ai.chat.memory.ChatMemory; +import org.springframework.ai.chat.messages.Message; +import org.springframework.ai.chat.messages.UserMessage; +import org.springframework.ai.chat.model.ChatResponse; +import org.springframework.ai.vectorstore.SearchRequest; +import org.springframework.ai.vectorstore.VectorStore; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import reactor.core.publisher.Flux; + +import java.util.List; +import java.util.Map; + +/** + * AI 聊天服务类 + * @author ThinkGem + */ +@Service +public class CmsAiChatService extends BaseService { + + private static final String CMS_CHAT_CACHE = "cmsChatCache"; + + @Autowired + private ChatClient chatClient; + @Autowired + private ChatMemory chatMemory; + @Autowired + private VectorStore vectorStore; + + /** + * 获取聊天对话消息 + * @author ThinkGem + */ + public List getChatMessage(String conversationId) { + return chatMemory.get(conversationId, 100); + } + + private static String getChatCacheKey() { + String key = UserUtils.getUser().getId(); + if (StringUtils.isBlank(key)) { + key = UserUtils.getSession().getId().toString(); + } + return key; + } + + public Map> getChatCacheMap() { + Map> cache = CacheUtils.get(CMS_CHAT_CACHE, getChatCacheKey()); + if (cache == null) { + cache = MapUtils.newHashMap(); + } + return cache; + } + + /** + * 新建或更新聊天对话 + * @author ThinkGem + */ + public Map saveChatConversation(String conversationId, String title) { + if (StringUtils.isBlank(conversationId)) { + conversationId = IdGen.nextId(); + } + if (StringUtils.isBlank(title)) { + title = "新对话 " + DateUtils.getTime(); + } + Map map = MapUtils.newHashMap(); + map.put("id", conversationId); + map.put("title", title); + Map> cache = getChatCacheMap(); + cache.put(conversationId, map); + CacheUtils.put(CMS_CHAT_CACHE, getChatCacheKey(), cache); + return map; + } + + /** + * 删除聊天对话 + * @author ThinkGem + */ + public void deleteChatConversation(String conversationId) { + Map> cache = getChatCacheMap(); + cache.remove(conversationId); + CacheUtils.put(CMS_CHAT_CACHE, getChatCacheKey(), cache); + chatMemory.clear(conversationId); + } + + /** + * 聊天对话,流输出 + * @author ThinkGem + */ + public Flux chatStream(String conversationId, String message) { + return chatClient.prompt() + .messages(new UserMessage(message)) + .advisors( + new MessageChatMemoryAdvisor(chatMemory, conversationId, 1024), + new QuestionAnswerAdvisor(vectorStore, SearchRequest.builder().similarityThreshold(0.6F).topK(6).build())) + .stream() + .chatResponse(); + } + +} diff --git a/modules/cms-ai/src/main/java/com/jeesite/modules/cms/ai/web/CmsAiChatController.java b/modules/cms-ai/src/main/java/com/jeesite/modules/cms/ai/web/CmsAiChatController.java new file mode 100644 index 00000000..cab9e514 --- /dev/null +++ b/modules/cms-ai/src/main/java/com/jeesite/modules/cms/ai/web/CmsAiChatController.java @@ -0,0 +1,84 @@ +/** + * Copyright (c) 2013-Now http://jeesite.com All rights reserved. + * No deletion without permission, or be held responsible to law. + */ +package com.jeesite.modules.cms.ai.web; + +import com.jeesite.common.config.Global; +import com.jeesite.common.web.BaseController; +import com.jeesite.modules.cms.ai.service.CmsAiChatService; +import org.springframework.ai.chat.messages.Message; +import org.springframework.ai.chat.model.ChatResponse; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.MediaType; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import reactor.core.publisher.Flux; + +import java.util.Collection; +import java.util.Comparator; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * AI 聊天控制器类 + * @author ThinkGem + */ +@RestController +@RequestMapping("${adminPath}/cms/chat") +public class CmsAiChatController extends BaseController { + + @Autowired + private CmsAiChatService cmsAiChatService; + + /** + * 获取聊天对话消息 + * @author ThinkGem + */ + @RequestMapping("/message") + public List message(String id) { + return cmsAiChatService.getChatMessage(id); + } + + /** + * 聊天对话列表 + * @author ThinkGem + */ + @RequestMapping("/list") + public Collection> list() { + return cmsAiChatService.getChatCacheMap().values().stream() + .sorted(Comparator.comparing(map -> (String) map.get("id"), + Comparator.reverseOrder())).collect(Collectors.toList()); + } + + /** + * 新建或更新聊天对话 + * @author ThinkGem + */ + @RequestMapping("/save") + public String save(String id, String title) { + Map map = cmsAiChatService.saveChatConversation(id, title); + return renderResult(Global.TRUE, "保存成功", map); + } + + /** + * 删除聊天对话 + * @author ThinkGem + */ + @RequestMapping("/delete") + public String delete(String id) { + cmsAiChatService.deleteChatConversation(id); + return renderResult(Global.TRUE, "删除成功", id); + } + + /** + * 聊天对话,流输出 + * @author ThinkGem + */ + @RequestMapping(value = "/stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE) + public Flux stream(String id, String message) { + return cmsAiChatService.chatStream(id, message); + } + +} diff --git a/modules/cms-ai/src/main/resources/application-assistant.yml b/modules/cms-ai/src/main/resources/application-assistant.yml new file mode 100644 index 00000000..83dbcfce --- /dev/null +++ b/modules/cms-ai/src/main/resources/application-assistant.yml @@ -0,0 +1,12 @@ + +## 重要提示(Tip): + +## 请勿在该配置文件中添加其它任何配置(添加也不会生效)。 +## 该文件,仅仅是为了让 jeesite-cms-ai.yml 文件, +## 在 IDEA 中有一个自动完成及帮助提示,并无其它用意。 +## 参数配置请在 jeesite-cms-ai.yml 文件中添加。 + +spring: + config: + import: + - classpath:config/jeesite-cms-ai.yml diff --git a/modules/cms-ai/src/main/resources/config/jeesite-cms-ai.yml b/modules/cms-ai/src/main/resources/config/jeesite-cms-ai.yml new file mode 100644 index 00000000..e3b95e36 --- /dev/null +++ b/modules/cms-ai/src/main/resources/config/jeesite-cms-ai.yml @@ -0,0 +1,125 @@ +# 温馨提示:不建议直接修改此文件,为了平台升级方便,建议将需要修改的参数值,复制到application.yml里进行覆盖该参数值。 + +spring: + ai: + + # 云上大模型(使用该模型,请开启 enabled 参数) + openai: + base-url: https://api.siliconflow.cn + api-key: ${SFLOW_APP_KEY} + #base-url: https://ai.gitee.com + #api-key: ${GITEE_APP_KEY} + # 聊天对话模型 + chat: + enabled: true + options: + model: deepseek-ai/DeepSeek-R1-Distill-Qwen-7B + #model: DeepSeek-R1-Distill-Qwen-14B + max-tokens: 1024 + temperature: 0.6 + top-p: 0.7 + frequency-penalty: 0 + logprobs: true + # 向量库知识库模型(注意:不同的模型维度不同) + embedding: + enabled: true + options: + model: BAAI/bge-m3 + #model: bge-large-zh-v1.5 + dimensions: 512 + + # 本地大模型配置(使用该模型,请开启 enabled 参数) + ollama: + base-url: http://localhost:11434 + # 聊天对话模型 + chat: + enabled: false + options: + #model: qwen2.5 + model: deepseek-r1:7b + max-tokens: 1024 + temperature: 0.6 + top-p: 0.7 + frequency-penalty: 0 + # 向量库知识库模型(注意:不同的模型维度不同) + embedding: + enabled: false + # 维度 dimensions 设置为 384 + #model: all-minilm:33m + # 维度 dimensions 设置为 768 + #model: nomic-embed-text + # 维度 dimensions 设置为 1024 + model: bge-m3 + + # 向量数据库配置 + vectorstore: + + # Postgresql 向量数据库(PG 连接配置,见下文,需要手动建表) + pgvector: + initialize-schema: false + id-type: TEXT + index-type: HNSW + distance-type: COSINE_DISTANCE + #table-name: vector_store_384 + #dimensions: 384 + #table-name: vector_store_786 + #dimensions: 768 + table-name: vector_store_1024 + dimensions: 1024 + batching-strategy: TOKEN_COUNT + max-document-batch-size: 10000 + +# # ES 向量数据库(ES 连接配置,见下文) +# elasticsearch: +# initialize-schema: true +# index-name: vector-index +# dimensions: 1024 +# similarity: cosine +# batching-strategy: TOKEN_COUNT + +# # Milvus 向量数据库(字符串长度不超过65535) +# milvus: +# initialize-schema: true +# client: +# host: "localhost" +# port: 19530 +# username: "root" +# password: "milvus" +# database-name: "default2" +# collection-name: "vector_store2" +# embedding-dimension: 384 +# index-type: HNSW +# metric-type: COSINE + +# ========= Postgresql 向量数据库数据源 ========= + +jdbc: + ds_pgvector: + type: postgresql + driver: org.postgresql.Driver + url: jdbc:postgresql://127.0.0.1:5433/jeesite-ai + username: postgres + password: postgres + testSql: SELECT 1 + +# ========= ES 向量数据库连接配置 ========= + +spring.elasticsearch: + enabled: true + socket-timeout: 120s + connection-timeout: 120s + uris: http://127.0.0.1:9200 + username: elastic + password: elastic + +# 对话消息存缓存,可自定义存数据库 +j2cache: + caffeine: + region: + # 对话消息的超期时间,默认 30天,根据需要可以设置更久。 + cmsChatCache: 100000, 30d + cmsChatMsgCache: 100000, 30d + +#logging: +# level: +# org.springframework: debug diff --git a/modules/cms-ai/src/main/resources/db/upgrade/cms-ai/versions b/modules/cms-ai/src/main/resources/db/upgrade/cms-ai/versions new file mode 100644 index 00000000..57f82f72 --- /dev/null +++ b/modules/cms-ai/src/main/resources/db/upgrade/cms-ai/versions @@ -0,0 +1 @@ +5.11.0 \ No newline at end of file diff --git a/modules/pom.xml b/modules/pom.xml index d0384954..4e831165 100644 --- a/modules/pom.xml +++ b/modules/pom.xml @@ -16,6 +16,7 @@ core app cms + cms-ai static test diff --git a/web/pom.xml b/web/pom.xml index aa8e309a..339a7c61 100644 --- a/web/pom.xml +++ b/web/pom.xml @@ -66,6 +66,13 @@ ${project.parent.version} + +