这篇文章里面会有一些 python 代码,能看懂就行,可能会有语法错误大家当伪代码看吧, AI 应用开发也不会去敲这些代码(甚至整个过程都不太需要敲代码),文章中的这些代码只是为了更好的理解这些组件,实际应用开发中大概率是见不到文中用来示例的这种代码的。

一、LangChain是什么

LangChain is a framework for developing applications powered by large language models (LLMs).(来自LangChain 官网的描述)

LangChain是一个开源框架,是一个 LLM 变成框架,它允许开发人员将大模型、外部计算、数据源结合起来。

它是围绕LLMs(大语言模型)建立的一个框架。LangChain自身并不开发LLMs,它的核心理念是为各种LLMs实现通用的接口,把LLMs相关的组件“链接”在一起,简化LLMs应用的开发难度,方便开发者快速地开发复杂的LLMs应用。

LangChain目前支持三种类型的模型:LLMs、Chat Models(聊天模型)、Embeddings Models(嵌入模型).

二、为什么使用LangChain

如果我们要做一个企业内部的机器人助手,我们期望这个机器人可以能回答通用的问题、能从企业知识库中或者数据库中提取信息、并且能够根据我们指令去执行发送邮件等的操作,LangChain就是可以实现这一目标。

数据连接和行动执行是 LangChain 的两大特点。

  • 数据连接:Langchain 允许你将大型语言模型连接到你自己的数据源,比如数据库、PDF文件或其他文档。这意味着你可以使模型从你的私有数据中提取信息。
  • 行动执行:不仅可以提取信息,Langchain 还可以帮助你根据这些信息执行特定操作,如发送邮件。无需硬编码:它提供了灵活的方式来动态生成查询,避免了硬编码的需求。

到此大家如果还不是太理解 LangChain 是个啥,那么就索性把LangChain类比数据库连接的JDBC,JDBC屏蔽数据库之间连接差异,LangChain 屏蔽了 LLM 之间的差异,是一个桥梁和中介的角色。

三、LangChain核心组件

3.1、模型的I/O封装

  • LLMs:大语言模型
  • Chat Models:一般基于 LLMs,但按对话结构重新封装
  • PromptTemple:提示词模板
  • OutputParser:解析输出

3.2、数据连接封装

对 RAG 的封装在这部分。

  • Document Loaders:各种格式文件的加载器
  • Document Transformers:对文档的常用操作,如:split, filter, translate, extract metadata, etc
  • Text Embedding Models:文本向量化表示,用于检索等操作(啥意思?别急,后面详细讲)
  • Verctorstores: (面向检索的)向量的存储
  • Retrievers: 向量的检索

3.3、对话历史管理

  • 对话历史的存储、加载与剪裁

3.4、架构封装

  • Chain:实现一个功能或者一系列顺序功能组合

  • Agent:根据用户输入,自动规划执行步骤,自动选择每步需要的工具,最终完成用户指定的功能

    • Tools:调用外部功能的函数,例如:调 google 搜索、文件 I/O、Linux Shell 等等
    • Toolkits:操作某软件的一组工具集,例如:操作 DB、操作 Gmail 等等

3.5、Callbacks

在LangChain中,Callback 是一种非常重要的机制,它允许用户监听和处理在执行链式任务 (Chain) 过程中的各种事件。举个例子,在你问完模型问题之后需要记录时间回答所用时长、统计答案多多少个字、回答问题之后主动提醒你回答完了,以上这些在AI 执行任务的节点所出发的设定操作都可以用 CallBaks实现。

四、通过代码体验LangChain

笔者在调用的 openAI的远程接口来展示功能,大家看的时候不要迷糊。

笔者下面做的验证都使用的是 OpenAI的远程接口,因此如果想要用笔者的代码请先确保环境变量里面配置好了OPENAI_API_KEY, OPENAI_BASE_URL

4.1 、模型 I/O封装

把不同模型统一封装成一个接口,方便更换模型而不用重构代码,同时通过模型的封装实现模型的统一接口调用。

