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

本地大模型编程实战(19)RAG(Retrieval Augmented Generation,检索增强生成)(3)

文章目录

    • 准备
    • 创建矢量数据库对象
    • 创建 LangGraph 链
      • 将检索步骤转化为工具
      • 定义节点
      • 构建图
    • 见证效果
      • `qwen2.5`
      • `llama3.1`
      • `MFDoom/deepseek-r1-tool-calling:7b`
    • 总结
    • 代码
    • 参考

上一篇文章我们演练了一个 用 langgraph 实现的 RAG(Retrieval Augmented Generation,检索增强生成) 系统。本文将要创建的系统将更加智能:如果在知识库中未找到靠谱的文档,则用 LLM(大语言模型) 自身的能力弥补。
另外,检索和生成部分增加了更多的细节控制。本次构建的 LangGraph 链如下图:
langgraph 链

如上图,query_or_respond 是一个条件节点,它通过能否根据用户的问题生成 工具调用(tool_calls) ,来判断是否需要检索矢量知识库:如果 工具调用 为空,则直接由大语言模型处理;否则通过 工具调用 调用 tools 进行检索。

使用 qwen2.5deepseek 以及 llama3.1 做实验,用 shaw/dmeta-embedding-zh 做中文嵌入和检索。

准备

在正式开始撸代码之前,需要准备一下编程环境。

  1. 计算机
    本文涉及的所有代码可以在没有显存的环境中执行。 我使用的机器配置为:

    • CPU: Intel i5-8400 2.80GHz
    • 内存: 16GB
  2. Visual Studio Code 和 venv
    这是很受欢迎的开发工具,相关文章的代码可以在 Visual Studio Code 中开发和调试。 我们用 pythonvenv 创建虚拟环境, 详见:
    在Visual Studio Code中配置venv。

  3. Ollama
    Ollama 平台上部署本地大模型非常方便,基于此平台,我们可以让 langchain 使用 llama3.1qwen2.5deepseek 等各种本地大模型。详见:
    在langchian中使用本地部署的llama3.1大模型 。

创建矢量数据库对象

我们直接使用之前使用 chroma 创建好的本地嵌入数据库,它的数据源是一个 csv 文件,每一行包含了一种动物的信息,例如:

名称,学名,特点,作用
狗,Canis lupus familiaris,忠诚、聪明、社交性强,看家护院、导盲、搜救、警务、情感陪伴
猫,Felis catus,独立、高冷、善于捕鼠,消灭害鼠、陪伴、缓解压力

详细的创建过程可参见:本地大模型编程实战(14)初探智能体Agent(1)

embed_model_name = "shaw/dmeta-embedding-zh"
vector_store = Chroma(persist_directory=get_persist_directory(embed_model_name),embedding_function=OllamaEmbeddings(model=embed_model_name))

创建 LangGraph 链

在上一篇文章 RAG(Retrieval Augmented Generation,检索增强生成)(2) 中,我们将用户输入、检索到的上下文和生成的答案表示为状态对象中的单独键。
除了来自用户和AI的消息之外,还可以通过工具消息将检索到的文档内容合并到消息序列中,这样我们可以使用一系列消息来表示 RAG 应用程序的状态。具体来说,我们将:

  • 把用户输入作为 HumanMessage;
  • 把向量存储查询作为带有工具调用的 AIMessage;
  • 把检索到的文档作为 ToolMessage;
  • 最终响应作为 AIMessage。
    这种状态模型非常通用,因此 LangGraph 提供了一个内置版本以方便使用:
from langgraph.graph import MessagesState, StateGraph
graph_builder = StateGraph(MessagesState)

将检索步骤转化为工具

利用工具调用与检索步骤交互还有另一个好处,即检索查询由我们的大语言模型生成。这在对话环境中尤其重要,因为用户查询可能需要基于聊天记录进行情境化。例如,考虑以下交流:

Human:“什么是任务分解?”
AI:“任务分解涉及将复杂任务分解为更小、更简单的步骤,以使代理或模型更易于管理。”
Human:“常见的做法是什么?”

