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

使用OpenAI、LangChain、MongoDB构建一个AI agent

LangChain真是好起来了。24年中的时候用LangChain V2差点把我气死,现在V3用起来开始真香了~

像 ChatGPT、Gemini 和 Claude 这样的大模型已成为企业必不可少的工具。如今,几乎每家公司都希望根据自己的需求或客户群体,开发一款定制化的AI Agent。

这篇文章将重点介绍如何创建一个个性化的助手,这个助手不仅能进行功能调用,还能将对话记录存储在数据库中,实现多会话的连续互动,同时能够执行网页搜索并总结相关信息。

为了更好地组织结构并便于未来扩展功能,使用 Langchain、Langgraph 和 LangSmith 这三个工具,它们会简化整个过程,并提升系统的功能性。Langchain 可以简化流媒体处理、工具调用,并支持多种不同的 LLM。Langgraph 是一个组织工具,帮助我们选择使用的工具,并且让智能助手自主决策路径。LangSmith 则是一个观察工具,它能帮助我们监控向 LLM 提问到最终得到答案的整个过程。

完整代码见仓库:https://github.com/zpillsbury/ai-agent。

资源准备

  • Tavily API key
  • OpenAI API key
  • MongoDB Atlas
  • Langsmith API key

首先,在你的 .env 文件里加上几个关键的环境变量,包括 openai_keytavily_keymongo_uri

📝 .env

OPENAPI\_KEY\=OPENAI\_KEY=sk-proj-XXXXXX
TAVILY\_API\_KEY\=tvly-XXXXXXXXXXXXXXXXXXXXXXXX
MONGO\_URI\=mongodb+srvXXXXXXXXXXXXXXXXXXXXXXXXXXXLANGCHAIN\_TRACING\_V2\=true
LANGCHAIN\_ENDPOINT\=https://api.smith.langchain.com
LANGCHAIN\_API\_KEY\=lsv2\_pt\_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\_xxxxxxxxxx
LANGCHAIN\_PROJECT\=project-name

然后,把这些Key和 URI 都配置到你的设置文件里,确保 langsmith、OpenAI key、Tavily key和 Mongo URI 一个都不少。

📝 app/utilities/settings.py

from pydantic import SecretStr
from pydantic_settings import BaseSettings, SettingsConfigDictclass Settings(BaseSettings):openai_key: SecretStrtavily_api_key: strmongo_uri: SecretStr# LangSmithlangchain_tracing_v2: bool = Truelangchain_endpoint: str = "https://api.smith.langchain.com"langchain_project: str = "ai-agent"langchain_api_key: strmodel_config = SettingsConfigDict(env_file=".env", extra="ignore")settings = Settings()

使用设置中的API key设置 OpenAI 客户端。

📝 app/main.py

from langchain_openai import ChatOpenAIfrom .utilities.settings import settingsllm = ChatOpenAI(openai_api_key=settings.openai_key,model_name="gpt-4o-mini",max_retries=2,
)

Langgraph

为了让聊天机器人的各个部分能够顺畅交流,需要设置一个全局“状态”变量,这样数据就能在各个节点间流通了。用 LLM 生成消息之后,通过 langgraphadd_messages 函数,把这些消息加入到聊天机器人的记忆里。

📝 app/main.py

from typing import Annotated, TypedDictfrom langchain_core.messages import BaseMessage
from langgraph.graph import END, START, StateGraph
from langgraph.graph.message import add_messages
from langgraph.graph.state import CompiledStateGraphclass State(TypedDict):messages: Annotated[list[BaseMessage], add_messages]

langgraph 中,每个节点其实就是一个函数。我们现在要做一个新的 chatbot 函数,它会通过 llm.ainvoke 去调用 OpenAI,把当前的消息状态传过去。OpenAI 会给我们返回一条新的 AI 消息,然后我们就把这个新消息更新到状态里。通过上一步配置的 add_messages 函数,新消息会自动加入到现有的消息队列中。

最后提一下,langgraph 提供了同步和异步两种方法。如果你想要异步处理,只需在方法名前加个 a。这次我们选择异步的 ainvoke,而不是同步的 invoke

📝 app/main.py

