将AI大模型轻松集成至致远OA,系列教程带你一步步实现!

这篇文章讲解通过致远OA上传附件到文档中心后,把文档解析成文字,再把数据用大模型转成向量入库。用AI大模型进行文档的召回和基于文档的上下文进行简单对话。

思路:OA切入点

利用OA在附件上传和下载时提供拦截机制.

杀毒:附件上传时结合杀毒软件厂商提供的接口,对文件进行查毒和杀毒。

加密:附件上传下载时使用特定的加密算法对附件进行加解密。

舆情监控:扫描上传附件的内容,禁止含特定关键字的附件进入系统。

审计日志:对附件的上传和下载行为进行记录。

什么是Ollma?

Ollama是一个专为在本地机器上便捷部署和运行大型语言模型(LLM)而设计的工具。

什么是embedding?

embedding在机器学习和自然语言处理中,主要是将词汇、句子、段落甚至整个文档转换为实数向量的过程。这种转换过程允许模型在进行训练和推理过程中,能够理解和处理语言数据。这些向量能够捕捉单词语义上的相似性,例如词义相近的单词在嵌入空间中的向量会更接近。

大语言模型 LLM

LLM(Large Language Model,大语言模型)是指使用大量文本数据训练的深度学习模型,能够生成自然语言文本或理解语言文本的含义。‌ LLM的核心思想是通过大规模的无监督训练学习自然语言的模式和结构,模拟人类的语言认知和生成过程。这些模型通常采用Transformer架构,并通过自监督学习方法利用大量未标注文本进行训练。‌

LLM的使用场景非常广泛。首先,LLM可以用于文本生成,可以生成连贯的段落、文章、对话等,可以应用于自动写作、机器翻译等任务中。其次,LLM可以用于问答系统,可以回答复杂的问题,甚至进行对话式问答。再者,LLM可以用于语义理解和推理,可以进行情感分析、命名实体识别、文本分类等任务。此外,LLM还可以用于智能助理、机器人交互、自动摘要、信息提取等应用领域。

ChromaDB‌ 向量数据库

‌ChromaDB‌ 是一个轻量级向量数据库,主要用于存储和查询大规模、高维数据。它支持多种数据类型,包括文本、图像等,并且能够处理复杂的查询和大规模数据集。ChromaDB特别适用于自然语言处理(NLP)和机器学习应用,能够提供高效的向量检索和语义搜索功能‌。

环境搭建

安装Ollma

Ollma官网地址:https://ollama.com/

下载安装Ollma:

下载完成后,打开Ollma,安装后启动,其默认端口为11334,浏览器访问:http://localhost:11434 ,页面显示:Ollama is running,电脑右下角展示图标;

安装大模型

1、搜索大模型,查找运行大模型的命令,

地址:https://ollama.com/search

2、运行大模型,通过命令行下载大模型,命令行格式:ollmapull modelName,如:ollma pull llama3;

3、大模型一般要几个G,需要等一会;一般运行, llama3、 qwen(通义千问),这两个都是开源免费的,英文场景 用 llama3,中文场景用 qwen;

电脑如果内存小,建议运行一个就行了,8g内存的电脑肯定,开发肯定不行,至少16g

本次运行:qwen2.5:3b 这个3b的模型小适合开发用

通过 ollma list 可以查看 已下载的大模型:

启动大模型‍‍:

用命令行 :ollma run 模型名称,来启动大模型;启动后,可以立即输入内容与大模型进行对话,如下:

让他介绍一下LangChain

安装ChromaDB‌

1.安装:pip install chromadb ; 安装需要先安装Python,不要安装最新的,安装python=3.11.10 左右的版本最合适。

2.启动:chroma run :

把大模型接入致远OA

加入jar包

 `<properties>`      `<maven.compiler.source>8</maven.compiler.source>`    `<maven.compiler.target>8</maven.compiler.target>`  `<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>`      `<langchain4j.version>0.34.0</langchain4j.version>` `</properties>``<dependency>`    `<groupId>dev.langchain4j</groupId>`    `<artifactId>langchain4j-open-ai</artifactId>`            `<version>${langchain4j.version}</version>``</dependency>``<dependency>`    `<groupId>dev.langchain4j</groupId>`    `<artifactId>langchain4j-chroma</artifactId>`    `<version>${langchain4j.version}</version>``</dependency>``<!--     ollama       -->``<dependency>`    `<groupId>dev.langchain4j</groupId>`    `<artifactId>langchain4j-ollama</artifactId>`    `<version>${langchain4j.version}</version>``</dependency>``<!--    chroma 向量数据库        -->``<dependency>`    `<groupId>io.github.amikos-tech</groupId>`    `<artifactId>chromadb-java-client</artifactId>`    `<version>0.1.7</version>``</dependency>`

通过监听FileUploadEvent事件可以拦截附件上传进行处理。