在这种情况下,模型可以生成查询,例如:任务分解的常见方法。
由于大语言模型在生成工具调用时会智能的生成查询,那么它将会明显提升查询的准确性。它还可以生成不涉及检索步骤的直接响应(例如,响应用户的一般问候),也可以自动进行指代消解:根据上下文自动修改问题,把问题中的代词替换成上下文中的内容。

下面我们基于 检索 生成一个 工具:

@tool(response_format="content_and_artifact",parse_docstring=True)      # docstring的内容对agent自动推理影响比较大
def retrieve(query: str):"""检索与 query参数内容 相关的信息Args:query: 要搜索的字符串。 """print(f"start retrieve:{query}")# 定义相似度阈值。因为这种相似性检索并不考虑相似性大小,如果不限制可能会返回相似性不大的文档, 可能会影响问答效果。similarity_threshold = 0.8retrieved_docs = vector_store.similarity_search_with_score(query, k=3)# 根据相似度分数过滤结果filtered_docs = [doc for doc, score in retrieved_docs if score <= similarity_threshold]serialized = "\n\n".join((f"Source: {doc.metadata}\n" f"Content: {doc.page_content}")for doc in filtered_docs)if not serialized:return "抱歉,我找不到任何相关信息。", Noneelse:return serialized, filtered_docs

上述检索工具完善了以下几个细节:

  • 定义了相似度阈值:过滤掉相似度太低的文档,防止差的结果产生负面影响;
  • 如果未找到靠谱的文档,返回:“抱歉,我找不到任何相关信息。”:这个结果将会在 生成 阶段被添加到提示词中,有助于大语言模型自行推理更合理的回答。

定义节点

我们的链将由三个节点组成:

  • 一个处理用户输入的节点:要么为检索器生成查询,要么直接响应;
  • 一个用于执行检索步骤的检索器工具的节点;
  • 一个使用检索到的上下文生成最终响应的节点。
    我们在下面构建它们。
    请注意,我们利用另一个预先构建的 LangGraph 组件 ToolNode,它执行该工具并将结果作为 ToolMessage 添加到状态(state)。
# 1: 生成可能包含工具调用(tool_call)的 AIMessage。
def query_or_respond(state: MessagesState):"""生成用于检索或响应的工具调用。"""llm_with_tools = llm.bind_tools([retrieve])response = llm_with_tools.invoke(state["messages"])"""这里会自动进行指代消解:根据上下文自动修改问题,把问题中的代词替换成上下文中的内容"""# MessagesState 将消息附加到 state 而不是覆盖return {"messages": [response]}# 2: 执行检索
tools = ToolNode([retrieve])# 3: 使用检索到的内容生成响应。
def generate(state: MessagesState):"""生成回答。"""# 获取生成的 ToolMessagesrecent_tool_messages = []for message in reversed(state["messages"]):if message.type == "tool":recent_tool_messages.append(message)else:breaktool_messages = recent_tool_messages[::-1]# 获取 ToolMessages 的内容,并格式化为提示词docs_content = "\n\n".join(doc.content for doc in tool_messages)system_message_content = ("你是一个负责答疑任务的助手。 ""使用以下检索到的上下文来回答问题。 ""如果你不知道答案,就说你不知道。 ""最多使用三句话并保持答案简洁。 ""\n\n"f"{docs_content}")conversation_messages = [messagefor message in state["messages"]if message.type in ("human", "system")or (message.type == "ai" and not message.tool_calls)]prompt = [SystemMessage(system_message_content)] + conversation_messages# 执行response = llm.invoke(prompt)# MessagesState 将消息附加到 state 而不是覆盖return {"messages": [response]}

构建图

现在,我们将节点连接起来,将应用程序编译成单个 LangGraph 对象。
第一个节点 query_or_respond 步骤可以“短路”并直接响应用户(如果它不生成工具调用)。这使我们的应用程序能够支持对话体验。 例如,响应可能不需要检索步骤的通用问候语。