# 没配过 python 环境的同学,直接搜Anaconda搞一个吧,能用明白命令行的同学装个minni也行。
# 这是第一步。
!pip install --upgrade langchain
!pip install --upgrade langchain-openai
!pip install --upgrade langchain-community

4.1.1、OpenAI封装

from langchain_openai import ChatOpenAI

# 如果不想在代码中显式的使用key,就得保证操作系统的环境变量里面配置好了OPENAI_API_KEY, OPENAI_BASE_URL
llm = ChatOpenAI(model="gpt-4o-mini") # 默认是gpt-3.5-turbo
response = llm.invoke("你是谁")
print(response.content)

以上代码的执行结果是

4.1.2、多轮对话 Session 封装

多轮对话是指用户与系统之间进行多次信息交换的对话形式。这种对话模式需要系统能够维护对话状态,理解并利用上下文信息。

from langchain.schema import (
'''
在LangChain框架中,四类消息通过角色分工实现对LLM的精细化控制:
SystemMessage是“导演”,设定对话规则;
HumanMessage是“用户代理”,传递具体需求;
AIMessage是“执行者”,生成响应或触发工具;
ChatMessage是“灵活扩展”,但需谨慎使用。
'''
#下面这三个参数具体的概念和用法大家可以单独查一下。
AIMessage, # 表示LLM生成的响应,可能包含文本或工具调用请求。在多轮对话中,历史AIMessage可作为上下文,影响后续响应。
HumanMessage, # 表示用户向LLM发送的输入,对应对话中的“用户”角色。如提问“帮我翻译这段文本”。
SystemMessage # 是对话中的初始化指令,用于设置LLM的行为模式、上下文或背景信息。通常作为对话的首条消息传入。
)
) messages = [
SystemMessage(content="你是机器人助手"),
HumanMessage(content="我是使用者,我叫张三。"),
AIMessage(content="欢迎!"),
HumanMessage(content="我是谁")
] ret = llm.invoke(messages)
# 将上下文都拿到进行输出。
print(ret.content)

以上代码在获取上下文后进行输出,结果是:

4.2、模型的输入与输出

4.2.1、Prompt模板封装

Prompt模板是预定义的提示词(Prompt)结构,包含可填充的占位符,用于规范与大语言模型(LLM)交互的输入格式,以提高输出结果的准确性和一致性。

1、PromptTemplate在模版中自定义变量

from langchain.prompts import PromptTemplate
from langchain_openai import ChatOpenAI template = PromptTemplate.from_template("给我讲个关于{subject}的笑话")
print("********Template********")
print(template)
print("********Prompt********")
print(template.format(subject='李华')) # 定义 LLM
llm = ChatOpenAI(model="gpt-4o-mini")
# 通过 Prompt 调用 LLM
ret = llm.invoke(template.format(subject='李华'))
# 打印输出
print(ret.content)

2、ChatPromptTemplate 用模板表示的对话上下文

from langchain.prompts import (
ChatPromptTemplate,
HumanMessagePromptTemplate,
SystemMessagePromptTemplate,
)
from langchain_openai import ChatOpenAI template = ChatPromptTemplate.from_messages(
[
SystemMessagePromptTemplate.from_template("你是{product}的客服助手。你的名字叫{name}"),
HumanMessagePromptTemplate.from_template("{query}"),
]
) llm = ChatOpenAI(model="gpt-4o-mini")
prompt = template.format_messages(
product="XXX公司",
name="小 XX",
query="你是谁"
) print(prompt) ret = llm.invoke(prompt) print(ret.content)

3、MessagesPlaceholder 把多轮对话变成模板

from langchain.prompts import (
ChatPromptTemplate,
HumanMessagePromptTemplate,
MessagesPlaceholder,
) human_prompt = "Translate your answer to {language}."
human_message_template = HumanMessagePromptTemplate.from_template(human_prompt) chat_prompt = ChatPromptTemplate.from_messages(
# variable_name 是 message placeholder 在模板中的变量名
# 用于在赋值时使用
[MessagesPlaceholder("history"), human_message_template]
)
from langchain_core.messages import AIMessage, HumanMessage

