当前位置: 首页 > article >正文

Java + LangChain 实战入门,开发大语言模型应用!

在 Baeldung 上看到了一篇介绍基于 Java + LangChain 开发大语言模型应用的基础入门文章,写的非常不错,非常适合初学者。于是,我抽空翻译了一下。

  • 原文地址:https://www.baeldung.com/java-langchain-basics
  • 翻译: JavaGuide(转载请注明)

1. 简介

在本教程中,我们将详细探讨 LangChain,一个用于开发基于语言模型的应用程序的框架。我们将首先了解语言模型的基础概念,这些知识将对本教程有所帮助。

尽管 LangChain 主要提供 Python 和 JavaScript/TypeScript 版本,但也可以在 Java 中使用 LangChain。我们会讨论 LangChain 作为框架的构建模块,然后尝试在 Java 中进行实验。

2. 背景

在深入探讨为什么需要一个用于构建基于语言模型的应用程序的框架之前,我们需要弄清楚语言模型是什么,并了解使用语言模型时可能遇到的一些典型复杂性。

2.1. 大型语言模型

语言模型是自然语言的概率模型,可以生成一系列单词的概率。大型语言模型(LLM)则是以其规模庞大而著称,通常包含数十亿参数的人工神经网络。

大型语言模型通常通过在大量未标记数据上进行预训练,使用自监督学习和弱监督学习技术。之后,通过微调提示词工程等技术将预训练模型适配于特定任务:

大型语言模型

大型语言模型可以执行多种自然语言处理任务,如语言翻译、内容摘要等。此外,它们还具备生成内容的能力,因此在回答问题等应用场景中非常有用。

几乎所有主流云服务提供商都在其服务中引入了大型语言模型。例如,Microsoft Azure 提供了 Llama 2 和 OpenAI GPT-4,Amazon Bedrock 提供了 AI21 Labs、Anthropic、Cohere、Meta 和 Stability AI 的模型。

2.2. 提示词工程

大型语言模型是一种基础模型,经过大规模文本数据的训练后,可以捕捉人类语言的语法和语义。然而,为了让模型执行特定任务,它们需要进一步调整。

提示词工程(Prompt engineering)是让语言模型完成特定任务的最快捷方法之一。它通过结构化文本向模型描述任务目标,使其能够理解并执行任务:

提示词工程

提示词帮助大型语言模型执行上下文学习,这种学习是暂时的。通过提示词工程,我们可以促进大型语言模型的安全使用,并构建新的功能,比如将领域知识和外部工具整合到模型中。

这一领域目前是一个活跃的研究方向,不断涌现新的技术。然而,诸如 链式思维提示 等技术已经变得颇为流行。这种方法的核心是让大型语言模型在给出最终答案之前,将问题分解为一系列中间步骤。

2.3. 词向量

如前所述,大型语言模型能够高效处理自然语言。如果我们将自然语言中的单词表示为词向量(Word Embeddings ),模型的性能将显著提升。词向量是能够编码单词语义的实值向量

词向量通常通过算法生成,例如 Word2vec 或 GloVe。

GloVe 是一种无监督学习算法,在语料库的全局词共现统计上进行训练:

Word Embedding Illustration

在提示词工程中,我们将提示转换成词向量,这使得模型更容易理解和响应提示。此外,它也对增强我们提供给模型的上下文非常有帮助,从而使模型能够给出更具上下文意义的回答。

例如,我们可以从现有数据集中生成词向量并将其存储在向量数据库中。然后,我们可以使用用户提供的输入在向量数据库中执行语义搜索,并将搜索结果作为附加上下文提供给模型。

3. 使用 LangChain 构建 LLM 技术栈

正如我们已经了解的那样,创建有效的提示词是成功利用 LLM 的关键元素。这包括使与语言模型的交互具有上下文感知能力,并依赖语言模型进行推理。

