改版
https://github.com/8DE4732A/RapiPdf
- 支持中文
- 目录改成描述
- 加了servers
无论是easyExcel或者poi等excel处理框架,在生成excel时都需要同步等待操作。但如果数据量较大,生成excel的时间会比较长,对于用户来说需要等待,影响体验。这时候就需要考虑使用流式生成excel。
下面提供了几种方案实现流失生成,能够在页面上直接开启下载。
excel2017版本之后,文件本身其实是一个zip文件,里面包含了多个xml文件,这些xml文件描述了excel的内容。所以我们可以通过流式生成xml文件,然后将这些xml文件打包成zip文件,最后返回给浏览器。
1 | public ExcelGenerator(InputStream template, Integer dataIndex, OutputStream outputStream) throws IOException { |
前端可以通过restful接口获取到excel内容,然后通过blob对象生成excel文件,最后通过a标签的download属性下载excel文件。
https://medium.com/@Nopziiemoo/create-excel-files-using-javascript-without-all-the-fuss-2c4aa5377813
使用dify.ai构建考试问答机器人
发现问卷星没有强制使用https,本地配置hosts
1 | 127.0.0.1 kaoshi.wjx.top |
实现一个代理服务,注入我们的js代码,实现答题时访问dify api 获取答案,将答案拼接在问题下面。将原来的地址改成http访问,也省需要mitm了。
当然也需要将代理返回内容里的https改成http,否则就访问不了了。
1 | from http.server import HTTPServer, BaseHTTPRequestHandler |
1 | document.addEventListener("DOMContentLoaded", (event) => { |
http://reports-archive.adm.cs.cmu.edu/anon/1995/CMU-CS-95-113.pdf
https://github.com/GNaive/naive-rete
由google gemini-pro-1.5回答
在 Rete 算法中,TOKEN 和 WEM (Working Memory Element) 是两个重要的概念,它们在规则引擎的工作机制中扮演着不同的角色。
TOKEN
WEM (Working Memory Element)
区别总结:
特征 | TOKEN | WEM |
---|---|---|
定义 | 事实或事件 | 工作内存中的事实或事件 |
作用 | 匹配规则条件 | 存储事实和事件 |
可变性 | 不可变 | 可变 |
变化追踪 | 不追踪 | 追踪 |
影响规则 | 触发规则 | 影响规则匹配 |
举例:
假设有一个规则:
1 | 规则: IF A = 1 AND B = 2 THEN C = 3 |
总结:
TOKEN 代表着具体的、不可变的事实或事件信息,用于匹配规则条件。WEM 代表着工作内存中的事实和事件,可变且跟踪变化,影响规则的匹配和执行。两者协同工作,共同构建了 Rete 算法的规则引擎机制。
在 Rete 算法中,Join Node 是非常重要的组成部分,它的作用是连接匹配不同规则条件的 Token,并将符合条件的 Token 组合起来,传递给后续节点。
简单来说,可以将 Join Node 想象成数据库中的 JOIN 操作,它根据一定的条件将来自不同来源的数据合并在一起。
更具体地说,Join Node 的作用体现在以下几个方面:
1. 模式匹配: 每个 Join Node 对应一个规则中的多个条件。当来自不同 Alpha Node (存储单个条件匹配结果的节点) 的 Token 进入 Join Node 时,它会检查这些 Token 是否满足连接条件。
2. 连接条件: Join Node 会存储连接条件,通常是用来比较两个 Token 的属性值是否相等。例如,一个 Join Node 的连接条件可能是 “Token1.customerID == Token2.customerID”,表示只有当两个 Token 的 customerID 属性相等时才会被连接。
3. Token 组合: 如果 Join Node 判断多个 Token 满足连接条件,就会将它们组合成一个新的 Token,这个新的 Token 包含了所有输入 Token 的信息。
4. 传递 Token: Join Node 会将组合后的新 Token 传递给它的后续节点,例如 Beta Node (存储部分或全部规则匹配结果的节点) 或另一个 Join Node。
Join Node 的优势:
举例说明:
假设有一个规则:
1 | 规则: IF Person.city == "北京" AND Order.customerID == Person.customerID THEN ... |
这个规则包含两个条件:
在 Rete 网络中,这两个条件会被分别存储在两个 Alpha Node 中。当有新的 Person 或 Order 对象进入系统时,对应的 Alpha Node 会生成 Token 并传递给后续的 Join Node。
Join Node 会检查来自两个 Alpha Node 的 Token 是否满足连接条件 “Order.customerID == Person.customerID”,如果满足,就会将它们组合成一个新的 Token,包含 Person 和 Order 的所有信息,并传递给后续节点。
总而言之,Join Node 是 Rete 算法中至关重要的组成部分,它通过连接匹配不同规则条件的 Token,将符合条件的 Token 组合起来,为高效执行复杂规则匹配提供了基础。
在 Rete 算法中,否定条件的实现依赖于一种特殊的节点类型,称为 Not Node (否定节点) 或 Negative Node。 Not Node 用于处理规则中包含 “NOT”、”!==” 等否定语义的条件。
Not Node 的工作机制:
Not Node 的特点:
示例说明:
假设有一条规则:
1 | 规则: IF Person.age > 18 AND NOT Order.product == "玩具" THEN ... |
这条规则包含一个否定条件: NOT Order.product == "玩具"
,表示只有当订单中的商品不是玩具时,规则才会被触发。
在 Rete 网络中,这个规则会被分解成多个节点,其中包含一个 Not Node 用于处理否定条件。
总结:
Not Node 是 Rete 算法中处理否定条件的关键机制,它通过监听多个分支的输入、比较 Token 并撤销不符合条件的数据,确保了只有满足所有条件(包括否定条件)的数据才会触发规则。
在 Rete 算法中,Conjunctive Negations(合取否定)指的是规则中包含多个否定条件,并且这些否定条件之间是 AND 关系的情况。例如:
1 | 规则:IF A > 10 AND NOT B = 20 AND NOT C = 30 THEN ... |
这个规则包含两个否定条件:NOT B = 20
和 NOT C = 30
, 而且它们之间是 AND 的关系,也就是说只有当 B 不等于 20 并且 C 不等于 30 时,规则才会被触发。
实现 Conjunctive Negations 的关键在于如何协调多个否定条件的匹配结果,确保只有当所有否定条件都满足时才会触发规则。
在 Rete 网络中,通常有以下几种方式实现 Conjunctive Negations:
1. 级联 Not Node:
这种方式简单直观,但效率较低,因为需要在多个 Not Node 之间传递 Token,增加了网络的复杂度。
2. 专用 Join Node:
这种方式效率较高,因为它避免了在多个节点之间传递 Token,但需要设计专门的 Join Node 来处理否定条件的逻辑。
3. Negation Join Node + 共享 Beta Memory:
这种方式结合了前两种方法的优点,既能高效地处理多个否定条件,又能保持 Rete 网络的结构简洁。
总而言之,Conjunctive Negations 是 Rete 算法中处理复杂规则的重要机制。选择哪种实现方式取决于具体的应用场景和性能需求。
利用groovy的元编程能力,实现以下逻辑。将function和匹配规则存储在数据库中,启动时读取相关数据,替换掉functions
字段,实现简单的模式匹配式的规则引擎。
例如
增加方法
1 | addFunc "familyStructure" { |
增加规则
1 | addAction {familyInsureds.count({i -> i.relation == 3}) > 3} {multiply '1.144'} |
无论函数规则都可以存储在数据库中,且该规则类可以通过缓存动态刷新替换。
问题:
Java线程的interrupt方法本质上是在线程对象上打了一个标记。实际上如果线程本身愿意的话,是可以忽略这个标记的。但是如果线程是处于阻塞状态,那么这个标记会使线程从阻塞状态中退出,并抛出一个InterruptedException异常。这个异常是一个检查异常,所以在调用interrupt方法的时候,要么捕获这个异常,要么抛出这个异常。这个异常的抛出会清除掉线程的中断标记。
利用interrupt可以实现一个可以终止的异步线程管理。
OpenAPI 规范(OAS)是一种通用的、和编程语言无关的 API 描述规范,使人类和计算机都可以发现和理解服务的功能,而无需访问源代码、文档或针对接口进行嗅探。正确定义后,使用者可以使用最少的实现逻辑来理解远程服务并与之交互。
OpenAPI 始于 Swagger 规范,Swagger 规范已于 2015 年捐赠给 Linux 基金会后改名为 OpenAPI,并定义最新的规范为 OpenAPI 3.0。
可以使用文本编辑器编写yaml按照规范的方式来定义API,也可以使用Swagger Editor在线编辑器来编辑。
定义好的API可以使用APIFOX或者RapiPdf生成接口文档,Swagger Editor也可以生成各种代码的server以及client代码。
更多的相关工具openapi.tools
问题:
wikiQA是一个问答系统,用于从confluence中获取文档,生成文档向量,然后用llama3-chinese-alpaca回答问题。
wiki_qa.py:
1 | from langchain_text_splitters import RecursiveCharacterTextSplitter |
app.py
1 | import streamlit as st |
llama3回答都是英文,因而改用lgkt/llama3-chinese-alpaca,但中文返回结果感觉比较单薄。
问题:
RecursiveCharacterTextSplitter
?与其他的splitter有什么区别?还有哪些splitter?chunk_size
和chunk_overlap
如何设置?Build a Retrieval Augmented Generation (RAG) App
Building a Confluence Q&A App with LangChain and ChatGPT
RAG行业交流中发现的一些问题和改进方法
树莓派4运行ollama