使用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_key
、tavily_key
和 mongo_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 生成消息之后,通过 langgraph
的 add_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
目前流程图长这样:
图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大模型时代的学习之旅:从基础到前沿,掌握人工智能的核心技能!
二、640套AI大模型报告合集
这套包含640份报告的合集,涵盖了AI大模型的理论研究、技术实现、行业应用等多个方面。无论您是科研人员、工程师,还是对AI大模型感兴趣的爱好者,这套报告合集都将为您提供宝贵的信息和启示。
三、AI大模型经典PDF籍
随着人工智能技术的飞速发展,AI大模型已经成为了当今科技领域的一大热点。这些大型预训练模型,如GPT-3、BERT、XLNet等,以其强大的语言理解和生成能力,正在改变我们对人工智能的认识。 那以下这些PDF籍就是非常不错的学习资源。
四、AI大模型商业化落地方案
作为普通人,入局大模型时代需要持续学习和实践,不断提高自己的技能和认知水平,同时也需要有责任感和伦理意识,为人工智能的健康发展贡献力量。
相关文章:
使用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以及之前版本不支持属性名和属性值一样,可以只写属性名src属性:指定音频文件…...
【SQLi_Labs】Basic Challenges
什么是人生?人生就是永不休止的奋斗! Less-1 尝试添加’注入,发现报错 这里我们就可以直接发现报错的地方,直接将后面注释,然后使用 1’ order by 3%23 //得到列数为3 //这里用-1是为了查询一个不存在的id,好让第一…...
InnoDB存储引擎对MVCC的实现
多版本并发控制 (Multi-Version Concurrency Control) MVCC(Multi-Version Concurrency Control),即多版本并发控制,是一种并发控制方法,主要用于数据库管理系统中实现对数据库的并发访问。以下是MVCC的详细解释&#…...
3D线上艺术展:艺术与技术的完美融合
随着数字技术的飞速发展,未来的艺术展览正逐步迈向线上线下融合的新阶段。其中,3D线上展览以其独特的魅力,成为线下展览的延伸与拓展,为艺术爱好者们开辟了全新的观赏途径。 对于艺术家和策展人而言,3D线上展览不仅打…...
EasyExcel(读取操作和填充操作)
文章目录 1.准备Read.xlsx(具有两个sheet)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)的性能
当前内容所在位置(可进入专栏查看其他译好的章节内容) 第五部分 添加动效 ✔️【第 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 等,内置中间件和多种插件。社区支持广泛:拥有大量使用者,资料…...
连锁餐饮行业数据可视化分析方案
引言 随着连锁餐饮行业的迅速发展,市场竞争日益激烈。企业需要更加精准地把握运营状况、消费者需求和市场趋势,以制定科学合理的决策,提升竞争力和盈利能力。可视化数据分析可以帮助连锁餐饮企业整合多源数据,通过直观、动态的可…...
如何通过采购管理系统提升供应链协同效率?
供应链是企业运营的命脉,任何环节的延迟或失误都会对企业造成严重影响。在采购环节中,如何保证与供应商的协同效率,避免因信息不对称而导致的决策失误,是企业面临的一大挑战。采购管理系统作为数字化供应链管理的重要工具…...
1、Jmeter、jdk下载与安装
1、访问官网,点击下载Jmeter http://jmeter.apache.org/ 2、在等待期间,下载对应的Java https://www.oracle.com/cn/java/technologies/downloads/#jdk23-windows 3、全部下载好,先安装JDK : ListBuffer[BookModel] {val books new ListBuffer[BookModel](…...
Java 类加载机制
什么是类 类是现实世界的实体在计算中的映射、它将数据以及对这些数据的操作封装在一起。 类加载的定义 类加载是 JVM 运行时的一个动作、支持将 class 动态加载到 JVM 中 类加载是一种懒加载模式、按需加载。 类加载到五个过程 加载验证准备解释初始化 提一点࿰…...
Lombok是银弹?还是陷阱?
Lombok 是一个 Java 库,它通过注解简化和减少了 Java 中的样板代码(boilerplate code),例如 getter/setter 方法、构造函数、equals 和 hashCode 方法等。 对于是否将 Lombok 视为“银弹”或“陷阱”,这实际上取决于你…...
大数据技术-Hadoop(四)Yarn的介绍与使用
目录 一、Yarn 基本结构 1、Yarn基本结构 2、Yarn的工作机制 二、Yarn常用的命令 三、调度器 1、Capacity Scheduler(容量调度器) 1.1、特点 1.2、配置 1.2.1、yarn-site.xml 1.2.2、capacity-scheduler.xml 1.3、重启yarn、刷新队列 测试 向hi…...
CentOS修改docker镜像存储位置并进行数据迁移
在 CentOS 上修改 Docker 镜像存储位置并进行数据迁移是一个常见的需求。以下是一个详细的步骤指南,帮助你完成这个任务。 1. 停止 Docker 服务 首先,确保 Docker 服务已经停止,以避免在迁移过程中出现数据损坏。 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 的应用方式(引用方式) 四、选择器:如何挑选要 “打扮” 的元素 五、CSS 属性:丰富多样的 “服装款式” 字体属性: 文本属性:只能控制文字的相关样式。 …...
AWS K8s 部署架构
Amazon Web Services(AWS)提供了一种简化的Kubernetes(K8s)部署架构,使得在云环境中管理和扩展容器化应用变得更加容易。这个架构的核心是AWS EKS(Elastic Kubernetes Service),它是…...
【鸿蒙NEXT】鸿蒙里面类似iOS的Keychain——关键资产(@ohos.security.asset)实现设备唯一标识
前言 在iOS开发中Keychain 是一个非常安全的存储系统,用于保存敏感信息,如密码、证书、密钥等。与 NSUserDefaults 或文件系统不同,Keychain 提供了更高的安全性,因为它对数据进行了加密,并且只有经过授权的应用程序才…...
电子电器架构 --- HUD的工作原理
我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 所谓鸡汤,要么蛊惑你认命,要么怂恿你拼命,但都是回避问题的根源,以现象替代逻辑,以情绪代替思考,把消极接受现实的懦弱,伪装成乐观面对不幸的…...
C# 窗体应用程序嵌套web网页,基于谷歌浏览器内核(含源码)
有一个winform项目,需要借助一个web项目来显示,并且对web做一些操作,web页目是需要用谷歌内核,基于谷歌 Chromium项目的开源Web Browser控件来开发写了一个demo。 安装步骤 第一步:右键项目,点击 管理NuGet程序包 , 输…...
FFmpeg 中 examples 使用教程
FFmpeg 中 examples FFmpeg 的 examples 目录包含了一系列示例程序,旨在展示如何使用 FFmpeg 的不同库和 API。这些示例涵盖了多种功能,包括音视频编解码、格式转换、过滤、网络传输等。以下是一些常见的示例程序及其功能介绍: 音频和视频解码: 示例程序展示了如何打开音视…...
自动化办公-合并多个excel
在日常的办公自动化工作中,尤其是处理大量数据时,合并多个 Excel 表格是一个常见且繁琐的任务。幸运的是,借助 Python 语言中的强大库,我们可以轻松地自动化这个过程。本文将带你了解如何使用 Python 来合并多个 Excel 表格&#…...
Docker搭建MySQL
Docker搭建MySQL 准备工作 先准备配置目录和持久化目录,举个栗子:mkdir -p /opt/module/mysql/{conf,data,log}准备配置文件*.cnf,放到/opt/module/mysql/conf目录下。当然不准备也没事,容器中有个默认配置:/etc/mysql/conf.d/m…...
亚马逊国际站商品爬虫:Python实战指南
在数字化时代,数据的价值不言而喻。对于电商领域而言,获取竞争对手的商品信息、价格、评价等数据,对于市场分析和策略制定至关重要。本文将带你了解如何使用Python编写爬虫,以亚马逊国际站为例,按照关键字搜索并获取商…...
pwntools用法
pwntools 是一个Python库, 用于编写二进制漏洞利用(exploitation)脚本 功能: 远程连接和本地连接: 支持通过TCP/UDP连接远程服务或与本地进程进行交互。Shellcode和ROP链构造: 提供了便捷的工具来生成和利…...
企业云盘怎么选?2024年免费版9款整理
文章介绍了以下9大企业云盘:1.亿方云;2.Worktile;3.百度网盘;4.腾讯云盘;5.阿里云盘;6.金山云盘;7.Dropbox;8.Box。 在企业日常管理中,文件存储和共享一直是个不小的难题…...
Linux之ARM(MX6U)裸机篇----5.仿stm32的LED驱动实验
一,启动文件 .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从入门到入土(六)-实现炫酷的登录注册界面(上)主要讲了如何使用QSS样式表进行登录注册的界面设计,本篇文章将介绍如何对登录注册界面进行整体控件的布局,界面的切换以及实现登录、记住密码等功能。…...
如何进行年度工作回顾?
发生了什么事? 什么事情进展顺利 ? 什么事情进展不顺利? 如何适应未来? 年度回顾的定义:这是一种战略工具,能帮助人们清晰看到过去一年对业务、职业或个人生活的影响,可用于明确关键事件、找出问…...
spring默认线程池SimpleAsyncTaskExecutor特点为什么要尽量避免使用
在 Spring Boot 中,默认的线程池配置由 TaskExecutionAutoConfiguration 类提供,使用的是 SimpleAsyncTaskExecutor。 SimpleAsyncTaskExecutor特点 每次调用创建新线程: SimpleAsyncTaskExecutor 每次执行任务时都会创建一个新线程…...
每天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 “你日渐平庸,甘于平庸,将继续平庸。”——《以自己喜欢的方式过一生》 2. “总是有人要赢的,那为什么不能是我呢?”——科比布莱恩特 3. “你那么憎恨那些人,和他们斗了那么久,最终却要变得和他们一样,…...
ubuntu 20.04 国内源安装docker
先更新软件包,安装备要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? 二、app.json 文件的基本结构 三、详细解析 app.json 配置项 1. pages:小程序页面路径配置 2. window:窗口样式配置 3. tabBar:底部标签栏配置 4. networkTimeout:网络请求超时配置 …...
C高级:思维导图Day2
目录 总览1 总览2 总览1 压缩与解压缩 打包与解包 软连接与硬链接 ubuntu下关机与重启指令 总览2 结束...
蓝桥杯(Java)(ing)
Java前置知识 输入流: (在Java面向对象编程-CSDN博客里面有提过相关知识------IO流) // 快读快写 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——集合框架
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 1 集合框架概述1.1 内存层面需要针对多个数据进行存储。此时,可以考虑的容器有:1.2 数组存储多个数据方面的特点和弊端1.3 Java集合框架体系…...
Mac 环境 VVenC 编译与编码命令行工具使用教程
VVenC VVenC 是一个开源的高效视频编码器,专门用于支持 H.266/VVC (Versatile Video Coding) 标准的编码。H.266/VVC 是继 HEVC (H.265) 之后的新一代视频编码标准,主要目的是提供比 HEVC 更高的压缩效率,同时保持或提高视频质量。H.266/VVC…...
WebRTC:实现浏览器与移动应用的实时通信
1.技术简介 (Web Real-Time)是一种开放式实时通信技术,旨在使浏览器和移动应用程序通过简单的API即可实现实时音频、视频和数据传输,而无需安装插件或额外软件。它支持网络应用中的点对点通信,例如视频聊天、语音通话…...
curl+openssl 踩坑笔记
curl编译:点击跳转 踩坑一 * 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. 追加需求:如果增加每一跳都要指定查询某SPACE下的Tag,或者不查询某个Tag怎么办 1. 需求 存在多跳请求,其中每一跳是从上一跳查询结果为基础的。但是 …...
【C++】九九乘法表编程题详解与多角度对比分析
博客主页: [小ᶻ☡꙳ᵃⁱᵍᶜ꙳] 本文专栏: C 文章目录 💯前言💯题目概述题目描述 💯老师的实现方法代码解析优点不足 💯我的实现方法代码解析优点不足 💯实现方法对比💯优化与扩展代码优化…...
node.js卸载并重新安装(超详细图文步骤)
卸载node.js 重新安装nodejs 一、卸载 1、首先进入控制面板卸载程序 2、卸载后 到文件夹中进行进一步的删除 删除上述的几个文件夹 每个人可能不一样,总之是找到自己的nodejs安装路径,下面是我的 ①删除C:UsersAdminAppDataRoaming路径下的npm相关文件…...
redis的集群模式与ELK基础
一、redis的集群模式 1.主从复制 (1)概述 主从模式:这是redis高可用的基础,哨兵和集群都是建立在此基础之上。 主从模式和数据库的主从模式是一样的,主负责写入,然后把写入的数据同步到从服务器ÿ…...