【优化】AI 知识库: 从url下载文档资源
This commit is contained in:
parent
ed2296e4c7
commit
024109dac9
@ -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> {
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -1,310 +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 转变成让人满意的模块
|
||||
化结构。
|
||||
|
||||
Loading…
Reference in New Issue
Block a user