human_message = HumanMessage(content="Who is Elon Musk?")
ai_message = AIMessage(
content="Elon Musk is a billionaire entrepreneur, inventor, and industrial designer"
) messages = chat_prompt.format_prompt(
# 对 "history" 和 "language" 赋值
history=[human_message, ai_message], language="中文"
) print(messages.to_messages())
result = llm.invoke(messages)
print(result.content)

4.2.2、从文件加载Prompt模板

新建一个 prompt_template.txt文件,内容如下:

举一个{topic}的例子

from langchain.prompts import PromptTemplate

template = PromptTemplate.from_file("prompt_template.txt")
print("********Template********")
print(template)
print("********Prompt********")
print(template.format(topic='冷笑话'))

4.2.3 、结构化输出

1、直接输出Pydntic 对象

‌*Pydantic 对象**‌是 Python 中的一个库,主要用于数据验证和解析。Pydantic通过使用Python的类型注解来定义模型的字段类型,并在运行时自动进行数据验证和解析。

from pydantic import BaseModel, Field

# 定义你的输出对象
class Date(BaseModel):
year: int = Field(description="Year")
month: int = Field(description="Month")
day: int = Field(description="Day")
era: str = Field(description="BC or AD")
from langchain.prompts import PromptTemplate, ChatPromptTemplate, HumanMessagePromptTemplate
from langchain_openai import ChatOpenAI from langchain_core.output_parsers import PydanticOutputParser model_name = 'gpt-4o-mini'
temperature = 0
llm = ChatOpenAI(model_name=model_name, temperature=temperature) # 定义结构化输出的模型
structured_llm = llm.with_structured_output(Date) template = """提取用户输入中的日期。
用户输入:
{query}""" prompt = PromptTemplate(
template=template,
) query = "2025年六月8日天气 多云..."
input_prompt = prompt.format_prompt(query=query) structured_llm.invoke(input_prompt)

输出结果如下:

2、输出指定格式的JSON

json_schema = {
"title": "Date",
"description": "Formated date expression",
"type": "object",
"properties": {
"year": {
"type": "integer",
"description": "year, YYYY",
},
"month": {
"type": "integer",
"description": "month, MM",
},
"day": {
"type": "integer",
"description": "day, DD",
},
"era": {
"type": "string",
"description": "BC or AD",
},
},
}
structured_llm = llm.with_structured_output(json_schema) structured_llm.invoke(input_prompt)

输出结果如下:

3、OutputParser

使用OutputParser可以按指定格式解析模型的输出,示例如下:

from langchain_core.output_parsers import JsonOutputParser

parser = JsonOutputParser(pydantic_object=Date)

prompt = PromptTemplate(
template="提取用户输入中的日期。\n用户输入:{query}\n{format_instructions}",
input_variables=["query"],
partial_variables={"format_instructions": parser.get_format_instructions()},
) input_prompt = prompt.format_prompt(query=query)
output = llm.invoke(input_prompt)
print("原始输出:\n"+output.content) print("\n解析后:")
parser.invoke(output)

输出结果如下:

4、 PydanticOutputParser

‌PydanticOutputParser 是一个用于解析 语言模型 输出的工具,它允许用户指定一个 Pydantic 模型,并指导语言模型生成符合该模型的 JSON 输出。通过这种方式,PydanticOutputParser确保从语言模型获得的结构化数据符合预期的格式,从而简化了数据处理和集成的过程‌

from langchain_core.output_parsers import PydanticOutputParser

parser = PydanticOutputParser(pydantic_object=Date)

input_prompt = prompt.format_prompt(query=query)
output = llm.invoke(input_prompt)
print("原始输出:\n"+output.content) print("\n解析后:")
parser.invoke(output)

输出结果如下:

5、OutputFixingParser