def build_graph(llm_model_name):"""构建 langgraph 链"""llm = ChatOllama(model=llm_model_name,temperature=0, verbose=True)# 串联节点和边,构建图graph_builder = StateGraph(MessagesState)graph_builder.add_node(query_or_respond)graph_builder.add_node(tools)graph_builder.add_node(generate)graph_builder.set_entry_point("query_or_respond")graph_builder.add_conditional_edges("query_or_respond",tools_condition,{END: END, "tools": "tools"},)graph_builder.add_edge("tools", "generate")graph_builder.add_edge("generate", END)graph = graph_builder.compile()return graph

见证效果

现在可以定义测试方法:

def ask(llm_model_name,question):"""提问"""graph = build_graph(llm_model_name)for step in graph.stream({"messages": [{"role": "user", "content": question}]},stream_mode="values",):step["messages"][-1].pretty_print()

我们准备两个问题:

query1 = "马的学名是什么?它有什么用途?"
query2 = "中国有多少个省份?"

现在用各大模型试一下。

qwen2.5

  • query1 = “马的学名是什么?它有什么用途?”
================================ Human Message =================================马的学名是什么?它有什么用途?
================================== Ai Message ==================================
Tool Calls:retrieve (729acad9-b8ae-4ed3-aa12-f48dd431d8ed)Call ID: 729acad9-b8ae-4ed3-aa12-f48dd431d8edArgs:query: 马 学名
start retrieve:马 学名
================================= Tool Message =================================
Name: retrieveSource: {'row': 2, 'source': 'D:\\project\\programming-with-local-large-language-model\\server\\services\\practice\\assert/animals.csv'}
Content: 名称: 马
学名: Equus ferus caballus
特点: 速度快、耐力强、与人类有深厚的合作关系
作用: 交通、战马、农业、体育竞技
================================== Ai Message ==================================马的学名是Equus ferus caballus。马的用途包括交通、作为战马、用于农业劳动以及参与体育竞技。

在生成工具调用(Tool Calls),调用工具检索步骤都很稳妥,最终结果也没问题。

  • query2 = “中国有多少个省份?”
================================ Human Message =================================中国有多少个省份?
================================== Ai Message ==================================中国的行政区划中,通常指的是34个省级行政区,包括23个省、5个自治区、4个直辖市以及香港特别行政区和澳门特别行政区。如果您需要更详细的信息或者有其他问题,请告诉我!

这次生成的工具调用(Tool Calls)为空,所以调过了检索和生成步骤,直接由大语言模型返回结果了。
值得一提的是:虽然大语言模型 在 query_or_respond 函数中生成的 response 对象的工具调用(tool_calls)为空,但是 content 是有正确内容的,这说明:它还可以生成不涉及检索步骤的直接响应
很棒!

llama3.1

  • query1 = “马的学名是什么?它有什么用途?”
================================ Human Message =================================马的学名是什么?它有什么用途?
================================== Ai Message ==================================
Tool Calls:retrieve (c811874c-528f-4f17-878b-774452af14d8)Call ID: c811874c-528f-4f17-878b-774452af14d8Args:query: 王的学名我是,常用给为为
start retrieve:王的学名我是,常用给为为
================================= Tool Message =================================
Name: retrieve抱歉,我找不到任何相关信息。
================================== Ai Message ==================================马的学名是Equus caballus。马主要用于运输、耕作和骑乘等方面。

显然,它生成的工具调用(tool_calls)是错误的, retrieve 返回错误信息:“抱歉,我找不到任何相关信息。”,大模型最终还是利用自己的能力回答了问题。

  • query2 = “中国有多少个省份?”
================================ Human Message =================================中国有多少个省份?
================================== Ai Message ==================================
Tool Calls:retrieve (95b0f1ca-9292-4df6-b670-64a267ef1a60)Call ID: 95b0f1ca-9292-4df6-b670-64a267ef1a60Args:query: 中国有有二市综名
start retrieve:中国有有二市综名
================================= Tool Message =================================
Name: retrieve抱歉,我找不到任何相关信息。
================================== Ai Message ==================================中国共有34个省份。

按照常理来讲,这次不应该工具调用(tool_calls)了,结果 llama3.1 还是生成了一个不靠谱的 工具调用(tool_calls)。
看起来 llama3.1 生成中文的工具调用(tool_calls)有问题。