为此,我们需要执行多项任务,例如为提示词创建模板、调用语言模型,以及从多种来源提供用户特定数据。为了简化这些任务,我们需要一个像 LangChain 这样的框架作为 LLM 技术栈的一部分:

使用 LangChain 构建 LLM 技术栈

该框架还帮助开发需要链式调用多个语言模型的应用程序,并能够回忆起过去与语言模型过去交互的信息。此外,还有更复杂的用例,例如将语言模型用作推理引擎。

最后,我们可以执行日志记录、监控、流式处理以及其他重要的维护和故障排除任务。LLM 技术栈正在快速发展以应对许多此类问题,而 LangChain 正迅速成为 LLM 技术栈的宝贵组成部分。

4. 面向 Java 的 LangChain

LangChain 于 2022 年作为开源项目推出,凭借社区支持迅速发展壮大。最初是由 Harrison Chase 开发的 Python 项目,后来成为 AI 领域增长最快的初创企业之一。

随后,JavaScript/TypeScript 版本的 LangChain 于 2023 年初推出,并迅速流行起来,支持多个 JavaScript 环境,如 Node.js、浏览器、CloudFlare workers、Vercel/Next.js、Deno 和 Supabase Edge functions。

然而,目前没有官方的 Java 版本 LangChain 可供 Java 或 Spring 应用使用。不过,社区开发了 Java 版本 LangChain,称为 LangChain4j ,支持 Java 8 或更高版本,并兼容 Spring Boot 2 和 3。

LangChain 的各种依赖项可以在 Maven Central 上找到。根据我们使用的功能,可能需要在应用程序中添加一个或多个依赖项

<dependency><groupId>dev.langchain4j</groupId><artifactId>langchain4j</artifactId><version>0.23.0</version>
</dependency>

5. LangChain 的构建模块

LangChain 为我们的应用程序提供了多种价值主张,这些功能以模块化组件的形式提供。模块化组件不仅提供了有用的抽象,还包含了一系列操作语言模型的实现。接下来,我们将通过 Java 示例来讨论其中的一些模块。

5.1. 模型输入/输出(Models I/O)

在使用任何语言模型时,我们需要具备与其交互的能力。LangChain 提供了必要的构建模块,例如模板化提示的能力,以及动态选择和管理模型输入的能力。此外,我们还可以使用输出解析器从模型输出中提取信息:

LangChain 模型

提示模板(Prompt Templates)是用于生成语言模型提示的预定义配方,可以包括指令、少样本示例和特定上下文:

PromptTemplate promptTemplate = PromptTemplate.from("Tell me a {{adjective}} joke about {{content}}..");
Map<String, Object> variables = new HashMap<>();
variables.put("adjective", "funny");
variables.put("content", "computers");
Prompt prompt = promptTemplate.apply(variables);

5.2. 内存

通常,一个利用大型语言模型(LLM)的应用程序会有一个对话界面。对话的一个重要方面是能够引用对话中先前的信息。这种存储过去交互信息的能力称为内存

LangChain 内存

LangChain 提供了一些关键功能,可以为应用程序添加内存。例如,我们需要能够从内存中读取信息以增强用户输入,同时还需要将当前运行的输入和输出写入内存:

ChatMemory chatMemory = TokenWindowChatMemory.withMaxTokens(300, new OpenAiTokenizer(GPT_3_5_TURBO));
chatMemory.add(userMessage("你好,我叫 Kumar"));
AiMessage answer = model.generate(chatMemory.messages()).content();
System.out.println(answer.text()); // 你好 Kumar!今天我能为您做些什么?
chatMemory.add(answer);
chatMemory.add(userMessage("我叫什么名字?"));
AiMessage answerWithName = model.generate(chatMemory.messages()).content();
System.out.println(answerWithName.text()); // 您的名字是 Kumar。
chatMemory.add(answerWithName);

在这里,我们使用 TokenWindowChatMemory 实现了固定窗口聊天内存,它允许我们读取和写入与语言模型交换的聊天消息。

