Browse Source

【优化】AI 知识库: 从url下载文档资源

xiaoxin 1 year ago
parent
commit
024109dac9

+ 1 - 1
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/knowledge/AiKnowledgeBaseMapper.java

@@ -10,5 +10,5 @@ import org.apache.ibatis.annotations.Mapper;
  * @author xiaoxin
  */
 @Mapper
-public interface AiKnowledgeBaseMapper extends BaseMapperX<AiKnowledgeDO> {
+public interface AiKnowledgeMapper extends BaseMapperX<AiKnowledgeDO> {
 }

+ 16 - 8
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/knowledge/AiKnowledgeDocumentServiceImpl.java

@@ -1,6 +1,7 @@
 package cn.iocoder.yudao.module.ai.service.knowledge;
 
 import cn.hutool.core.collection.CollUtil;
+import cn.hutool.http.HttpUtil;
 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
@@ -17,7 +18,7 @@ import org.springframework.ai.reader.tika.TikaDocumentReader;
 import org.springframework.ai.tokenizer.TokenCountEstimator;
 import org.springframework.ai.transformer.splitter.TokenTextSplitter;
 import org.springframework.ai.vectorstore.RedisVectorStore;
-import org.springframework.beans.factory.annotation.Value;
+import org.springframework.core.io.ByteArrayResource;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
@@ -46,17 +47,14 @@ public class AiKnowledgeDocumentServiceImpl implements AiKnowledgeDocumentServic
     private RedisVectorStore vectorStore;
 
 
-    // TODO xiaoxin 临时测试用,后续删
-    @Value("classpath:/webapp/test/Fel.pdf")
-    private org.springframework.core.io.Resource data;
-
     // TODO 芋艿:需要 review 下,代码格式;
     @Override
     @Transactional(rollbackFor = Exception.class)
     public Long createKnowledgeDocument(AiKnowledgeDocumentCreateReqVO createReqVO) {
-        // TODO xiaoxin 后续从 url 加载
-        TikaDocumentReader loader = new TikaDocumentReader(data);
-        // 1.1 加载文档
+        // 1.1 下载文档
+        String url = createReqVO.getUrl();
+        TikaDocumentReader loader = new TikaDocumentReader(downloadFile(url));
+        // 1.2 加载文档
         List<Document> documents = loader.get();
         Document document = CollUtil.getFirst(documents);
         // TODO @xin:是不是不存在,就抛出异常呀;厚泽 return 呀;
@@ -86,4 +84,14 @@ public class AiKnowledgeDocumentServiceImpl implements AiKnowledgeDocumentServic
         return documentId;
     }
 
+    private org.springframework.core.io.Resource downloadFile(String url) {
+        try {
+            byte[] bytes = HttpUtil.downloadBytes(url);
+            return new ByteArrayResource(bytes);
+        } catch (Exception e) {
+            log.error("[downloadFile][url({}) 下载失败]", url, e);
+            throw new RuntimeException(e);
+        }
+    }
+
 }

+ 2 - 2
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/knowledge/AiKnowledgeServiceImpl.java

@@ -7,7 +7,7 @@ import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.AiKnowledgeCreat
 import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.AiKnowledgeUpdateMyReqVO;
 import cn.iocoder.yudao.module.ai.dal.dataobject.knowledge.AiKnowledgeDO;
 import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModelDO;
-import cn.iocoder.yudao.module.ai.dal.mysql.knowledge.AiKnowledgeBaseMapper;
+import cn.iocoder.yudao.module.ai.dal.mysql.knowledge.AiKnowledgeMapper;
 import cn.iocoder.yudao.module.ai.service.model.AiChatModelService;
 import jakarta.annotation.Resource;
 import lombok.extern.slf4j.Slf4j;