MFDoom/deepseek-r1-tool-calling:7b

  • query1 = “马的学名是什么?它有什么用途?”
================================ Human Message =================================马的学名是什么?它有什么用途?
================================== Ai Message ==================================
Tool Calls:retrieve (9fcc67a2-e78e-489c-81d3-ed50688c4422)Call ID: 9fcc67a2-e78e-489c-81d3-ed50688c4422Args:query:  horse's scientific name
start retrieve: horse's scientific name
================================= Tool Message =================================
Name: retrieveSource: {'row': 2, 'source': 'D:\\project\\programming-with-local-large-language-model\\server\\services\\practice\\assert/animals.csv'}
Content: 名称: 马
学名: Equus ferus caballus
特点: 速度快、耐力强、与人类有深厚的合作关系
作用: 交通、战马、农业、体育竞技
================================== Ai Message ==================================<think>
好的,我现在需要回答用户的问题:“马的学名是什么?它有什么用途?”首先,我查看提供的上下文内容。内容中提到“名称: 马”和“学名: Equus ferus caballus”。所以,马的学名应该是Equus ferus caballus。接下来,关于用途部分,内容里列出了几点:交通、战马、农业、体育竞技。这些都是马被广泛使用的领域。因此,我需要将这些信息整合成一个简洁的回答。最后,确保回答不超过三句话,并且保持简洁明了。这样用户就能清楚地得到学名和用途的信息。
</think>马的学名是Equus ferus caballus。它主要用作交通工具、军事马、农业动物以及体育竞技中的赛马。

不知为什么生成的 工具调用(Tool Calls)中的查询是英文,当然,最终结果不错。

  • query2 = “中国有多少个省份?”
================================ Human Message =================================中国有多少个省份?
================================== Ai Message ==================================
Tool Calls:retrieve (3ce0bbec-2612-4e79-85b8-d7f9cbe0d422)Call ID: 3ce0bbec-2612-4e79-85b8-d7f9cbe0d422Args:query: 中国有多少个省份?
start retrieve:中国有多少个省份?
================================= Tool Message =================================
Name: retrieve抱歉,我找不到任何相关信息。
================================== Ai Message ==================================<think>
嗯,用户问的是中国有多少个省份。我记得中国有34个省份,对吧?不过有时候也会加上特别行政区和台湾地区,这样就是36个地方了。但通常在正式统计中,不包括香港和澳门,所以应该是34个省份。我应该确认一下这个数字是否正确 ,确保回答准确。
</think>中国有34个省份。

显然,针对这个问题,大语言模型不应该生成工具调用。最终检索工具未检索出靠谱的文档,大语言模型凭借自己的能力回答了问题。

总结

这次我们实验了一个 通过 是否可以生成工具调用(tool_calls)作为条件来判断是否检索知识库的 RAG(Retrieval Augmented Generation,检索增强生成) 系统。
经过3个大模型的对比实验,我们发现,在处理中文工具生成这方面:qwen2.5 非常稳健。

如果您想自己实现一个包含前端和后端的 RAG 系统,从零搭建langchain+本地大模型+本地矢量数据库的RAG系统 可能对您入门有帮助。


代码

本文涉及的所有代码以及相关资源都已经共享,参见:

  • github
  • gitee

为便于找到代码,程序文件名称最前面的编号与本系列文章的文档编号相同。

参考

  • Build a Retrieval Augmented Generation (RAG) App

🪐感谢您观看,祝好运🪐

相关文章:

本地大模型编程实战(19)RAG(Retrieval Augmented Generation,检索增强生成)(3)

文章目录 准备创建矢量数据库对象创建 LangGraph 链将检索步骤转化为工具定义节点构建图 见证效果qwen2.5llama3.1MFDoom/deepseek-r1-tool-calling:7b 总结代码参考 上一篇文章我们演练了一个 用 langgraph 实现的 RAG(Retrieval Augmented Generation,检索增强生成) 系统。本…...

DeepSeek与ChatGPT:AI语言模型的全面对决