LangChain 还提供更复杂的数据结构和算法,以便从内存中返回选定的消息, 而不是返回所有内容。例如,它支持返回过去几条消息的摘要,或者仅返回与当前运行相关的消息。

5.3. 检索(Retrieval)

大型语言模型通常是在大量的文本语料库上进行训练的。因此,它们在处理通用任务时表现得非常高效,但在处理特定领域任务时可能效果不佳。为了解决这一问题,我们需要在生成阶段检索相关的外部数据,并将其传递给语言模型

这个过程被称为检索增强生成(Retrieval Augmented Generation,RAG)。RAG 有助于将模型的生成过程与相关且准确的信息结合,同时也让我们更深入地了解模型的生成过程。LangChain 提供了构建 RAG 应用程序所需的核心组件:

LangChain Retrieval

首先,LangChain 提供了文档加载器 FileSystemDocumentLoader,用于从存储位置检索文档。然后,LangChain 还提供了转换器,用于进一步处理文档,例如将大型文档分割成更小的块:

Document document = FileSystemDocumentLoader.loadDocument("simpson's_adventures.txt");
DocumentSplitter splitter = DocumentSplitters.recursive(100, 0,new OpenAiTokenizer(GPT_3_5_TURBO));
List<TextSegment> segments = splitter.split(document);

在这里,我们使用 FileSystemDocumentLoader 从文件系统中加载文档。然后使用 OpenAiTokenizer 将文档分割成更小的段落。

为了提高检索效率,这些文档通常会被转换成嵌入(embeddings),并存储在向量数据库中。LangChain 支持多种嵌入提供商和方法,并与几乎所有主流的向量存储集成:

EmbeddingModel embeddingModel = new AllMiniLmL6V2EmbeddingModel();
List<Embedding> embeddings = embeddingModel.embedAll(segments).content();
EmbeddingStore<TextSegment> embeddingStore = new InMemoryEmbeddingStore<>();
embeddingStore.addAll(embeddings, segments);

在这里,我们使用 AllMiniLmL6V2EmbeddingModel 为文档段落创建嵌入,然后将嵌入存储在内存中的向量存储中。

现在,我们的外部数据已经以嵌入的形式存储在向量存储中,可以从中进行检索。LangChain 支持多种检索算法,例如简单的语义搜索和更复杂的集成检索器(ensemble retriever):

String question = "Who is Simpson?";
// 假设该问题的答案包含在我们之前处理的文档中。
Embedding questionEmbedding = embeddingModel.embed(question).content();
int maxResults = 3;
double minScore = 0.7;
List<EmbeddingMatch<TextSegment>> relevantEmbeddings = embeddingStore.findRelevant(questionEmbedding, maxResults, minScore);

我们为用户的问题生成嵌入,然后使用该问题的嵌入从向量存储中检索相关的匹配项。现在,我们可以将检索到的相关内容作为上下文,添加到我们打算发送给模型的提示中。

6. LangChain 的复杂应用

到目前为止,我们已经了解了如何使用单个组件来创建一个基于语言模型的应用程序。LangChain 还提供了构建更复杂应用程序的组件。例如,我们可以使用链(Chains)和代理(Agents)来构建更加自适应、功能增强的应用程序。

6.1. 链(Chains)

通常,一个应用程序需要按特定顺序调用多个组件。在 LangChain 中,这被称为链(Chain)。链简化了开发更复杂应用程序的过程,并使调试、维护和改进更加容易。

链还可以组合多个链来构建更复杂的应用程序,这些应用程序可能需要与多个语言模型交互。LangChain 提供了创建此类链的便捷方式,并内置了许多预构建链:

ConversationalRetrievalChain chain = ConversationalRetrievalChain.builder().chatLanguageModel(chatModel).retriever(EmbeddingStoreRetriever.from(embeddingStore, embeddingModel)).chatMemory(MessageWindowChatMemory.withMaxMessages(10)).promptTemplate(PromptTemplate.from("Answer the following question to the best of your ability: {{question}}\n\nBase your answer on the following information:\n{{information}}")).build();

在这里,我们使用了预构建的链 ConversationalRetrievalChain,它允许我们将聊天模型与检索器、内存和提示模板结合使用。现在,我们可以简单地使用该链来执行用户查询:

String answer = chain.execute("Who is Simpson?");

该链提供了默认的内存和提示模板,我们可以根据需要进行覆盖。创建自定义链也非常容易。链的能力使我们能够更轻松地实现复杂应用程序的模块化实现。

6.2. 代理(Agents)

LangChain 还提供了更强大的结构,例如代理(Agent)。与链不同,代理将语言模型用作推理引擎,以确定应该采取哪些操作以及操作的顺序。我们还可以为代理提供访问合适工具的权限,以执行必要的操作。

在 LangChain4j 中,代理作为 AI 服务(AI Services)提供,用于声明性地定义复杂的 AI 行为。让我们看看如何通过提供一个计算器工具,为 AI 服务赋能,从而使语言模型能够执行计算。

首先,我们定义一个包含一些基本计算功能的类,并用自然语言描述每个函数,这样模型可以理解:

public class AIServiceWithCalculator {static class Calculator {@Tool("Calculates the length of a string")int stringLength(String s) {return s.length();}@Tool("Calculates the sum of two numbers")int add(int a, int b) {return a + b;}}

接下来,我们定义一个接口,用于构建我们的 AI 服务。这里的接口相对简单,但也可以描述更复杂的行为:

interface Assistant {String chat(String userMessage);
}

然后,我们使用 LangChain4j 提供的构建器工厂,通过定义的接口和工具创建一个 AI 服务:

Assistant assistant = AiServices.builder(Assistant.class).chatLanguageModel(OpenAiChatModel.withApiKey(<OPENAI_API_KEY>)).tools(new Calculator()).chatMemory(MessageWindowChatMemory.withMaxMessages(10)).build();

完成了!现在,我们可以向语言模型发送包含计算任务的问题:

String question = "What is the sum of the numbers of letters in the words \"language\" and \"model\"?";
String answer = assistant.chat(question);
System.out.println(answer); // The sum of the numbers of letters in the words "language" and "model" is 13.

运行这段代码后,我们会发现语言模型现在能够执行计算。

需要注意的是,语言模型在执行某些任务时可能会遇到困难,例如需要时间和空间概念的任务或复杂的算术操作。然而,我们可以通过为模型提供必要的工具来解决这些问题。

7. 总结

在本教程中,我们探讨了创建基于大型语言模型的应用程序的一些基本元素。此外,我们讨论了将 LangChain 作为技术栈的一部分对开发此类应用程序的重要价值。

这使得我们能够探索 LangChain 的 Java 版本 —— LangChain4j 的一些核心组件 。这些库未来将快速发展,它们会让开发由语言模型驱动的应用程序的过程变得更成熟和有趣!

相关文章:

Java + LangChain 实战入门,开发大语言模型应用!

在 Baeldung 上看到了一篇介绍基于 Java LangChain 开发大语言模型应用的基础入门文章&#xff0c;写的非常不错&#xff0c;非常适合初学者。于是&#xff0c;我抽空翻译了一下。 原文地址&#xff1a;https://www.baeldung.com/java-langchain-basics翻译&#xff1a; Java…...

el-date-picker时间范围 编辑回显后不能修改问题

el-date-picker daterange时间范围 编辑回显后不能修改 <el-form-item:label"LABELS.gplanRecordDateLabel"prop"gplanRecordDate"><el-date-pickerstyle"width: 300px"v-model"formData.gplanRecordDate"type"daterang…...

Java多线程与高并发专题—— CyclicBarrier 和 CountDownLatch 有什么异同?

引入 上一篇我们了解CountDownLatch的原理和常见用法&#xff0c;在CountDownLatch的源码注释中&#xff0c;有提到&#xff1a; 另一种典型用法是将一个问题分解为 N 个部分&#xff0c;用一个Runnable描述每个部分&#xff0c;该Runnable执行相应部分的任务并对闭锁进行倒计…...

leetcode543.二叉树的直径

当前顶点作为拐点时&#xff0c;求左子树加上右子树的高度可以求出该通过该顶点的直径大小&#xff0c;再对该顶点和左右子节点作为拐点时直径大小进行比对&#xff0c;返回最大值 缺点是递归了多次 /*** Definition for a binary tree node.* public class TreeNode {* …...

Java EE 进阶:MyBatis案例练习

表白墙 首先我们先准备一下数据库的数据 创建一个信息表 DROP TABLE IF EXISTS message_info;CREATE TABLE message_info (id INT ( 11 ) NOT NULL AUTO_INCREMENT,from VARCHAR ( 127 ) NOT NULL,to VARCHAR ( 127 ) NOT NULL,message VARCHAR ( 256 ) NOT NULL,delete_fla…...

Dubbo 全面解析:从 RPC 核心到服务治理实践

一、分布式系统与 RPC 框架概述 在当今互联网时代&#xff0c;随着业务规模的不断扩大&#xff0c;单体架构已经无法满足高并发、高可用的需求&#xff0c;分布式系统架构成为主流选择。而在分布式系统中&#xff0c;远程服务调用&#xff08;Remote Procedure Call&#xff0…...

路由选型终极对决:直连/静态/动态三大类型+华为华三思科配置差异,一张表彻底讲透!

路由选型终极对决&#xff1a;直连/静态/动态三大类型华为华三思科配置差异&#xff0c;一张表彻底讲透&#xff01; 一、路由&#xff1a;互联网世界的导航系统二、路由类型深度解析三者的本质区别 三、 解密路由表——网络设备的GPS华为&#xff08;Huawei&#xff09;华三&a…...

[微信小程序]对接sse接口

[微信小程序]对接sse接口 在uni开发中&#xff0c;在微信小程序中实现sse接口请求 相关连接 微信小程序对接SSE接口记录 uni中实现sse代码 注意的坑点 接收的并不是字符串&#xff0c;而是ArrayBuffer模拟流推送并不是流推送&#xff0c;会有data:字符扰乱推送并不是完全按照…...

01 相机标定与相机模型介绍

学完本文,您将了解不同相机模型分类、内参意义,及对应的应用代码模型 标定的意义 建模三维世界点投影到二维图像平面的过程。标定输出的是相机模型。 相机模型 相机模型可以解理解为投影模型 +...

【商城实战(72)】解锁用户评价与晒单功能开发秘籍

【商城实战】专栏重磅来袭&#xff01;这是一份专为开发者与电商从业者打造的超详细指南。从项目基础搭建&#xff0c;运用 uniapp、Element Plus、SpringBoot 搭建商城框架&#xff0c;到用户、商品、订单等核心模块开发&#xff0c;再到性能优化、安全加固、多端适配&#xf…...

2025.03.27【基因分析新工具】| MAST:解锁基因表达差异分析与网络构建

文章目录 1. MAST工具简介&#xff1a;探索生物信息分析的新利器1.1 什么是MAST工具&#xff1f;1.2 MAST工具的优势1.3 MAST工具的应用场景 2. MAST的安装方法&#xff1a;轻松入门的第一步2.1 安装R语言环境2.2 安装MAST包2.3 安装依赖库 3. MAST常用命令&#xff1a;掌握数据…...

浅谈WebSocket-FLV

FLV是一种视频数据封装格式&#xff0c;这种封装被标准通信协议HTTP-FLV和RTMP协议应用。 而WebSocket-FLV是一种非标的FLV封装数据从后端发送到前端的一种方式。 在WebSocket的url请求中&#xff0c;包含了需要请求设备的视频相关信息&#xff0c;在视频数据到达时&#xff0c…...

SICAR标准 汽车焊装生产线触摸屏操作说明

目录 SIMATIC HMI 是西门子工业自动化解决方案的核心组件&#xff0c;支持实时设备监控与交互&#xff0c;文档中展示了其在焊装生产线中以SICAR标准为基础的具体应用&#xff0c;包括车型切换&#xff08;如 AY2/A26&#xff09;、KMC 夹具配置及能源效率分析&#xff0c;适用…...

CentOS 7 磁盘及分区管理笔记

一、查看磁盘信息 1. lsblk 命令 作用&#xff1a;列出系统中所有的块设备&#xff08;包括磁盘、分区等&#xff09;及其相关信息&#xff0c;如设备名称、大小、类型等。 命令格式&#xff1a;lsblk 示例&#xff1a; lsblk NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT sd…...

Unity Standard Shader 解析(一)之ForwardBase(标准版)

一、ForwardBase // Base forward pass (directional light, emission, lightmaps, ...)Pass{Name "FORWARD"Tags { "LightMode" "ForwardBase" }Blend [_SrcBlend] [_DstBlend]ZWrite [_ZWrite]CGPROGRAM#pragma target 3.0// --------------…...

关于bug总结记录

1、vs中出现bug error C1083:无法打开文件 链接&#xff1a;vs中出现bug error C1083:无法打开文件_vs20151083错误解决方法-CSDN博客 2、 VS小技巧&#xff1a;系统却提示&#xff1a;示msvcp120.dll丢失 链接&#xff1a;VS小技巧&#xff1a;系统却提示&#xff1a;示msvc…...

go - grpc入门

前期准备 工具安装及使用 grpc开发 编写proto文件 proto文件是符合Protocol Buffers语言规范的数据交换协议文件&#xff0c;就像以前WebService定义服务时使用的XML文件。现在一般都是用proto3了&#xff0c;这里创建一个名为 hello.proto 的文件&#xff0c;放到项目的pr…...

Selenium Web自动化如何快速又准确的定位元素路径,强调一遍是元素路径

如果文章对你有用&#xff0c;请给个赞&#xff01; 匹配的ChromeDriver和浏览器版本是更好完成自动化的基础&#xff0c;可以从这里去下载驱动程序&#xff1a; 最全ChromeDriver下载含win linux mac 最新版本134.0.6998.165 持续更新..._chromedriver 134-CSDN博客 如果你问…...

鸿蒙-全屏播放页面(使用相对布局)---持续更新中

最终实现效果图&#xff1a; 实现步骤 创建FullScreenPlay.ets全品播放页面 并将其修改为启动页面。 全屏播放&#xff0c;屏幕必然横过来&#xff0c;所以要将窗口横过来。 编辑 src/main/ets/entryability/EntryAbility.ets 若写在/EntryAbility.ets中&#xff0c;则所有…...

全面讲解python的uiautomation包

在常规的模拟鼠标和键盘操作&#xff0c;我们一般使用pyautogui&#xff0c;uiautomation模块不仅能直接支持这些操作&#xff0c;还能通过控件定位方式直接定位到目标控件的位置&#xff0c;而不需要自己去获取对应坐标位置。uiautomation模块不仅支持任意坐标位置截图&#x…...

CentOS 7 源码安装libjsoncpp-1.9.5库

安装依赖工具 sudo yum install cmake make gcc cmake 需要升级至 3.8.0 以上可参考&#xff1a;CentOS安装CMakegcc 需要升级至9.0 以上可参考&#xff1a;CentOS 7升级gcc版本 下载源码 wget https://github.com/open-source-parsers/jsoncpp/archive/refs/tags/1.9.5.…...

备赛蓝桥杯之第十六届模拟赛第1期职业院校组第五题:回忆画廊

提示&#xff1a;本篇文章仅仅是作者自己目前在备赛蓝桥杯中&#xff0c;自己学习与刷题的学习笔记&#xff0c;写的不好&#xff0c;欢迎大家批评与建议 由于个别题目代码量与题目量偏大&#xff0c;请大家自己去蓝桥杯官网【连接高校和企业 - 蓝桥云课】去寻找原题&#xff0…...

闭包、装饰器学习笔记(第二次学习)

以下是整理后的笔记格式&#xff1a; --- # 闭包与装饰器 ## 一、闭包的概念&#xff0c;作用&#xff0c;条件### 作用&#xff1a; 1. **保存外部函数的变量**&#xff1a;可以让一个变量常驻于内存。 python def func():a 10def inner():print(a)return areturn inne…...

Windows下docker使用教程

docker安装 镜像制作镜像加载容器创建更新镜像导出镜像 Windows10安装dockerdocker image制作docker 镜像加载docker 容器创建更新imageimage 导出为.tar文件 #以Windows10 、11为例 linux和Windows区别在于docker安装的程序是哪个操作系统的&#xff0c;后面的内容其实不变 …...

Java项目生成接口文档的方案

文章目录 问题&#xff1a;Java项目生成接口文档的方案方案一&#xff1a;Swagger3.0方案二&#xff1a;Apipost两者对比 问题&#xff1a;Java项目生成接口文档的方案 需求 1、需要生成生成时间&#xff0c;作者名称&#xff0c;项目名称&#xff0c;接口名称&#xff0c;请…...

Android第七次面试总结(Java和kotlin源码级区别 )

Java 和 Kotlin 作为用于软件开发尤其是 Android 和后端开发的编程语言&#xff0c;在源码层面存在诸多区别&#xff0c;下面从多个方面进行深入讲解&#xff1a; 1. 基础语法与变量声明 变量声明方式 Java&#xff1a;变量声明时必须明确指定数据类型&#xff0c;并且若要声…...

北斗导航 | 改进奇偶矢量法的接收机自主完好性监测算法原理,公式,应用,RAIM算法研究综述,matlab代码

改进奇偶矢量法的接收机自主完好性监测算法研究 摘要 接收机自主完好性监测(RAIM)是保障全球导航卫星系统(GNSS)安全性的核心技术。针对传统奇偶矢量法在噪声敏感性、多故障隔离能力上的缺陷,本文提出一种基于加权奇偶空间与动态阈值的改进算法。通过引入观测值权重矩阵重…...

案例实践 | 招商局集团以长安链构建“基于DID的航运贸易数据资产目录链”

概览 案例名称 基于DID的航运贸易数据资产目录链 业主单位 招商局集团 上线时间 2024年10月 用户群体 供数用数企业和个人 用户规模 集团内20企业 案例背景 招商局集团深入落实“促进数据高效流通使用、赋能实体经济”精神&#xff0c;深化集团数字化水平&#xff0c…...

【C++】httplib:轻量级的 HTTP 服务器和客户端

本教程采用渐进式讲解方式&#xff0c;适用于 MinGW 环境。我们将从 httplib 的基本概念入手&#xff0c;通过一个小型 Demo 展示其核心用法&#xff0c;最后深入探讨高级功能与实际应用场景。 1. 简介 1.1 httplib 基本概念 httplib 是一个轻量级的 C HTTP 库&#xff0c;设…...

【算法工程】RAG:针对linux下文档解析出现乱码问题的解决

RAG服务中&#xff0c;非常关键的模块是文档解析。但将解析服务部署到linux平台&#xff0c;解析word、ppt等文档时可能就会出现乱码&#xff0c;核心原因是系统未能识别出对应的字体。因为word、ppt在windows下是最适配的&#xff0c;如果将解析服务部署到linux上&#xff0c;…...