async def chatbot(state: State) -> State:"""Chatbot"""response_message = await llm.ainvoke(state["messages"])return {"messages": [response_message]}

现在,我们要用 add_node 把新写的函数加入到流程图里。在这个图中,节点之间的连线就是所谓的“边”

接下来,要用 add_edge 把图的起点 START 和聊天机器人节点连起来。最后用 graph_builder.compile 来编译这个图表。不编译的话,这个图表是没法用的。

其实这就是代码话的流程编排,很多AI WebUI都有。

📝 app/main.py

async def get_graph() -> CompiledStateGraph:    """    Get the graph    """    graph_builder = StateGraph(State)    graph_builder.add_node("chatbot", chatbot)    graph_builder.add_edge(START, "chatbot")    graph_builder.add_edge("chatbot", END)    graph = graph_builder.compile()    return graph

目前流程图长这样:

img图1 流程图

然后让我们来编写一个新异步函数 run_graph,通过 graph.astream(同步的话就用 stream)来启动我们精心编译的图。这个函数会激活“chatbot”节点,也就是之前定义的 chatbot 函数。

首先,它会放入一个System Prompt,再加上用户提出的问题,这样就构成了我们的对话状态。这些信息会被发送到 OpenAI,AI会回一条消息,我们的函数则会把这个回复加入到对话状态中。

在图的循环中,我们可以随时查看事件变量,了解当前的对话状态。我们会从这些事件中挖掘出 value,再从这个 value 中提取出最后一条消息的精华,最后把这份精华传回给用户。

至于系统提示,它就像是为 AI 助手提供了一份“情报”,让它的搜索更加精确。因为 LLM 的训练数据有截止时间,所以它可能会更擅长挖掘历史资料,而不是最新的知识。

📝 app/main.py

async def get_graph() -> CompiledStateGraph:"""Get the graph"""graph_builder = StateGraph(State)graph_builder.add_node("chatbot", chatbot)graph_builder.add_edge(START, "chatbot")graph_builder.add_edge("chatbot", END)graph = graph_builder.compile()return graph

接下来,写一个新异步函数 main,这个函数的核心任务就是接收用户的输入。同时,加入一个循环语句,它的作用是监听用户的输入,一旦用户键入(quit、exit 或 q),聊天就会在终端优雅地结束。

📝 app/main.py

from datetime import datetime, timezone
from langchain_core.messages import BaseMessage, HumanMessage, SystemMessagenow = datetime.now(timezone.utc)system_prompt = f"""
You are an AI assistant helping an user.Current Date: {now}
"""asyncdef run_graph(question: str) -> None:"""Run the graph"""asyncfor event in graph.astream({"messages": [SystemMessage(content=system_prompt),HumanMessage(content=question),]}):for value in event.values():print(value["messages"][-1].content)returnNone

工具调用

现在,我们要利用 .env.settings 文件中的 tavily_api_key。通过 TavilySearchResults,我们的 AI 助手就能在网上进行搜索了。这些搜索工具会被集成到 tools 中,方便未来我们随时扩充工具箱。然后,我们通过 llm_with_tools = llm.bind_tools 这行代码,将工具列表绑定到 AI 助手身上。最后,记得把代码中所有用到 llm 的地方,都替换成 llm_with_tools,这样一来,AI 助手就能使用这些工具了。

📝 app/main.py

async def main() -> None:"""AI Agent"""whileTrue:question = input("q: ")if question.lower() in ["quit", "exit", "q"]:print("Goodbye!")breakawait run_graph(question)returnNoneif __name__ == "__main__":anyio.run(main)

下一步,加入一个 tool_node,这个节点的作用是激活调用 AI 消息的工具。设置一个 add_conditional_edge,这个特殊的边可以让 AI 助手根据不同的需求,导向不同的节点。它会先判断是否需要进行工具调用,如果不需要,那么流程就会直接导向 END 节点,结束这次交互。

📝 app/main.py

from langchain_community.tools.tavily_search import TavilySearchResultsweb_search = TavilySearchResults(max_results=2)
tools = [web_search]llm = ChatOpenAI(openai_api_key=settings.openai_key,model_name="gpt-4o-mini",max_retries=2,
)llm_with_tools = llm.bind_tools(tools)asyncdef chatbot(state: State) -> State:"""Chatbot"""response_message = await llm_with_tools.ainvoke(state["messages"])return {"messages": [response_message]}