‌OutputFixingParser 是一个用于修复API或模型输出格式错误的工具,它通过调用一个语言模型(LLM)来自动修复解析错误。OutputFixingParser封装了其他输出解析器,当初次解析失败时,它会调用LLM来尝试修复格式错误,从而提供了一种自动化解决方案‌。

from langchain.output_parsers import OutputFixingParser

new_parser = OutputFixingParser.from_llm(parser=parser, llm=ChatOpenAI(model="gpt-4o"))

bad_output = output.content.replace("5","五")
print("PydanticOutputParser:")
try:
parser.invoke(bad_output)
except Exception as e:
print(e) print("OutputFixingParser:")
new_parser.invoke(bad_output)

输出结果如下

4.2.4、Function Calling

不知道 Function Calling 的请看博主写技术架构的那篇文章。

from langchain_core.tools import tool

@tool
def add(a: int, b: int) -> int:
"""Add two integers. Args:
a: First integer
b: Second integer
"""
return a + b @tool
def multiply(a: int, b: int) -> int:
"""Multiply two integers. Args:
a: First integer
b: Second integer
"""
return a * b
import json

llm_with_tools = llm.bind_tools([add, multiply])

query = "3的4倍是多少?"
messages = [HumanMessage(query)] output = llm_with_tools.invoke(messages) print(json.dumps(output.tool_calls, indent=4))
#回传 Function Call的结果
messages.append(output) available_tools = {"add": add, "multiply": multiply} for tool_call in output.tool_calls:
selected_tool = available_tools[tool_call["name"].lower()]
tool_msg = selected_tool.invoke(tool_call)
messages.append(tool_msg) new_output = llm_with_tools.invoke(messages)
for message in messages:
print(json.dumps(message.dict(), indent=4, ensure_ascii=False))
print(new_output.content)

这里的结果运行图太长了,大家看看代码知道怎么回事儿就行了,实际开发中也不会这么去写着用。

4.3、数据连接封装

笔者这里准备了一个临时的 testFile.pdf,内容大概就是几大段文字三页的那个 pdf。

!pip install pymupdf
from langchain_community.document_loaders import PyMuPDFLoader

loader = PyMuPDFLoader("testFile.pdf")
pages = loader.load_and_split() print(pages[0].page_content)

4.3.1、文档加载器Document Loaders

!pip install --upgrade langchain-text-splitters
from langchain_text_splitters import RecursiveCharacterTextSplitter

# 简单的文本内容切割
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=200,
chunk_overlap=100,
length_function=len,
add_start_index=True,
) paragraphs = text_splitter.create_documents([pages[0].page_content])
for para in paragraphs:
print(para.page_content)
print('-------')

4.3.2、文档处理器

1、TextSplitter

!pip install --upgrade langchain-text-splitters
from langchain_text_splitters import RecursiveCharacterTextSplitter

# 简单的文本内容切割
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=200,
chunk_overlap=100,
length_function=len,
add_start_index=True,
) paragraphs = text_splitter.create_documents([pages[0].page_content])
for para in paragraphs:
print(para.page_content)
print('-------')

4.3.3、向量数据库与向量检索

向量数据库的连接部分本质是接口的封装,数据库需要自己选型。

更多的三方检索组件链接,参考:https://python.langchain.com/v0.3/docs/integrations/vectorstores/

# 安装一个向量检索库Faiss
'''
‌向量检索库和向量数据库不是同一个概念。‌
向量数据库是一种专门设计用于存储和查询向量数据的数据库,常用于机器学习和数据科学领域。向量数据库的主要功能是高效地存储和检索高维向量数据,常用于推荐系统或检索系统中‌,而向量检索库则是指从向量库中检索出距离目标向量最近的K个向量的过程,通常使用欧式距离或余弦距离来衡量两个向量间的相似度‌。
'''
conda install -c pytorch faiss-cpu
from langchain_openai import OpenAIEmbeddings
from langchain_text_splitters import RecursiveCharacterTextSplitter
from langchain_community.vectorstores import FAISS
from langchain_openai import ChatOpenAI
from langchain_community.document_loaders import PyMuPDFLoader # 加载文档
loader = PyMuPDFLoader("llama2.pdf")
pages = loader.load_and_split() # 文档切分
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=300,
chunk_overlap=100,
length_function=len,
add_start_index=True,
) texts = text_splitter.create_documents(
[page.page_content for page in pages[:4]]
) # 灌库
embeddings = OpenAIEmbeddings(model="text-embedding-ada-002")
db = FAISS.from_documents(texts, embeddings) # 检索 top-3 结果
retriever = db.as_retriever(search_kwargs={"k": 3}) docs = retriever.invoke("为什么觉着你适合当产品经理?") for doc in docs:
print(doc.page_content)
print("----")