@@ -29,7 +29,7 @@ public class AiKnowledgeServiceImpl implements AiKnowledgeService {
     private AiChatModelService chatModalService;
 
     @Resource
-    private AiKnowledgeBaseMapper knowledgeBaseMapper;
+    private AiKnowledgeMapper knowledgeBaseMapper;
 
     @Override
     public Long createKnowledgeMy(AiKnowledgeCreateMyReqVO createReqVO, Long userId) {

+ 0 - 311
yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/webapp/test/Fel.pdf

@@ -1,311 +0,0 @@
-                   Fel 表达式引擎
-
-一、名词解释
-
-      Fel:全称是 Fast Expression Language,一种开源表达式引擎。
-      EL:表达式语言,用于求表达式的值。
-      Ast:抽象语法树,一般由语法分析工具生成。1+2*3 会解析结果如下所示:
-
-二、简介
-
-      Fel(Fast Expression Language)在源自于企业项目,设计目标是为了满足不断变化的功能需
-求和性能需求。
-
-      Fel 是开放的,引擎执行中的多个模块都可以扩展或替换。Fel 的执行主要是通过函数实现,
-运算符(+、-等都是 Fel 函数),所有这些函数都是可以替换的,扩展函数也非常简单。
-
-      Fel 有双引擎,同时支持解释执行和编译执行。可以根据性能要求选择执行方式。编译执行
-就是将表达式编译成字节码(生成 java 代码和编译模块都是可以扩展和替换的)
-
-      Fel 基于 Java1.5开发,适用于 Java1.5及以上版本。
-
-1. 特点
-
-      易用性:API 使用简单,语法简洁,和 java 语法很相似。
-      轻量级:整个包只有200多 KB。
-      高 效:目前没有发现有开源的表达式引擎比 Fel 快。
-      扩展性:采用模块化设计,可灵活控制表达式的执行过程。
-      根函数:Fel 支持根函数,“$('Math')”在 Fel 中是常用的使用函数的方式。
-      $函数:通过$函数,Fel 可以方便的调用工具类或对象的方法(并不需要任何附加代码),
-2. 不足
-
-      支持脚本:否。
-
-3. 适应场景
-
-      Fel 适合处理海量数据,Fel 良好的扩展性可以更好的帮助用户处理数据。
-      Fel 同样适用于其他需要使用表达式引擎的地方(如果工作流、公式计算、数据有效性校验
-等等)
-
-三、安装
-
-1. 获取 Fel
-
-      项目主页:http://code.google.com/p/fast-el/
-      下载地址:http://code.google.com/p/fast-el/downloads/list
-
-2. Jdk1.6 环境
-
-      使用:将 fel.jar 加入 classpath 即可。
-      构建 Fel:下载 fel-all.tar.gz,解压后将 src 作为源码文件夹,并且将 lib/antlr-min.jar 加入
-classpath 即可。
-
-3. Jdk1.5 环境:
-
-      与 jdk1.6 环境下的区别在于,需要添加 jdk 内置的 tools.jar 到 classpath。
-
-四、功能
-
-1. 算术表达式:
-
-FelEngine fel= new FelEngineImpl();
-Object result= fel.eval("5000*12+7500");
-System.out.println(result);
-
-输出结果:67500
-2. 变量
-
-使用变量,其代码如下所示:
-
-FelContext ctx= fel.getContext();
-ctx.set("单价", 5000);
-ctx.set("数量", 12);
-ctx.set("运费", 7500);
-Object result= fel.eval("单价*数量+运费");
-System.out.println(result);
-
-输出结果:67500
-
-3. 调用 JAVA 方法
-
-FelEngine fel= new FelEngineImpl();
-FelContext ctx= fel.getContext();
-ctx.set("out", System.out);
-fel.eval("out.println('Hello Everybody'.substring(6))");
-
-输出结果:Everybody
-
-4. 自定义上下文环境
-
-//负责提供气象服务的上下文环境
-FelContext ctx= new AbstractConetxt() {
-
-      public Object get(Object name) {
-            if("天气".equals(name)){
-                  return "晴";
-            }
-            if("温度".equals(name)){
-                  return 25;
-            }
-            return null;
-
-      }
-};
-FelEngine fel= new FelEngineImpl(ctx);
-Object eval = fel.eval("'天气:'+天气+';温度:'+温度");
-System.out.println(eval);
-
-输出结果:天气:晴;温度:25
-
-5. 多层上下文环境(命名空间)
-
-FelEngine fel= new FelEngineImpl();
-String costStr= "成本";
-String priceStr="价格";
-FelContext baseCtx= fel.getContext();
-//父级上下文中设置成本和价格
-baseCtx.set(costStr, 50);
-baseCtx.set(priceStr,100);
-
-String exp= priceStr+"-"+costStr;
-Object baseCost= fel.eval(exp);
-System.out.println("期望利润:" + baseCost);
-
-FelContext ctx= new ContextChain(baseCtx, new MapContext());
-//通货膨胀导致成本增加(子级上下文 中设置成本,会覆盖父级上下文中的成本)
-ctx.set(costStr,50+20 );
-Object allCost= fel.eval(exp, ctx);
-System.out.println("实际利润:" + allCost);
-
-输出结果:
-期望利润:50
-实际利润:30
-
-6. 编译执行
-
-FelEngine fel= new FelEngineImpl();
-FelContext ctx= fel.getContext();
-ctx.set("单价", 5000);
-ctx.set("数量", 12);
-ctx.set("运费", 7500);
-Expression exp= fel.compile("单价*数量+运费",ctx);
-Object result= exp.eval(ctx);
-System.out.println(result);
-
-执行结果:67500
-备注:适合处理海量数据,编译执行的速度基本与 Java 字节码执行速度一样快。
-
-7. 自定义函数
-
-          //定义 hello 函数
-    Function fun= new CommonFunction() {
-
-            public String getName() {
-                  return "hello";
-
-            }
-
-          /*
-               * 调用 hello("xxx")时执行的代码
-             */
-            @Override
-            public Object call(Object[] arguments) {
-
-                  Object msg= null;
-                  if(arguments!= null && arguments.length>0){
-
-                         msg= arguments[0];
-                  }
-                  return ObjectUtils.toString(msg);
-            }
-
-      };
-      FelEngine e= new FelEngineImpl();
-      //添加函数到引擎中。
-      e.addFun(fun);
-      String exp= "hello('fel')";
-      //解释执行
-    Object eval = e.eval(exp);
-      System.out.println("hello "+eval);
-      //编译执行
-    Expression compile= e.compile(exp, null);
-      eval = compile.eval(null);
-      System.out.println("hello "+eval);
-
-执行结果:
-hello fel hello fel
-
-8. 调用静态方法
-
-      如果你觉得上面的自定义函数也麻烦,Fel 提供的$函数可以方便的调用工具类的方法 熟悉
-jQuery 的朋友肯定知道"$"函数的威力。Fel 东施效颦,也实现了一个"$"函数,其作用是获取 class
-和创建对象。结合点操作符,可以轻易的调用工具类或对象的方法。
-
-       //调用 Math.min(1,2)
- FelEngine.instance.eval("$('Math').min(1,2)");
- //调用 new Foo().toString();
- FelEngine.instance.eval("$('com.greenpineyu.test.Foo.new').toString()");
-
-      通过"$('class').method"形式的语法,就可以调用任何等三方类包(commons lang 等)及自
-定义工具类的方法,也可以创建对象,调用对象的方法。如果有需要,还可以直接注册 Java
-Method 到函数管理器中。
-五、安全(始于 0.8 版本)
-
-      为了防止出现“${'System'}.exit(1)”这样的表达式导致系统崩溃。Fel 加入了安全管理器,主
-要是对方法访问进行控制。安全管理器中通过允许访问的方法列表(黑名单)和禁止访问的方
-法列表(白名单)来控制方法访问。将 "java.lang.System. *"加入到黑名单,表示 System 类的
-所以方法都不能访问。将"java.lang.Math. *"加入白名单,表示只能访问 Math 类中的方法。如
-果你不喜欢这个安全管理器,可以自己开发一个,非常简单,只需要实现一个方法就可以了。
-
-六、语法
-
-1. 简介
-
-      Fel 的语法非常简单,基本和 Java 语法没没有区别。Fel 语法是 Java 语法的一个子集,支
-持的运算符有限。如果熟悉语法的话,只需要关注一下 Fel 支持的运算即可。
-
-      Fel 表达式由常量、变量、函数、运算符组成。详见下文。
-
-2. 常量
-
-常量         说明
-Number     1,1.0 等
-Boolean    true,false
-String     'abc',"abc"
-
-3. 变量
-
-变量命名规则与 java 变量相同。变量名由字母、数字、下划线、$组成。
-
-变量         说明
-
-abc 以字母开头
-
-abc 以下划线开头
-
-$abc 以$开头
-
-变量         中文变量名也可以
-
-4. 函数
-
-函数名的语法规则与变量相同
-
-函数         说明
-
-$('Math')  $是变量名,'Math'是参数
-5. 运算符
-
-运算符        类型  优先级     说明
-?:         条件          三元操作符
-           逻辑       优  或操作
-||                  先  与操作
-&&         关系       级  等于、不等于
-==、!=               从  大于、小于、大于等于、小于等于
->、<、<=、>=  算术       低  加减
-+、-        逻辑       到  乘、除、取模
-*、/、%               高  取反操作
-!
-
-七、结构
-
-1. 主要组成部分
-
-      引擎由四部分组成,每个组成部分都可以被替换。组成部分如下所示:
-
-组件         说明
-解析器        将表达式解析成 Ast 节点
-解释执行       负责执行节点
-执行上下文      负责提供变量
-编译器        负责生成代码并编译
-
-2. 主要流程
-
-执行表达式的流程如下所示:
-组件            说明
-解析表达式         默认 Antlr 解析表达式,生成 Ast 节点。
-Ast 节点        由解析器生成的抽象语法树节点
-节点解释器         每一个节点都有一个解释器,负责解释节点。
-编译器           负责生成表达式对应 Java 类并编译,生成 Expression 对象
-
-3. 引擎上下文
-
-      引擎上下文负责存取变量,它是脚本引擎与 Java 对象之间的桥梁。其结构如下所示:
-
-组件            说明
-FelContext    负责存储和保存变量
-MapContext    使用 Map 来保存变量
-ContextChain  上下文链,保存两个上下文的引用。存取变量委托引用的上下文处理。
-
-4. 表达式解析
-
-      解析表达式的过程就是将表达式解析成 Ast 节点的过程,目前 Fel 由 Antlr 负责解析表达式,
-生成 Ast 节点(FelNode),流程如下所示:
-5. 解释执行
-
-      FelNode(Ast 节点)中都包含一个解释器,不同的节点有不同的解释器,解释器负责求节点
-值,流程如下所示:
-
-6. 编译执行
-
-      FelNode(Ast 节点)中都包含一个代码生成器,负责将 Fel 表达式转换成 java 表达式。编译
-模块负责将 java 表达式封装成 Java 类、编译、创建 Expression。再通过调用 Expression.eval 求
-表达式的值。其过程如下所示:
-
-7. 小结
-
-      在上文介绍的 Fel 组件中,绝大多数组件都是可能被替换的。通过在运行时替换一些小粒
-度的组件,就可以灵活控制 Fel 的执行过程,很有实用价值。有些变化较少的组件(Antlr 解析器)
-的替换过程还不是挺方便,随着 Fel 的发展,会慢慢重构,努力使 Fel 转变成让人满意的模块
-化结构。
-