DeepSeek与ChatGPT&#xff1a;AI语言模型的全面对决 引言&#xff1a;AI 语言模型的时代浪潮一、认识 DeepSeek 与 ChatGPT&#xff08;一&#xff09;DeepSeek&#xff1a;国产新星的崛起&#xff08;二&#xff09;ChatGPT&#xff1a;AI 界的开拓者 二、DeepSeek 与 ChatGP…...

2024年年终总结

2024年终于过去了&#xff0c;这绝对是我人生中最惨痛的一年&#xff01;被小人欺骗、被庸人耽误、被自己蠢到&#xff01;不由的让我想起了22年那次算命&#xff0c;算命先生说我十年低谷期&#xff0c;如果从15年进创业公司开始&#xff0c;24年是最后一年&#xff0c;果然应…...

利用 Valgrind 检测 C++ 内存泄露

Valgrind 是一款运行在 Linux 系统上的编程工具集&#xff0c;主要用于调试和分析程序的性能、内存使用等问题。其中最常用的工具是 Memcheck&#xff0c;它可以帮助检测 C 和 C 程序中的内存管理错误&#xff0c;如内存泄漏、使用未初始化的内存、越界访问等。 安装 这里我以…...

Python中的HTTP客户端库:httpx与request | python小知识

Python中的HTTP客户端库&#xff1a;httpx与request | python小知识 在Python中&#xff0c;发送HTTP请求和处理响应是网络编程的基础。requests和httpx是两个常用的HTTP库&#xff0c;它们都提供了简洁易用的API来发送HTTP请求。然而&#xff0c;httpx作为新一代的HTTP客户端…...

【Python】Python入门基础——环境搭建

学习Python&#xff0c;首先需要搭建一个本地开发环境&#xff0c;或是使用线上开发环境&#xff08;各类练习网站&#xff09;&#xff0c;这里主要记录本地开发环境的配置。 目录&#xff1a; 一、下载和安装python解释器 官网下载地址&#xff1a;Download Python | Pytho…...

2025 pwn_A_childs_dream

文章目录 fc/sfc mesen下载和使用推荐 fc/sfc https://www.mesen.ca/docs/ mesen2安装&#xff0c;vscode安装zg 任天堂yyds w d 左右移动 u结束游戏 i崩溃或者卡死了 L暂停 D658地方有个flag 发现DEEE会使用他。且只有这个地方&#xff0c;maybe会输出flag&#xff0c;应…...

面试题整理:操作系统

文章目录 操作系统操作系统基础1. 操作系统的功能&#xff1f;2. 什么是用户态和内核态&#xff1f; 进程和线程1. 是什么&#xff1f;区别&#xff1f;2. ⭐线程间的同步的方式有哪些&#xff1f;3. PCB 是什么&#xff1f;包含哪些信息&#xff1f;4. 进程的状态有哪些&#…...

构建未来教育的基石:智慧校园与信息的重要性

随着科技的迅猛发展&#xff0c;教育领域正经历一场深刻的变革。在这个过程中&#xff0c;“智慧校园”作为教育信息化的重要实践&#xff0c;扮演着不可或缺的角色。智慧校园不仅仅是硬件设施的升级&#xff0c;更是一种全新的教育理念&#xff0c;强调利用信息技术优化教育资…...

C# 控制台相关 API 与随机数API

C# 控制台相关 API 与随机数API 控制台输入输出 功能说明 Console.WriteLine(string): 输出字符串并换行Console.Write(string, string): 输出字符串不换行Console.ReadLine(): 等待用户输入并返回字符串Console.ReadKey(bool).KeyChar: 读取按键&#xff0c;指定是否显示输…...

【踩坑】⭐️MyBatis的Mapper接口中不建议使用重载方法

目录 &#x1f378;前言 &#x1f37b;一、背景 &#x1f379;二、问题处理 &#x1f49e;️三、处理方法 &#x1f378;前言 小伙伴们大家好&#xff0c;很久没有水..不是&#xff0c;写文章了&#xff0c;都收到系统的消息了&#xff1b;我算下时间&#xff0c;上周是单休…...