4.4、对话历史管理

4.4.1、历史记录的剪裁

在开发一个对话系统时,为了避免输入的上下文信息超过了模型的最大长度(max token),所以需要对历史对话内容进行裁剪,LangChain就提供了一个已经封装好的函数trim_messages来解决这个问题。

4.4.2、过滤带标识的历史记录

from langchain_core.messages import (
AIMessage,
HumanMessage,
SystemMessage,
filter_messages,
) messages = [
SystemMessage("you are a good assistant", id="1"),
HumanMessage("example input", id="2", name="example_user"),
AIMessage("example output", id="3", name="example_assistant"),
HumanMessage("real input", id="4", name="bob"),
AIMessage("real output", id="5", name="alice"),
] filter_messages(messages, include_types="human")

五、Chain 和 LangChain Expression Language (LCEL)

在LangChain框架中,Chain(链) 和 LCEL(LangChain Expression Language) 是两个密切相关但本质不同的概念。

Chain(链): 是LangChain中处理流程的抽象概念,指将多个组件(模型、工具、逻辑)串联成一个可执行的任务序列。

LangChain Expression Language(LCEL)是一种声明式语言,可轻松组合不同的调用顺序构成 Chain。LCEL 自创立之初就被设计为能够支持将原型投入生产环境,无需代码更改,从最简单的“提示+LLM”链到最复杂的链(已有用户成功在生产环境中运行包含数百个步骤的 LCEL Chain)。

LCEL 的一些亮点包括:

  1. 流支持:使用 LCEL 构建 Chain 时,你可以获得最佳的首个令牌时间(即从输出开始到首批输出生成的时间)。对于某些 Chain,这意味着可以直接从 LLM 流式传输令牌到流输出解析器,从而以与 LLM 提供商输出原始令牌相同的速率获得解析后的、增量的输出。

  2. 异步支持:任何使用 LCEL 构建的链条都可以通过同步 API(例如,在 Jupyter 笔记本中进行原型设计时)和异步 API(例如,在 LangServe 服务器中)调用。这使得相同的代码可用于原型设计和生产环境,具有出色的性能,并能够在同一服务器中处理多个并发请求。

  3. 优化的并行执行:当你的 LCEL 链条有可以并行执行的步骤时(例如,从多个检索器中获取文档),我们会自动执行,无论是在同步还是异步接口中,以实现最小的延迟。

  4. 重试和回退:为 LCEL 链的任何部分配置重试和回退。这是使链在规模上更可靠的绝佳方式。目前我们正在添加重试/回退的流媒体支持,因此你可以在不增加任何延迟成本的情况下获得增加的可靠性。

  5. 访问中间结果:对于更复杂的链条,访问在最终输出产生之前的中间步骤的结果通常非常有用。这可以用于让最终用户知道正在发生一些事情,甚至仅用于调试链条。你可以流式传输中间结果,并且在每个 LangServe 服务器上都可用。

  6. 输入和输出模式:输入和输出模式为每个 LCEL 链提供了从链的结构推断出的 Pydantic 和 JSONSchema 模式。这可以用于输入和输出的验证,是 LangServe 的一个组成部分。

  7. 无缝 LangSmith 跟踪集成:随着链条变得越来越复杂,理解每一步发生了什么变得越来越重要。通过 LCEL,所有步骤都自动记录到 LangSmith,以实现最大的可观察性和可调试性。

  8. 无缝 LangServe 部署集成:任何使用 LCEL 创建的链都可以轻松地使用 LangServe 进行部署。

    使用 LCEL 的价值,也就是 LangChain 的核心价值。

    LCEL 笔者会写一篇专门的文章给大家示例