/**` `* 〈监听附件上传〉` `*` `* @author OA同学` `* @create 2024/11/11` `* @since 1.0.0` `*/``public class RAGFileEvent {``   `    `@ListenEvent(event = FileUploadEvent.class)`    `public void onFileUpload(FileUploadEvent evt) throws Exception {`        `// 取得上传的文件`        `FileItem fileItem = evt.getFileItem();`        `String originalFilename = fileItem.getOriginalFilename();`        `if (originalFilename.contains(".txt")) {`            `//保存文件到临时目录`            `String systemTempFolder = SystemEnvironment.getSystemTempFolder();`            `String pathname = systemTempFolder + File.separator + UUIDUtil.getUUIDString() + File.separator + originalFilename;`            `CtpFile tempFile = new CtpFile(pathname);`            `InputStream inputStream = fileItem.getInputStream();`            `GlobalFileUtils.saveCtpFile(inputStream, tempFile);``   `            `//解析文件 Document`            `Document document = LangChainUtils.getDocument(pathname);`                        `//拆分文件内容`                        `//文本向量化`                        `//向量库存储`                        `//向量库检索`                        `//与LLM交互`            `String chat=LangChainUtils.llmChat(message);`        `}`    `}``}

解析文件

把文件解析成langchain4j的Document对象。

public static Document getDocument(String fileName) {`    `URL docUrl = LangChainUtils.class.getClassLoader().getResource(fileName);`    `if (docUrl == null) {`        `log.error("未获取到文件");`    `}`    `Document document = null;`    `try {`        `Path path = Paths.get(docUrl.toURI());`        `document = FileSystemDocumentLoader.loadDocument(path);`    `} catch (URISyntaxException e) {`        `log.error("加载文件发生异常", e);`    `}`    `return document;``}

拆分文件

//======================= 拆分文件内容=======================``// 参数:分段大小(一个分段中最大包含多少个token)、重叠度(段与段之前重叠的token数)、分词器(将一段文本进行分词,得到token)``DocumentByLineSplitter lineSplitter = new DocumentByLineSplitter(200, 0, new OpenAiTokenizer());``List<TextSegment> segments = lineSplitter.split(document);``log.info("segment的数量是: {}", segments.size());``   ``//查看分段后的信息``segments.forEach(segment -> log.info("========================segment:" +segment.text()));

文本向量化并保存向量

 `private static final String CHROMA_DB_NAME = "rag-oa";` `private static final String CHROMA_URL = "http://localhost:8000"` `private static final String OLLAMA_URL = "http://localhost:11434";` `private static final String OLLAMA_NAME = "qwen2.5:3b";` ` //======================= 文本向量化=======================`  `OllamaEmbeddingModel embeddingModel = OllamaEmbeddingModel.builder()`          `.baseUrl(Optional.ofNullable(AppContext.getSystemProperty("rag.ollama_url")).orElse(OLLAMA_URL))`          `.modelName(Optional.ofNullable(AppContext.getSystemProperty("rag.ollama_name")).orElse(OLLAMA_NAME))`          `.build();``//======================= 向量库存储=======================`   `//创建向量数据库`  `EmbeddingStore<TextSegment> embeddingStore = ChromaEmbeddingStore.builder()`          `.baseUrl(Optional.ofNullable(AppContext.getSystemProperty("rag.chroma_url")).orElse(CHROMA_URL))`          `.collectionName(Optional.ofNullable(AppContext.getSystemProperty("rag.chroma_db_name")).orElse(CHROMA_DB_NAME ))`          `.build();`  `segments.forEach(segment -> {`      `Embedding e = embeddingModel.embed(segment).content();`      `embeddingStore.add(e, segment);`  `});`

向量库检索

//======================= 向量库检索=======================``String qryText = "待办";``Embedding queryEmbedding = embeddingModel.embed(qryText).content();``   ``EmbeddingSearchRequest embeddingSearchRequest = EmbeddingSearchRequest.builder().queryEmbedding(queryEmbedding).maxResults(1).build();``EmbeddingSearchResult<TextSegment> embeddedEmbeddingSearchResult = embeddingStore.search(embeddingSearchRequest);``List<EmbeddingMatch<TextSegment>> embeddingMatcheList = embeddedEmbeddingSearchResult.matches();``EmbeddingMatch<TextSegment> embeddingMatch = embeddingMatcheList.get(0);``TextSegment textSegment = embeddingMatch.embedded();``log.info("查询结果:" +textSegment.text());

与LLM交互

//======================= 与LLM交互=======================``PromptTemplate promptTemplate = PromptTemplate.from("基于如下信息用中文回答:\n" + "{{context}}\n" + "提问:\n" + "{{question}}");``Map<String, Object> variables = new HashMap<>();``//以向量库检索到的结果作为LLM的信息输入``variables.put("context", textSegment.text());``variables.put("question", "我总共几个待办事项");``Prompt prompt = promptTemplate.apply(variables);``   ``//连接大模型``OllamaChatModel ollamaChatModel = OllamaChatModel.builder()`        `.baseUrl(Optional.ofNullable(AppContext.getSystemProperty("rag.ollama_url")).orElse(OLLAMA_URL))`        `.modelName(Optional.ofNullable(AppContext.getSystemProperty("rag.ollama_name")).orElse(OLLAMA_NAME))`        `.build();``UserMessage userMessage = prompt.toUserMessage();``Response<AiMessage> aiMessageResponse = ollamaChatModel.generate(userMessage);``AiMessage response = aiMessageResponse.content();``log.info("大模型回答: "+ response.text());

我们写个接口测试一下:

@Path("ai")``@Produces({"application/json"})``public class AIRestResource extends BaseResource {`    `private static final Log log = LogFactory.getLog(AIRestResource.class);``   `    `@POST`    `@Path("/message")`    `public Response mesasge(@QueryParam("message") String message) {`         `//与LLM交互`        `return ok(LangChainUtils.llmChat(message));`    `}``}

上传一个测试.txt,内容如下

在致远OA中有2个待办协同,``有3个待办公文,``有1个10点的会议

调用接口输入问题:“我总共几个待办事项”,程序打印如下结果:

根据你的描述,在致远OA中你有以下几个待办事项:``- 两个待办协同任务``- 三个待办公文任务``- 一次在10点开始的会议``将这些加起来,你可以得出总共的待办事项目数是:``\[ 2 + 3 + 1 = 6 \]``所以,你总共有 **六个** 待办事项目。

总结:

1、上面是一个简单的入门级实践AI大模型。

2、回答系统可以使用Spring AI 和Spring AI ALibaba来搭建这个两个社区都很活跃。

3、集成在OA中一般都用langchain 另外它还有很多很强大的能力,prompt Fomat、output Fomat、工具调用、memory存储等,这个社区也非常活跃;

4、我一直在思考,客开这行是否还可以做,AI这么火,能否用AI来解决客户的需求,我觉得客开还是能一直做,大家对用AI来帮助客开有什么看法,欢迎在评论区讨论。

5、接下来我将用AI大模型把OA的大部分功能重做一遍。(做好后我会第一时间发出来,欢迎大家关注我的微信公众号,有什么意见欢迎留言!)

在这里插入图片描述

如何学习AI大模型?

我在一线互联网企业工作十余年里,指导过不少同行后辈。帮助很多人得到了学习和成长。

我意识到有很多经验和知识值得分享给大家,也可以通过我们的能力和经验解答大家在人工智能学习中的很多困惑,所以在工作繁忙的情况下还是坚持各种整理和分享。但苦于知识传播途径有限,很多互联网行业朋友无法获得正确的资料得到学习提升,故此将并将重要的AI大模型资料包括AI大模型入门学习思维导图、精品AI大模型学习书籍手册、视频教程、实战学习等录播视频免费分享出来。

在这里插入图片描述

第一阶段: 从大模型系统设计入手,讲解大模型的主要方法;

第二阶段: 在通过大模型提示词工程从Prompts角度入手更好发挥模型的作用;

第三阶段: 大模型平台应用开发借助阿里云PAI平台构建电商领域虚拟试衣系统;

第四阶段: 大模型知识库应用开发以LangChain框架为例,构建物流行业咨询智能问答系统;

第五阶段: 大模型微调开发借助以大健康、新零售、新媒体领域构建适合当前领域大模型;

第六阶段: 以SD多模态大模型为主,搭建了文生图小程序案例;

第七阶段: 以大模型平台应用与开发为主,通过星火大模型,文心大模型等成熟大模型构建大模型行业应用。

在这里插入图片描述

👉学会后的收获:👈
• 基于大模型全栈工程实现(前端、后端、产品经理、设计、数据分析等),通过这门课可获得不同能力;

• 能够利用大模型解决相关实际项目需求: 大数据时代,越来越多的企业和机构需要处理海量数据,利用大模型技术可以更好地处理这些数据,提高数据分析和决策的准确性。因此,掌握大模型应用开发技能,可以让程序员更好地应对实际项目需求;

• 基于大模型和企业数据AI应用开发,实现大模型理论、掌握GPU算力、硬件、LangChain开发框架和项目实战技能, 学会Fine-tuning垂直训练大模型(数据准备、数据蒸馏、大模型部署)一站式掌握;

• 能够完成时下热门大模型垂直领域模型训练能力,提高程序员的编码能力: 大模型应用开发需要掌握机器学习算法、深度学习框架等技术,这些技术的掌握可以提高程序员的编码能力和分析能力,让程序员更加熟练地编写高质量的代码。

在这里插入图片描述

1.AI大模型学习路线图
2.100套AI大模型商业化落地方案
3.100集大模型视频教程
4.200本大模型PDF书籍
5.LLM面试题合集
6.AI产品经理资源合集

👉获取方式:
😝有需要的小伙伴,可以保存图片到wx扫描二v码免费领取【保证100%免费】🆓

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值