CSS Grid 网格布局,以及 Flexbox 弹性盒布局模型,它们的适用场景是什么?

CSS Grid网格布局和Flexbox弹性盒布局模型都是现代CSS布局的重要工具&#xff0c;它们各自具有独特的优势和适用场景。 作为前端开发工程师&#xff0c;理解这些布局模型的差异和适用场景对于编写高效、可维护的代码至关重要。 CSS Grid网格布局 适用场景&#xff1a; 复杂…...

HDFS体系结构

HDFS 支持主从结 构 &#xff0c; 主节 点 称为 NameNode &#xff0c;从节点称为 DataNode HDFS中还包含一个 SecondaryNameNode 进程&#xff0c;只要辅助主节点 公司BOSS&#xff1a;NameNode &#xff08;NN&#xff09; 秘书&#xff1a;SecondaryNameNode (2NN) 员工&a…...

AI大模型的技术突破与传媒行业变革

性能与成本&#xff1a;AI大模型的“双轮驱动” 过去几年&#xff0c;AI大模型的发展经历了从实验室到产业化的关键转折。2025年初&#xff0c;以DeepSeek R1为代表的模型在数学推理、代码生成等任务中表现超越国际头部产品&#xff0c;而训练成本仅为传统模型的几十分之一。这…...

vscode/cursor+godot C#中使用socketIO

在 Visual Studio Code(VS Code)中安装 NuGet 包&#xff08;例如SocketIOClient&#xff09;&#xff0c;你可以通过以下几种方法&#xff1a; 方法 1&#xff1a;使用dotnet cli 打开终端&#xff1a;在 VS Code 中按下Ctrl 或者通过菜单View -> Terminal打开终端。 导…...

分段线性插值

分段线性插值 分段线性插值&#xff0c;就是将插值点用折线段连接起来逼近f(x)。设已知节点 a x 0 < x 1 < ⋅ ⋅ ⋅ < x n b ax_0<x_1<<x_nb ax0​<x1​<⋅⋅⋅<xn​b上的函数值 f 0 , f 1 , . . . , f n f_0,f_1,...,f_n f0​,f1​,...,fn​&a…...

制作一个项目用于研究elementUI的源码

需求&#xff1a;修改el-tooltip的颜色&#xff0c;发现传递参数等方法都不太好用&#xff0c;也可以使用打断点的方式&#xff0c;但也有点麻烦&#xff0c;因此打算直接修改源码&#xff0c;把组件逻辑给修改了 第一步下载源码 源码地址 GitHub - ElemeFE/element: A Vue.j…...

[AI]从零开始的llama.cpp部署与DeepSeek格式转换、量化、运行教程

一、前言 在上一次的DeepSeek的部署教程中&#xff0c;我们使用Ollama与LM Studio很轻松的部署了DeepSeek并且也完成了相关API的调用&#xff0c;如果还有不会的小伙伴请看下面的教程&#xff1a; DeepSeek本地部署&#xff1a;[AI]从零开始的DeepSeek本地部署及本地API调用教…...

vLLM专题(二):安装-CPU

vLLM 是一个 Python 库,支持以下 CPU 变体。选择您的 CPU 类型以查看供应商特定的说明: Intel/AMD x86 vLLM 最初支持在 x86 CPU 平台上进行基本模型推理和服务,支持的数据类型包括 FP32、FP16 和 BF16。 注意 此设备没有预构建的 wheel 包或镜像,因此您必须从源代码构建 v…...

JVM 底层探秘:对象创建的详细流程、内存分配机制解析以及线程安全保障策略

文章目录 1. 类加载检查2. 内存分配① 指针碰撞② 空闲列表线程安全问题&#xff1a; 3. 内存空间初始化4. 对象头设置5. 对象初始化 当Java虚拟机遇到一条 new指令时&#xff0c;会执行以下步骤来创建对象&#xff1a; 1. 类加载检查 首先检查new指令的参数是否能在常量池中…...

反射获取方法和属性