六、LangServe

‌LangServe **‌是一个用于构建和部署基于自然语言处理(NLP)模型的应用程序的框架,它帮助开发者将 LangChain 的可运行对象(Runnable)和链(Chain)部署为REST API。LangServe通过与 FastAPI 集成,并使用 Pydantic 进行数据验证,简化了从开发到生产的过渡,并确保服务的高性能和安全性‌。

七、LangChain 与LIamaIndex

LangChain 与 LlamaIndex 的错位竞争

八、LangChain与Dify

LangChain 是乐高,Dify 是拼好的乐高。

  • Dify:是低代码 AI 开发平台,强调易用性和快速开发,有直观的可视化界面,通过简单地拖拽和组合不同的模块来构建 Agent,即使是非技术人员也能参与到 AI 应用的定义和数据运营过程中。

  • LangChain:是开源的 Python 库,主要面向有编程经验的开发者,需要编写代码来定义逻辑、集成数据源以及协调大语言模型与其他组件之间的交互,更适合对代码编写有较高要求、希望深度定制 Agent 功能的开发者。

    开发过程的区别:

  • Dify:开发过程简单快捷,通过可视化界面和拖拽操作,利用预构建的模型、API 和集成,开发者可以快速组装出所需的 AI 应用功能,无需大量编写代码。

  • LangChain:遵循以代码为中心的传统开发过程,开发者需要熟练掌握 Python 编程以及 LangChain 框架,通过编写代码来实现各种功能,开发过程相对更复杂,需要更多的时间和精力来学习和实践。

你应该懂的AI大模型(四)之 LangChain的更多相关文章

  1. AI大模型学习了解

    # 百度文心 上线时间:2019年3月 官方介绍:https://wenxin.baidu.com/ 发布地点: 参考资料: 2600亿!全球最大中文单体模型鹏城-百度·文心发布 # 华为盘古 上线时 ...

  2. 华为高级研究员谢凌曦:下一代AI将走向何方?盘古大模型探路之旅

    摘要:为了更深入理解千亿参数的盘古大模型,华为云社区采访到了华为云EI盘古团队高级研究员谢凌曦.谢博士以非常通俗的方式为我们娓娓道来了盘古大模型研发的"前世今生",以及它背后的艰难 ...

  3. 保姆级教程:用GPU云主机搭建AI大语言模型并用Flask封装成API,实现用户与模型对话

    导读 在当今的人工智能时代,大型AI模型已成为获得人工智能应用程序的关键.但是,这些巨大的模型需要庞大的计算资源和存储空间,因此搭建这些模型并对它们进行交互需要强大的计算能力,这通常需要使用云计算服务 ...

  4. HBase实践案例:知乎 AI 用户模型服务性能优化实践

    用户模型简介 知乎 AI 用户模型服务于知乎两亿多用户,主要为首页.推荐.广告.知识服务.想法.关注页等业务场景提供数据和服务, 例如首页个性化 Feed 的召回和排序.相关回答等用到的用户长期兴趣特 ...

  5. zz独家专访AI大神贾扬清:我为什么选择加入阿里巴巴?

    独家专访AI大神贾扬清:我为什么选择加入阿里巴巴? Natalie.Cai 拥有的都是侥幸,失去的都是人生 ​关注她 5 人赞同了该文章 本文由 「AI前线」原创,原文链接:独家专访AI大神贾扬清:我 ...

  6. Expo大作战(四十)--expo sdk api之 Calendar,Constants

    简要:本系列文章讲会对expo进行全面的介绍,本人从2017年6月份接触expo以来,对expo的研究断断续续,一路走来将近10个月,废话不多说,接下来你看到内容,讲全部来与官网 我猜去全部机翻+个人 ...

  7. 阿里开源新一代 AI 算法模型,由达摩院90后科学家研发

    最炫的技术新知.最热门的大咖公开课.最有趣的开发者活动.最实用的工具干货,就在<开发者必读>! 每日集成开发者社区精品内容,你身边的技术资讯管家. 每日头条 阿里开源新一代 AI 算法模型 ...

  8. 搭乘“AI大数据”快车,肌肤管家,助力美业数字化发展

    经过疫情的发酵,加速推动各行各业进入数据时代的步伐.美业,一个通过自身技术.产品让用户变美的行业,在AI大数据的加持下表现尤为突出. 对于美妆护肤企业来说,一边是进入存量市场,一边是疫后的复苏期,一边 ...

  9. 文心一言,通营销之学,成一家之言,百度人工智能AI大数据模型文心一言Python3.10接入

    "文心"取自<文心雕龙>一书的开篇,作者刘勰在书中引述了一个古代典故:春秋时期,鲁国有一位名叫孔文子的大夫,他在学问上非常有造诣,但是他的儿子却不学无术,孔文子非常痛心 ...

  10. DeepSpeed Chat: 一键式RLHF训练,让你的类ChatGPT千亿大模型提速省钱15倍

    DeepSpeed Chat: 一键式RLHF训练,让你的类ChatGPT千亿大模型提速省钱15倍 1. 概述 近日来,ChatGPT及类似模型引发了人工智能(AI)领域的一场风潮. 这场风潮对数字世 ...