存储对话数据

接下来,利用 .env.settings 文件中的 mongo_uri。首先,在代码的顶部加入 async_mongodb_client。然后,我们会在 get_graph 函数中设置一个检查点,它的作用是将记忆存储到 mongoDB。注意,这个操作需要放在异步函数里面才能正常执行哦。

📝 app/main.py

async def get_graph() -> CompiledStateGraph:"""Get the graph"""graph_builder = StateGraph(State)graph_builder.add_node("chatbot", chatbot)tool_node = ToolNode(tools=tools)graph_builder.add_node("tools", tool_node)graph_builder.add_edge(START, "chatbot")graph_builder.add_conditional_edges("chatbot", tools_condition)graph_builder.add_edge("tools", "chatbot")graph = graph_builder.compile()return graph

现在,利用 MongoDB 来设置 thread_id,这样做可以保存不同聊天记录中的消息。这个功能很强大,它让助手能够跨多个聊天 session 记住之前的对话内容。而且,如果想要为不同的聊天创建独立的记录,只需要使用不同的 thread_id 就可以轻松实现。

📝 app/main.py

from typing import Annotated, Any, TypedDict
from langchain_core.runnables import RunnableConfig
from langgraph.checkpoint.mongodb.aio import AsyncMongoDBSaver
from motor.motor_asyncio import AsyncIOMotorClientasync_mongodb_client: AsyncIOMotorClient[Any] = AsyncIOMotorClient(settings.mongo_uri.get_secret_value()asyncdef get_graph() -> CompiledStateGraph:"""Get the graph"""checkpointer = AsyncMongoDBSaver(client=async_mongodb_client,db_name="ai",checkpoint_collection_name="checkpoints",writes_collection_name="checkpoint_writes",)graph_builder = StateGraph(State)graph_builder.add_node("chatbot", chatbot)tool_node = ToolNode(tools=tools)graph_builder.add_node("tools", tool_node)graph_builder.add_edge(START, "chatbot")graph_builder.add_conditional_edges("chatbot", tools_condition)graph_builder.add_edge("tools", "chatbot")graph = graph_builder.compile(checkpointer=checkpointer)return graph

现在,可以执行脚本,看看运行结果。由于输入的是当前日期,所以它能展示出团队最新的动态和信息。

from langchain_core.runnables import RunnableConfigasyncdef run_graph(config: RunnableConfig, question: str) -> None:"""Run the graph"""graph = await get_graph()asyncfor event in graph.astream({"messages": [SystemMessage(content=system_prompt),HumanMessage(content=question),]},config=config,stream_mode="values",):event["messages"][-1].pretty_print()returnNoneasyncdef main() -> None:"""AI Agent"""config = RunnableConfig(configurable={"thread_id": 1})whileTrue:question = input("q: ")if question.lower() in ["quit", "exit", "q"]:print("Goodbye!")breakawait run_graph(config=config, question=question)returnNone

可以在你的 langsmith 项目中逐步查看运行过程。

在这里插入图片描述
图2 Langsmith 可视化Trace

这就是打造一个能够自主决定是否需要调用工具、能够在网上查找信息,并且能够为每个对话线程保存信息,从而记住之前对话的 AI 助手的基本步骤。因为我们用的是 langchain,所以以后想要加入流媒体处理、支持多种模型和其他 AI 模型(llms)的功能,也会变得相当简单。

如何学习AI大模型?

作为一名热心肠的互联网老兵,我决定把宝贵的AI知识分享给大家。 至于能学习到多少就看你的学习毅力和能力了 。我已将重要的AI大模型资料包括AI大模型入门学习思维导图、精品AI大模型学习书籍手册、视频教程、实战学习等录播视频免费分享出来。

这份完整版的大模型 AI 学习资料已经上传CSDN,朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费

一、全套AGI大模型学习路线

AI大模型时代的学习之旅:从基础到前沿,掌握人工智能的核心技能!

img

二、640套AI大模型报告合集

这套包含640份报告的合集,涵盖了AI大模型的理论研究、技术实现、行业应用等多个方面。无论您是科研人员、工程师,还是对AI大模型感兴趣的爱好者,这套报告合集都将为您提供宝贵的信息和启示。

img

三、AI大模型经典PDF籍

随着人工智能技术的飞速发展,AI大模型已经成为了当今科技领域的一大热点。这些大型预训练模型,如GPT-3、BERT、XLNet等,以其强大的语言理解和生成能力,正在改变我们对人工智能的认识。 那以下这些PDF籍就是非常不错的学习资源。

img

四、AI大模型商业化落地方案

img

作为普通人,入局大模型时代需要持续学习和实践,不断提高自己的技能和认知水平,同时也需要有责任感和伦理意识,为人工智能的健康发展贡献力量。

相关文章:

使用OpenAI、LangChain、MongoDB构建一个AI agent

LangChain真是好起来了。24年中的时候用LangChain V2差点把我气死,现在V3用起来开始真香了~ 像 ChatGPT、Gemini 和 Claude 这样的大模型已成为企业必不可少的工具。如今,几乎每家公司都希望根据自己的需求或客户群体,开发一款定制化的AI Age…...

如何在 Ubuntu 22.04 上安装并开始使用 RabbitMQ

简介 消息代理是中间应用程序,在不同服务之间提供可靠和稳定的通信方面发挥着关键作用。它们可以将传入的请求存储在队列中,并逐个提供给接收服务。通过以这种方式解耦服务,你可以使其更具可扩展性和性能。 RabbitMQ 是一种流行的开源消息代…...

【ETCD】【实操篇(十九)】ETCD基准测试实战

目录 1. 设定性能基准要求2. 使用基准测试工具基准测试命令 3. 测试不同的负载和场景4. 监控集群性能5. 评估硬件和网络的影响6. 对比性能基准7. 负载均衡和容错能力测试8. 优化与调优9. 测试在高负载下的表现总结 1. 设定性能基准要求 首先,明确集群性能的目标&am…...

HTML——29. 音频引入二

<!DOCTYPE html> <html><head><meta charset"UTF-8"><title>音频引入</title></head><body><!--audio:在网页中引入音频IE8以及之前版本不支持属性名和属性值一样&#xff0c;可以只写属性名src属性:指定音频文件…...

【SQLi_Labs】Basic Challenges

什么是人生&#xff1f;人生就是永不休止的奋斗&#xff01; Less-1 尝试添加’注入&#xff0c;发现报错 这里我们就可以直接发现报错的地方&#xff0c;直接将后面注释&#xff0c;然后使用 1’ order by 3%23 //得到列数为3 //这里用-1是为了查询一个不存在的id,好让第一…...

InnoDB存储引擎对MVCC的实现

多版本并发控制 (Multi-Version Concurrency Control) MVCC&#xff08;Multi-Version Concurrency Control&#xff09;&#xff0c;即多版本并发控制&#xff0c;是一种并发控制方法&#xff0c;主要用于数据库管理系统中实现对数据库的并发访问。以下是MVCC的详细解释&#…...

3D线上艺术展:艺术与技术的完美融合

随着数字技术的飞速发展&#xff0c;未来的艺术展览正逐步迈向线上线下融合的新阶段。其中&#xff0c;3D线上展览以其独特的魅力&#xff0c;成为线下展览的延伸与拓展&#xff0c;为艺术爱好者们开辟了全新的观赏途径。 对于艺术家和策展人而言&#xff0c;3D线上展览不仅打…...

EasyExcel(读取操作和填充操作)

文章目录 1.准备Read.xlsx&#xff08;具有两个sheet&#xff09;2.读取第一个sheet中的数据1.模板2.方法3.结果 3.读取所有sheet中的数据1.模板2.方法3.结果 EasyExcel填充1.简单填充1.准备 Fill01.xlsx2.无模版3.方法4.结果 2.列表填充1.准备 Fill02.xlsx2.模板3.方法4.结果 …...

【CSS in Depth 2 精译_095】16.3:深入理解 CSS 动画(animation)的性能

当前内容所在位置&#xff08;可进入专栏查看其他译好的章节内容&#xff09; 第五部分 添加动效 ✔️【第 16 章 变换】 ✔️ 16.1 旋转、平移、缩放与倾斜 16.1.1 变换原点的更改16.1.2 多重变换的设置16.1.3 单个变换属性的设置 16.2 变换在动效中的应用 16.2.1 放大图标&am…...

目前最流行的 Rust Web 框架有哪些?

目前最流行的 Rust Web 框架有哪些? 1. Actix Web:高性能之王,老牌框架 特点: 高性能:基于 Actor 模型,是目前 Rust 生态中最成熟、性能最强的 Web 框架之一。功能强大:支持 HTTP/1.x、HTTP/2、WebSocket 等,内置中间件和多种插件。社区支持广泛:拥有大量使用者,资料…...

连锁餐饮行业数据可视化分析方案

引言 随着连锁餐饮行业的迅速发展&#xff0c;市场竞争日益激烈。企业需要更加精准地把握运营状况、消费者需求和市场趋势&#xff0c;以制定科学合理的决策&#xff0c;提升竞争力和盈利能力。可视化数据分析可以帮助连锁餐饮企业整合多源数据&#xff0c;通过直观、动态的可…...

如何通过采购管理系统提升供应链协同效率?

供应链是企业运营的命脉&#xff0c;任何环节的延迟或失误都会对企业造成严重影响。在采购环节中&#xff0c;如何保证与供应商的协同效率&#xff0c;避免因信息不对称而导致的决策失误&#xff0c;是企业面临的一大挑战。采购管理系统作为数字化供应链管理的重要工具&#xf…...

1、Jmeter、jdk下载与安装

1、访问官网&#xff0c;点击下载Jmeter http://jmeter.apache.org/ 2、在等待期间&#xff0c;下载对应的Java https://www.oracle.com/cn/java/technologies/downloads/#jdk23-windows 3、全部下载好&#xff0c;先安装JDK ![在这里插入图片描述](https://i-blog.csdnimg…...

Scala图书管理系统

package org.app package daoimport org.app.models.BookModelimport scala.collection.mutable.ListBuffer//图书&#xff0c;数据操作层 class BookDAO {//加载图书&#xff0c;从文件中读入def loadBooks(): ListBuffer[BookModel] {val books new ListBuffer[BookModel](…...

Java 类加载机制

什么是类 类是现实世界的实体在计算中的映射、它将数据以及对这些数据的操作封装在一起。 类加载的定义 类加载是 JVM 运行时的一个动作、支持将 class 动态加载到 JVM 中 类加载是一种懒加载模式、按需加载。 类加载到五个过程 加载验证准备解释初始化 提一点&#xff0…...

Lombok是银弹?还是陷阱?

Lombok 是一个 Java 库&#xff0c;它通过注解简化和减少了 Java 中的样板代码&#xff08;boilerplate code&#xff09;&#xff0c;例如 getter/setter 方法、构造函数、equals 和 hashCode 方法等。 对于是否将 Lombok 视为“银弹”或“陷阱”&#xff0c;这实际上取决于你…...

大数据技术-Hadoop(四)Yarn的介绍与使用

目录 一、Yarn 基本结构 1、Yarn基本结构 2、Yarn的工作机制 二、Yarn常用的命令 三、调度器 1、Capacity Scheduler&#xff08;容量调度器&#xff09; 1.1、特点 1.2、配置 1.2.1、yarn-site.xml 1.2.2、capacity-scheduler.xml 1.3、重启yarn、刷新队列 测试 向hi…...

CentOS修改docker镜像存储位置并进行数据迁移

在 CentOS 上修改 Docker 镜像存储位置并进行数据迁移是一个常见的需求。以下是一个详细的步骤指南&#xff0c;帮助你完成这个任务。 1. 停止 Docker 服务 首先&#xff0c;确保 Docker 服务已经停止&#xff0c;以避免在迁移过程中出现数据损坏。 sudo systemctl stop doc…...

xterm + vue3 + websocket 终端界面

xterm.js 下载插件 // xterm npm install --save xterm// xterm-addon-fit 使终端适应包含元素 npm install --save xterm-addon-fit// xterm-addon-attach 通过websocket附加到运行中的服务器进程 npm install --save xterm-addon-attach <template><div :…...

解锁 CSS:网页美化与布局的艺术

目录 一、CSS 是什么 二、CSS 的作用 三、CSS 的应用方式&#xff08;引用方式&#xff09; 四、选择器&#xff1a;如何挑选要 “打扮” 的元素 五、CSS 属性&#xff1a;丰富多样的 “服装款式” 字体属性&#xff1a; 文本属性&#xff1a;只能控制文字的相关样式。 …...

AWS K8s 部署架构

Amazon Web Services&#xff08;AWS&#xff09;提供了一种简化的Kubernetes&#xff08;K8s&#xff09;部署架构&#xff0c;使得在云环境中管理和扩展容器化应用变得更加容易。这个架构的核心是AWS EKS&#xff08;Elastic Kubernetes Service&#xff09;&#xff0c;它是…...

【鸿蒙NEXT】鸿蒙里面类似iOS的Keychain——关键资产(@ohos.security.asset)实现设备唯一标识

前言 在iOS开发中Keychain 是一个非常安全的存储系统&#xff0c;用于保存敏感信息&#xff0c;如密码、证书、密钥等。与 NSUserDefaults 或文件系统不同&#xff0c;Keychain 提供了更高的安全性&#xff0c;因为它对数据进行了加密&#xff0c;并且只有经过授权的应用程序才…...

电子电器架构 --- HUD的工作原理

我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 所谓鸡汤,要么蛊惑你认命,要么怂恿你拼命,但都是回避问题的根源,以现象替代逻辑,以情绪代替思考,把消极接受现实的懦弱,伪装成乐观面对不幸的…...

C# 窗体应用程序嵌套web网页,基于谷歌浏览器内核(含源码)

有一个winform项目&#xff0c;需要借助一个web项目来显示&#xff0c;并且对web做一些操作,web页目是需要用谷歌内核&#xff0c;基于谷歌 Chromium项目的开源Web Browser控件来开发写了一个demo。 安装步骤 第一步&#xff1a;右键项目&#xff0c;点击 管理NuGet程序包 , 输…...

FFmpeg 中 examples 使用教程

FFmpeg 中 examples FFmpeg 的 examples 目录包含了一系列示例程序,旨在展示如何使用 FFmpeg 的不同库和 API。这些示例涵盖了多种功能,包括音视频编解码、格式转换、过滤、网络传输等。以下是一些常见的示例程序及其功能介绍: 音频和视频解码: 示例程序展示了如何打开音视…...

自动化办公-合并多个excel

在日常的办公自动化工作中&#xff0c;尤其是处理大量数据时&#xff0c;合并多个 Excel 表格是一个常见且繁琐的任务。幸运的是&#xff0c;借助 Python 语言中的强大库&#xff0c;我们可以轻松地自动化这个过程。本文将带你了解如何使用 Python 来合并多个 Excel 表格&#…...

Docker搭建MySQL

Docker搭建MySQL 准备工作 先准备配置目录和持久化目录&#xff0c;举个栗子&#xff1a;mkdir -p /opt/module/mysql/{conf,data,log}准备配置文件*.cnf,放到/opt/module/mysql/conf目录下。当然不准备也没事&#xff0c;容器中有个默认配置&#xff1a;/etc/mysql/conf.d/m…...

亚马逊国际站商品爬虫:Python实战指南

在数字化时代&#xff0c;数据的价值不言而喻。对于电商领域而言&#xff0c;获取竞争对手的商品信息、价格、评价等数据&#xff0c;对于市场分析和策略制定至关重要。本文将带你了解如何使用Python编写爬虫&#xff0c;以亚马逊国际站为例&#xff0c;按照关键字搜索并获取商…...

pwntools用法

pwntools 是一个Python库&#xff0c; 用于编写二进制漏洞利用&#xff08;exploitation&#xff09;脚本 功能&#xff1a; 远程连接和本地连接&#xff1a; 支持通过TCP/UDP连接远程服务或与本地进程进行交互。Shellcode和ROP链构造&#xff1a; 提供了便捷的工具来生成和利…...

企业云盘怎么选?2024年免费版9款整理

文章介绍了以下9大企业云盘&#xff1a;1.亿方云&#xff1b;2.Worktile&#xff1b;3.百度网盘&#xff1b;4.腾讯云盘&#xff1b;5.阿里云盘&#xff1b;6.金山云盘&#xff1b;7.Dropbox&#xff1b;8.Box。 在企业日常管理中&#xff0c;文件存储和共享一直是个不小的难题…...

Linux之ARM(MX6U)裸机篇----5.仿stm32的LED驱动实验

一&#xff0c;启动文件 .global _start .global _bss_start /* 类似宏定义把__bss_start定义为_bss_start */ _bss_start:.word __bss_start.global _bss_end _bss_end:.word __bss_end_start:#设置处理器进入SVC模式mrs r0, cpsr /* 读取cpsr到r0 */bic r0, r0, …...

Qt从入门到入土(七)-实现炫酷的登录注册界面(下)

前言 Qt从入门到入土&#xff08;六&#xff09;-实现炫酷的登录注册界面&#xff08;上&#xff09;主要讲了如何使用QSS样式表进行登录注册的界面设计&#xff0c;本篇文章将介绍如何对登录注册界面进行整体控件的布局&#xff0c;界面的切换以及实现登录、记住密码等功能。…...

如何进行年度工作回顾?

发生了什么事&#xff1f; 什么事情进展顺利 &#xff1f; 什么事情进展不顺利&#xff1f; 如何适应未来&#xff1f; 年度回顾的定义&#xff1a;这是一种战略工具&#xff0c;能帮助人们清晰看到过去一年对业务、职业或个人生活的影响&#xff0c;可用于明确关键事件、找出问…...

spring默认线程池SimpleAsyncTaskExecutor特点为什么要尽量避免使用

在 Spring Boot 中&#xff0c;默认的线程池配置由 TaskExecutionAutoConfiguration 类提供&#xff0c;使用的是 SimpleAsyncTaskExecutor。 SimpleAsyncTaskExecutor特点 每次调用创建新线程&#xff1a; SimpleAsyncTaskExecutor 每次执行任务时都会创建一个新线程&#xf…...

每天40分玩转Django:Django表单集

Django表单集 一、知识要点概览表 类别知识点掌握程度要求基础概念FormSet、ModelFormSet深入理解内联表单集InlineFormSet、BaseInlineFormSet熟练应用表单集验证clean方法、验证规则熟练应用自定义配置extra、max_num、can_delete理解应用动态管理JavaScript动态添加/删除表…...

构建混合技术栈的统一监控与日志平台

文章目录 摘要引言构建统一监控与日志平台的核心思路痛点分析解决方案 平台架构设计架构概览 环境准备Java 服务的 Prometheus 指标导出Prometheus 指标采集模块Node.js 日志收集模块3. Logstash 配置4. Grafana 与 Kibana 配置 QA 环节总结未来展望参考资料 摘要 在多技术栈开…...

KOI技术-事件驱动编程(Sping后端)

1 “你日渐平庸&#xff0c;甘于平庸&#xff0c;将继续平庸。”——《以自己喜欢的方式过一生》 2. “总是有人要赢的&#xff0c;那为什么不能是我呢?”——科比布莱恩特 3. “你那么憎恨那些人&#xff0c;和他们斗了那么久&#xff0c;最终却要变得和他们一样&#xff0c;…...

ubuntu 20.04 国内源安装docker

先更新软件包&#xff0c;安装备要apt软件 # 更新软件包索引 sudo apt-get update# 安装需要的软件包以使apt能够通过HTTPS使用仓库 sudo apt-get install ca-certificates curl gnupg lsb-release使用阿里云源 # 添加阿里云官方GPG密钥 curl -fsSL http://mirrors.aliyun.co…...

微信小程序 app.json 配置文件解析与应用

目录 一、什么是 app.json&#xff1f; 二、app.json 文件的基本结构 三、详细解析 app.json 配置项 1. pages&#xff1a;小程序页面路径配置 2. window&#xff1a;窗口样式配置 3. tabBar&#xff1a;底部标签栏配置 4. networkTimeout&#xff1a;网络请求超时配置 …...

C高级:思维导图Day2

目录 总览1 总览2 总览1 压缩与解压缩 打包与解包 软连接与硬链接 ubuntu下关机与重启指令 总览2 结束...

蓝桥杯(Java)(ing)

Java前置知识 输入流&#xff1a; &#xff08;在Java面向对象编程-CSDN博客里面有提过相关知识------IO流&#xff09; // 快读快写 static BufferedReader in new BufferedReader(new InputStreamReader(System.in)); static BufferedWriter out new BufferedWriter(new…...

[Pro Git#2] 分支管理 | branch fix_bug , feature | 处理合并冲突

目录 一、Issue模板文件 二、Pull Requests模板文件 分支管理 1. 理解分支 2. 创建与管理分支 1. 切换分支与提交历史 2. 合并分支 3. 删除分支 4. 解决合并冲突 6. 查看分支合并情况 快速创建并切换分支 分支管理策略 分支合并模式 分支管理原则 日常开发环境 …...

Java——集合框架

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 1 集合框架概述1.1 内存层面需要针对多个数据进行存储。此时&#xff0c;可以考虑的容器有&#xff1a;1.2 数组存储多个数据方面的特点和弊端1.3 Java集合框架体系…...

Mac 环境 VVenC 编译与编码命令行工具使用教程

VVenC VVenC 是一个开源的高效视频编码器&#xff0c;专门用于支持 H.266/VVC (Versatile Video Coding) 标准的编码。H.266/VVC 是继 HEVC (H.265) 之后的新一代视频编码标准&#xff0c;主要目的是提供比 HEVC 更高的压缩效率&#xff0c;同时保持或提高视频质量。H.266/VVC…...

WebRTC:实现浏览器与移动应用的实时通信

1.技术简介 &#xff08;Web Real-Time&#xff09;是一种开放式实时通信技术&#xff0c;旨在使浏览器和移动应用程序通过简单的API即可实现实时音频、视频和数据传输&#xff0c;而无需安装插件或额外软件。它支持网络应用中的点对点通信&#xff0c;例如视频聊天、语音通话…...

curl+openssl 踩坑笔记

curl编译&#xff1a;点击跳转 踩坑一 * SSL certificate problem: unable to get local issuer certificate * closing connection #0 curl: (60) SSL certificate problem: unable to get local issuer certificate More details here: https://curl.se/docs/sslcerts.html …...

【NebulaGraph】变化的多跳查询

【NebulaGraph】变化的多跳查询 1. 需求2. 解决方案2.1 确定查询结构2.2 构建查询语句 3. 追加需求&#xff1a;如果增加每一跳都要指定查询某SPACE下的Tag&#xff0c;或者不查询某个Tag怎么办 1. 需求 存在多跳请求&#xff0c;其中每一跳是从上一跳查询结果为基础的。但是 …...

【C++】九九乘法表编程题详解与多角度对比分析

博客主页&#xff1a; [小ᶻ☡꙳ᵃⁱᵍᶜ꙳] 本文专栏: C 文章目录 &#x1f4af;前言&#x1f4af;题目概述题目描述 &#x1f4af;老师的实现方法代码解析优点不足 &#x1f4af;我的实现方法代码解析优点不足 &#x1f4af;实现方法对比&#x1f4af;优化与扩展代码优化…...

node.js卸载并重新安装(超详细图文步骤)

卸载node.js 重新安装nodejs 一、卸载 1、首先进入控制面板卸载程序 2、卸载后 到文件夹中进行进一步的删除 删除上述的几个文件夹 每个人可能不一样&#xff0c;总之是找到自己的nodejs安装路径&#xff0c;下面是我的 ①删除C:UsersAdminAppDataRoaming路径下的npm相关文件…...

redis的集群模式与ELK基础

一、redis的集群模式 1.主从复制 &#xff08;1&#xff09;概述 主从模式&#xff1a;这是redis高可用的基础&#xff0c;哨兵和集群都是建立在此基础之上。 主从模式和数据库的主从模式是一样的&#xff0c;主负责写入&#xff0c;然后把写入的数据同步到从服务器&#xff…...