Java反射获取方法 在Java中&#xff0c;反射&#xff08;Reflection&#xff09;是一种强大的机制&#xff0c;允许程序在运行时访问和操作类的内部属性和方法。通过反射&#xff0c;可以动态地创建对象、调用方法、改变属性值&#xff0c;这在很多Java框架中如Spring和Hiberna…...

Linux-07 ubuntu 的 chrome 启动不了

文章目录 问题原因解决步骤一、卸载旧版chrome二、重新安装chorme三、启动不了&#xff0c;报错如下四、启动不了&#xff0c;解决如下 总结 问题原因 在应用中可以看到chrome&#xff0c;但是打不开(说明&#xff1a;原来的ubuntu系统出问题了&#xff0c;这个是备用的硬盘&a…...

LeetCode - 199. 二叉树的右视图

题目 199. 二叉树的右视图 - 力扣&#xff08;LeetCode&#xff09; 思路 右视图是指从树的右侧看&#xff0c;对于每一层&#xff0c;只能看到该层最右边的节点。实现思路是&#xff1a; 使用深度优先搜索(DFS)按照"根-右-左"的顺序遍历树记录每个节点的深度对于…...

Golang——7、包与接口详解

包与接口详解 1、Golang包详解1.1、Golang中包的定义和介绍1.2、Golang包管理工具go mod1.3、Golang中自定义包1.4、Golang中使用第三包1.5、init函数 2、接口详解2.1、接口的定义2.2、空接口2.3、类型断言2.4、结构体值接收者和指针接收者实现接口的区别2.5、一个结构体实现多…...

解析两阶段提交与三阶段提交的核心差异及MySQL实现方案

引言 在分布式系统的事务处理中&#xff0c;如何保障跨节点数据操作的一致性始终是核心挑战。经典的两阶段提交协议&#xff08;2PC&#xff09;通过准备阶段与提交阶段的协调机制&#xff0c;以同步决策模式确保事务原子性。其改进版本三阶段提交协议&#xff08;3PC&#xf…...

【HarmonyOS 5】鸿蒙中Stage模型与FA模型详解

一、前言 在HarmonyOS 5的应用开发模型中&#xff0c;featureAbility是旧版FA模型&#xff08;Feature Ability&#xff09;的用法&#xff0c;Stage模型已采用全新的应用架构&#xff0c;推荐使用组件化的上下文获取方式&#xff0c;而非依赖featureAbility。 FA大概是API7之…...

CppCon 2015 学习:Reactive Stream Processing in Industrial IoT using DDS and Rx

“Reactive Stream Processing in Industrial IoT using DDS and Rx” 是指在工业物联网&#xff08;IIoT&#xff09;场景中&#xff0c;结合 DDS&#xff08;Data Distribution Service&#xff09; 和 Rx&#xff08;Reactive Extensions&#xff09; 技术&#xff0c;实现 …...

SQL注入篇-sqlmap的配置和使用

在之前的皮卡丘靶场第五期SQL注入的内容中我们谈到了sqlmap&#xff0c;但是由于很多朋友看不了解命令行格式&#xff0c;所以是纯手动获取数据库信息的 接下来我们就用sqlmap来进行皮卡丘靶场的sql注入学习&#xff0c;链接&#xff1a;https://wwhc.lanzoue.com/ifJY32ybh6vc…...

【技巧】dify前端源代码修改第一弹-增加tab页

回到目录 【技巧】dify前端源代码修改第一弹-增加tab页 尝试修改dify的前端源代码&#xff0c;在知识库增加一个tab页"HELLO WORLD"&#xff0c;完成后的效果如下 [gif01] 1. 前端代码进入调试模式 参考 【部署】win10的wsl环境下启动dify的web前端服务 启动调试…...

篇章一 论坛系统——前置知识

目录 1.软件开发 1.1 软件的生命周期 1.2 面向对象 1.3 CS、BS架构 1.CS架构​编辑 2.BS架构 1.4 软件需求 1.需求分类 2.需求获取 1.5 需求分析 1. 工作内容 1.6 面向对象分析 1.OOA的任务 2.统一建模语言UML 3. 用例模型 3.1 用例图的元素 3.2 建立用例模型 …...