随机推荐

  1. go 整分钟开始执行程序

    前言 有时候我们的程序要求整分钟开始运行,这时候就需要对当前时间进行判断 package main import ( "fmt" "time" ) func m ...

  2. 【前端开发】记一次Echart 内存泄露问题的排查

    最近发现一个web项目总是莫名其妙的内存增长,然后进行定位后来发现问题大概率出在Eharts上. 于是乎就开始搜索关于echarts内存增长的一些例子,但是都没有结果. 其中翻博客时发现甚至有人换成一 ...

  3. ORACLE数据挖掘之 MSET-SPRT

    虽然是熟悉的Oracle数据库,但关于机器学习.数据挖掘这方面的知识笔者起初也是不了解的,文中MSET相关设置来源于同事提供的sample,在测试过程中边查资料边学习吸收,也因此看到了别样的Oracl ...

  4. 自动旋转ROS小车(rviz+urdf+xacro)(附加python操作键盘控制小车运动)

    博客地址:https://www.cnblogs.com/zylyehuo/ 成果图 STEP1 创建工作空间 mkdir -p car_ws/src cd car_ws catkin_make ST ...

  5. HarmonyOS NEXT 基于原生能力获取视频缩略图

    大家好,我是 V 哥. 不得不佩服 HarmonyOS NEXT 原生能力的强大,如果你想在 鸿蒙 APP 开发中获取视频缩略图,不用依赖第三方库,就可以高效和稳定的实现,AVMetadataHelp ...

  6. BUUCTF---这是什么

    题目 题目给出apk 解题

  7. Pydantic字段元数据指南:从基础到企业级文档增强

    title: Pydantic字段元数据指南:从基础到企业级文档增强 date: 2025/3/28 updated: 2025/3/28 author: cmdragon excerpt: 通过Py ...

  8. This APT has Super Cow Powers.

    在Debian/Ubuntu上,apt包管理器内嵌着一个彩蛋. 如果你在命令行界面输入 apt help 在最后一行能找到This APT has Super Cow Powers. 说明该apt具有 ...

  9. Win10锁屏与关机相关设置-注册表

    禁用锁屏 HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\LogonUI\SessionData ...

  10. C多进程

    这篇文章主要是想针对多进程的创建和一些通信手段来进行一下记录 创建子进程 关于创建子进程的原型一般都是用的这个,直接fork,这个函数在父进程中调用,在父子进程中各有一个pid_t类型的返回值,父进程 ...