AI智能体记忆架构设计:从分层模型到工程实践

news2026/5/9 1:19:09
1. 项目概述从“记忆”视角重构智能体架构最近在折腾AI智能体项目时我遇到了一个几乎所有开发者都会头疼的经典问题智能体“记性”太差。一个会话稍微长点或者任务稍微复杂点它要么忘了上下文要么把关键指令给弄混了整个对话逻辑就开始跑偏。这就像让一个短期失忆症患者去执行一个多步骤的复杂项目每一步都得重新提醒他“你是谁”、“你要干嘛”、“上一步做了什么”效率低得令人抓狂。正是在这种背景下我注意到了futhgar/agent-memory-architecture这个项目。光看名字就很有意思它没有叫“XX智能体框架”或者“XX对话系统”而是直指核心——“智能体记忆架构”。这让我意识到它要解决的恐怕不是某个具体功能而是智能体底层的一个根本性能力如何像人一样有效地组织、存储、检索和利用“记忆”从而让智能体具备连贯性、长期性和情境感知能力。简单来说这个项目探讨的是如何为AI智能体设计一套“大脑”让它不仅能处理当前输入还能记住过去、规划未来在复杂的多轮交互中保持稳定和智能。这不仅仅是加个向量数据库存聊天记录那么简单它涉及到记忆的分类短期、长期、工作记忆、记忆的编码与索引策略、记忆的检索与关联机制以及最终如何将这些记忆有效地融入决策和生成过程。对于任何想要构建真正实用、可靠的智能体应用无论是客服助手、编程副驾还是游戏NPC的开发者来说这都是一个必须啃下来的硬骨头。接下来我会结合自己的实践和这个项目的思路拆解一套可落地的智能体记忆架构设计方案。我们会从为什么需要记忆开始一步步深入到记忆的类型、存储引擎的选择、检索算法的优化最后通过一个实战案例看看如何把这些理论变成代码。无论你是刚接触智能体的新手还是正在为智能体“健忘”而烦恼的老手相信这套架构思路都能给你带来直接的启发。2. 记忆架构的核心价值与设计哲学2.1 为什么“记忆”是智能体的阿喀琉斯之踵在深入技术细节之前我们必须先达成一个共识为什么传统的、基于大语言模型LLM单次调用的聊天模式在复杂任务中会失效核心原因在于LLM本质上是“无状态”的。每次你发送一个请求模型看到的都是一个全新的、孤立的文本片段。它没有内置的机制去“记住”三句话之前你说了什么更别提上一个会话、甚至昨天聊过的话题了。这就导致了几个典型问题上下文丢失在长对话中智能体很容易忘记最初的指令或目标。比如你让一个智能体帮你写一份项目计划书聊了十几轮关于市场分析、技术方案后你问“那我们最初定的项目核心优势是什么”它很可能已经忘了。身份与角色混乱你为智能体精心设定了角色如“资深Python导师”但在多轮交互后它的回答风格可能逐渐偏离甚至开始用其他角色的口吻说话。无法进行长期规划与学习一个理想的智能体应该能从历史交互中学习。比如它应该记住用户“不喜欢过于冗长的解释”或者“在讨论代码时偏好用Go语言举例”。传统的一次性上下文窗口无法积累这种长期偏好。agent-memory-architecture项目正是瞄准了这些痛点。它的设计哲学不是简单地“扩容上下文”而是模拟人类记忆系统的分层与动态处理机制。人类大脑有海马体负责短期记忆到长期记忆的转化有前额叶皮层管理“工作记忆”来处理当前任务。一个好的智能体记忆架构也应该有类似的职责划分。2.2 分层记忆模型短期、长期与工作记忆一个健壮的记忆架构通常采用分层设计这是该项目的核心思想之一。我们可以将其类比为计算机系统的存储层次结构寄存器-缓存-内存-硬盘。短期记忆相当于对话的“上下文窗口”。它容量小受限于LLM的Token限制存取速度快用于保持当前对话的连贯性。例如最近几轮的用户提问和智能体回答。这部分通常直接放在提示词Prompt中。长期记忆相当于外置的“知识库”或“数据库”。它容量理论上无限存取速度相对较慢需要检索用于存储跨越多个会话的重要信息。例如核心身份与指令智能体的角色设定、基础行为准则、不可违背的规则。用户档案用户的姓名、偏好、历史行为模式如“用户是前端开发对React更熟悉”。重要事实与知识在对话中产生的、需要长期保留的结论或数据如“用户决定将项目命名为‘星海’”、“用户公司的技术栈是JavaSpringBoot”。会话摘要对过去完整会话的浓缩总结用于在开启新会话时快速恢复上下文。工作记忆这是最精妙的一层相当于CPU的“寄存器”。它不是一个独立的存储区而是一个动态组装的过程。当智能体需要处理当前任务时它会从长期记忆中主动检索出与当前情境最相关的记忆片段并将其与短期记忆组合在一起形成送给LLM的最终提示词。这个过程是高度情境化的、动态的。注意很多初学者会把所有聊天记录一股脑塞进向量数据库然后每次检索Top K条。这会导致噪音极大相关度低。正确的做法是在存入长期记忆前就对记忆内容进行结构化或摘要化处理并打上丰富的元数据标签如记忆类型、关联实体、时间戳、重要性分数为高质量检索打下基础。2.3 架构设计的关键权衡设计记忆架构时你始终在几个维度上进行权衡保真度 vs. 效率存储原始对话保真度高但占用空间大、检索慢存储摘要效率高但可能丢失细节。一个常见策略是混合存储摘要用于快速关联检索当需要细节时再通过摘要中的索引找到原始记录。实时性 vs. 一致性记忆的写入和更新是否需要强一致性对于用户偏好可能需要实时更新对于会话历史可以异步批处理。这会影响你选择数据库的类型如关系型数据库ACID vs. 向量数据库的最终一致性。泛化能力 vs. 精准控制依靠向量检索的语义相似度泛化能力强能发现潜在关联但可能召回不相关结果基于关键词或结构化标签的检索精准可控但缺乏灵活性。混合检索Hybrid Search是目前的主流方案。理解了这些设计哲学我们就能明白futhgar/agent-memory-architecture提供的不是一个开箱即用的轮子而是一套构建轮子的蓝图和方法论。它指导我们如何根据自己智能体的具体任务是开放域聊天还是垂直领域任务来选择和组合不同的技术组件。3. 记忆系统的核心组件与技术选型3.1 记忆的存储后端不止于向量数据库谈到记忆存储很多人第一反应就是向量数据库如 Pinecone, Weaviate, Qdrant。这没错向量数据库通过嵌入Embedding模型将文本转换为高维向量并支持基于语义相似度的快速检索非常适合存储和检索非结构化的“经验”或“知识”片段。但是一个完整的记忆系统需要多种存储后端协同工作向量数据库存储非结构化记忆文本的嵌入向量。选型要点关注其是否支持过滤Filtering、是否提供混合检索、单次查询的延迟和吞吐量、以及成本。对于中小型项目甚至可以使用ChromaDB或FAISS这类轻量级、可嵌入的库。关系型数据库或文档数据库存储结构化的记忆元数据。例如memory_id: 记忆唯一标识。user_id: 所属用户。session_id: 所属会话。type: 记忆类型user_preference,fact,summary等。entities: 关联的实体列表如[项目A, Python, 部署]。created_at/accessed_at: 创建和最后访问时间。importance_score: 重要性分数可通过LLM或规则生成。raw_text或summary_text: 记忆的原文或摘要。embedding_id: 对应向量数据库中的向量ID。 这部分用 PostgreSQL、MySQL 或 MongoDB 都可以。关系型数据库在复杂查询和事务上更有优势。缓存用于存放高频访问的“热记忆”比如当前用户的个人资料、智能体的核心指令。Redis 或 Memcached 是理想选择能极大降低对主存储的查询压力。实操心得不要试图用向量数据库解决所有问题。我的建议是用关系型数据库做“索引簿”和“元数据管理器”用向量数据库做“内容检索器”。当需要检索时先根据时间、类型、实体等条件在关系库中过滤出一批候选记忆的ID再用这些ID去向量库做精准的相似度检索。这比直接在亿级向量中做全量搜索要高效、精准得多。3.2 记忆的编码与嵌入质量决定一切记忆在存入向量数据库前需要被编码成向量。这个过程的质量直接决定了后续检索的效果。嵌入模型的选择通用 vs. 领域专用对于通用聊天text-embedding-ada-002或开源模型如BGE-M3、Snowflake Arctic Embed是不错的选择。如果你的智能体专注于法律、医疗等专业领域使用在该领域语料上微调过的嵌入模型效果会有显著提升。上下文长度确保嵌入模型支持的上下文长度足够覆盖你的单条记忆文本。过长的文本需要先进行分割或摘要。向量维度更高的维度通常意味着更强的表现力但也会增加存储和计算成本。需要权衡。记忆文本的预处理 这是提升检索精度的关键一步却最容易被忽视。原始对话文本往往冗长、包含大量无关信息如语气词、重复内容。# 一个简单的记忆预处理示例概念性代码 def create_memory_entry(raw_text, memory_type, session_info): # 1. 清理文本去除无关格式、特殊字符 cleaned_text clean_text(raw_text) # 2. 摘要化对于长文本用LLM生成简洁的摘要 if len(cleaned_text.split()) 100: # 假设超过100词则摘要 summary llm_generate_summary(cleaned_text) memory_text_for_embedding summary raw_text_to_store cleaned_text # 原始文本另存 else: memory_text_for_embedding cleaned_text raw_text_to_store cleaned_text # 3. 信息增强为记忆添加“提示”前缀引导嵌入模型理解其类型 # 例如“用户偏好” “用户喜欢用dark mode” # “客观事实” “项目截止日期是2024-10-01” enhanced_text f[{memory_type}]: {memory_text_for_embedding} # 4. 提取实体使用NER模型或LLM提取文本中的关键实体 entities extract_entities(enhanced_text) # 5. 生成嵌入向量 embedding_vector embed_model.encode(enhanced_text) # 6. 组装结构化记忆对象 memory_obj { id: generate_uuid(), raw_text: raw_text_to_store, text_for_embedding: enhanced_text, embedding: embedding_vector, type: memory_type, entities: entities, session_id: session_info[id], created_at: datetime.now(), importance: calculate_importance(memory_type, enhanced_text) # 简单规则或LLM打分 } return memory_obj通过这样的预处理你存入的就不再是原始杂乱的文本而是经过提炼、增强的结构化记忆单元检索相关性会大大提高。3.3 记忆的检索与召回策略从相似度到相关性检索是记忆系统的灵魂。目标是在毫秒级时间内从海量记忆中找出与当前情境最相关的几条。单纯依赖余弦相似度Cosine Similarity的向量检索在复杂场景下往往不够用。1. 混合检索 结合语义搜索和元数据过滤。例如当前用户询问“我们之前讨论的那个Python项目的进度如何”。检索流程可以是步骤一元数据过滤在关系型数据库中筛选出user_id当前用户、type包含fact或project_update、entities包含Python的所有记忆ID。这步能快速排除大量无关记忆。步骤二语义检索将上述过滤出的记忆ID对应的嵌入向量在向量数据库中进行相似度查询查询向量是当前问题“Python项目进度”的嵌入。按相似度得分排序。步骤三重排序将前两步得到的结果比如Top 20条进行融合和重排序。这里可以引入更复杂的算法比如考虑记忆的重要性分数、新鲜度accessed_at越近分数越高、以及多样性避免返回过多高度重复的记忆。2. 递归检索与思维链 对于复杂问题单次检索可能不够。可以采用“递归检索”策略先用当前问题检索出一批记忆然后用LLM分析这批记忆生成一个更精准的“修正查询”再进行第二次检索。这模拟了人类思考时“先想起一些线索再顺着线索深入回忆”的过程。3. 记忆链 在存储时就有意识地将相关的记忆链接起来。例如一条关于“决定采用微服务架构”的记忆可以链接到之前“讨论架构选型”的记忆和之后“制定API网关规范”的记忆。检索时如果找到其中一条可以顺藤摸瓜将其关联记忆也一并召回提供更完整的背景。踩坑记录早期我们只做向量检索经常出现“答非所问”。比如用户问“上次吃饭那家餐厅叫什么”因为“餐厅”和“吃饭”的语义关联可能会召回“上次在餐厅讨论项目”的记忆而真正关于“餐厅名字”的记忆因为表述为“那家意大利馆子”而没被召回。引入基于type“restaurant_name”的元数据过滤后这个问题立刻解决了。教训是语义检索负责“联想”元数据过滤负责“精准”两者缺一不可。4. 实战构建一个具备记忆的编程助手智能体理论说了这么多我们来动手搭建一个简化但完整的、具备记忆能力的编程助手智能体。这个助手能记住用户的编程偏好、项目上下文和教过它的知识点。4.1 系统架构与数据流设计我们设计一个三层架构应用层处理用户交互管理对话状态短期记忆。记忆管理层核心组件负责记忆的编码、存储、检索和更新。存储层由 PostgreSQL存元数据和 ChromaDB存向量组成。数据流如下用户输入进入系统。记忆检索记忆管理器结合当前对话上下文短期记忆和用户输入生成检索查询从长期记忆中召回相关记忆。提示词组装将用户输入、短期记忆、检索到的长期记忆以及智能体的系统指令组装成完整的提示词。LLM调用与响应生成将提示词发送给LLM如GPT-4或开源模型得到响应。记忆更新分析本次交互判断是否有需要存入长期记忆的信息如新的用户偏好、达成共识的结论将其编码后写入存储层。将响应返回给用户并更新对话上下文短期记忆。4.2 核心代码实现拆解我们聚焦最核心的记忆管理器MemoryManager类。import uuid from datetime import datetime from typing import List, Dict, Any, Optional import chromadb from chromadb.config import Settings from sqlalchemy import create_engine, Column, String, DateTime, JSON, Float from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.orm import sessionmaker from sentence_transformers import SentenceTransformer Base declarative_base() # 定义关系数据库中的记忆元数据表模型 class MemoryMetadata(Base): __tablename__ memory_metadata id Column(String, primary_keyTrue) # 与向量库ID对应 user_id Column(String, indexTrue) session_id Column(String, indexTrue) type Column(String, indexTrue) # user_preference, code_snippet, project_context, learned_fact text_summary Column(String) # 用于检索的摘要文本 raw_text Column(String) # 原始完整文本可选 entities Column(JSON) # 关联实体列表如 [Python, FastAPI, authentication] importance_score Column(Float, default1.0) created_at Column(DateTime, defaultdatetime.utcnow) last_accessed_at Column(DateTime, defaultdatetime.utcnow) embedding_id Column(String) # 在向量库中的集合名或分区标识 class MemoryManager: def __init__(self, pg_connection_str, embed_model_nameBAAI/bge-small-zh-v1.5): # 初始化嵌入模型 self.embed_model SentenceTransformer(embed_model_name) # 初始化PostgreSQL self.engine create_engine(pg_connection_str) Base.metadata.create_all(self.engine) self.Session sessionmaker(bindself.engine) # 初始化ChromaDB持久化模式 self.chroma_client chromadb.PersistentClient(path./chroma_db) # 创建一个按用户分区的集合简化处理实际可按用户ID分集合 self.collection self.chroma_client.get_or_create_collection(nameagent_memories) def create_memory(self, user_id: str, session_id: str, memory_type: str, raw_text: str, **kwargs) - str: 创建并存储一条记忆 # 1. 预处理与增强文本 enhanced_text self._enhance_text_for_embedding(raw_text, memory_type) # 2. 提取实体 entities self._extract_entities(enhanced_text) # 可用简单规则或调用LLM # 3. 生成摘要如果是长文本 summary self._summarize_if_needed(raw_text) # 4. 生成嵌入向量 embedding self.embed_model.encode(enhanced_text).tolist() # 5. 生成唯一ID memory_id str(uuid.uuid4()) # 6. 存入向量数据库 self.collection.add( embeddings[embedding], documents[summary], # 用摘要作为检索文档 metadatas[{memory_id: memory_id, type: memory_type, user_id: user_id}], ids[memory_id] ) # 7. 存入关系数据库元数据 db_session self.Session() memory_meta MemoryMetadata( idmemory_id, user_iduser_id, session_idsession_id, typememory_type, text_summarysummary, raw_textraw_text, # 存储原始文本以备查看 entitiesentities, importance_scorekwargs.get(importance, 1.0), embedding_idagent_memories ) db_session.add(memory_meta) db_session.commit() db_session.close() return memory_id def retrieve_memories(self, user_id: str, query_text: str, memory_types: List[str]None, limit: int5) - List[Dict]: 检索与当前查询相关的记忆 # 1. 将查询文本转换为向量 query_embedding self.embed_model.encode(query_text).tolist() # 2. 构建向量检索的过滤条件 where_filter {user_id: user_id} if memory_types: where_filter[type] {$in: memory_types} # 3. 在向量库中进行相似度搜索 results self.collection.query( query_embeddings[query_embedding], n_resultslimit*2, # 多取一些供后续过滤和重排序 wherewhere_filter ) # 4. 根据向量库返回的ID从关系库获取完整的元数据信息 memory_ids results[ids][0] db_session self.Session() memories_meta db_session.query(MemoryMetadata).filter(MemoryMetadata.id.in_(memory_ids)).all() db_session.close() # 5. 结果组装与简单重排序这里可以加入更复杂的逻辑 retrieved_memories [] for meta in memories_meta: # 更新最后访问时间模拟记忆的激活 db_session self.Session() meta.last_accessed_at datetime.utcnow() db_session.commit() db_session.close() retrieved_memories.append({ id: meta.id, type: meta.type, summary: meta.text_summary, raw_text: meta.raw_text, entities: meta.entities, importance: meta.importance_score, last_accessed: meta.last_accessed_at }) # 6. 按重要性、新鲜度等综合排序简化版重要性*时间衰减 retrieved_memories.sort(keylambda x: x[importance] * self._recency_score(x[last_accessed]), reverseTrue) return retrieved_memories[:limit] # 返回Top K def _enhance_text_for_embedding(self, text: str, memory_type: str) - str: 为嵌入增强文本添加类型前缀 type_prefix_map { user_preference: 用户偏好, code_snippet: 代码示例, project_context: 项目上下文, learned_fact: 已知事实 } prefix type_prefix_map.get(memory_type, ) return f{prefix}{text} def _summarize_if_needed(self, text: str, max_words: int50) - str: 简单摘要生成此处为示例实际应调用LLM words text.split() if len(words) max_words: return text # 简化处理取开头和结尾部分 return .join(words[:max_words//2] [...] words[-max_words//2:]) def _extract_entities(self, text: str) - List[str]: 简单实体提取示例实际可用NER工具 # 这里可以集成spaCy、NLTK或调用LLM进行实体识别 # 为简化返回一个空列表 return [] def _recency_score(self, last_accessed: datetime) - float: 计算新鲜度分数越近分数越高 hours_passed (datetime.utcnow() - last_accessed).total_seconds() / 3600 return 1.0 / (1.0 hours_passed / 24) # 24小时半衰期 # 使用示例 if __name__ __main__: manager MemoryManager(postgresql://user:passlocalhost/agent_memory) # 当用户说“我更喜欢用递归而不是循环来解决树的问题” memory_id manager.create_memory( user_iduser_123, session_idsess_456, memory_typeuser_preference, raw_text用户表示在解决树形结构问题时更倾向于使用递归方法而非迭代循环。, importance1.5 # 偏好类记忆重要性较高 ) print(fMemory created: {memory_id}) # 当用户后续提问“二叉树遍历有什么好方法” relevant_memories manager.retrieve_memories( user_iduser_123, query_text二叉树遍历方法, memory_types[user_preference, learned_fact] ) for mem in relevant_memories: print(f- [{mem[type]}] {mem[summary]})这个MemoryManager实现了记忆的创建、存储和检索的核心闭环。在实际应用中你还需要在智能体的主循环中集成它并在每次LLM调用前后调用相应的检索和更新方法。4.3 提示词模板设计将记忆融入思考记忆检索回来后如何有效地喂给LLM是关键。你不能简单地把一堆记忆文本堆在提示词里。需要一个结构化的提示词模板。def build_prompt_with_memory(system_instruction, conversation_history, user_query, retrieved_memories): 组装包含记忆的提示词 prompt f # 系统指令 {system_instruction} # 相关背景记忆来自过往交互 以下是你之前了解到的关于用户或当前任务的信息请在处理当前请求时参考 for i, mem in enumerate(retrieved_memories): prompt f{i1}. [{mem[type]}] {mem[summary]}\n prompt f # 近期对话历史最近3轮 {format_conversation_history(conversation_history[-6:])} # 假设每轮包括用户和助手的话 # 当前用户请求 用户{user_query} # 你的思考与回应 请基于以上所有信息系统指令、背景记忆、对话历史来理解用户当前请求并给出最合适的回应。 return prompt这个模板清晰地将系统指令、长期记忆、短期记忆对话历史和当前问题分层帮助LLM更好地理解和利用这些信息。5. 高级优化与常见问题排查5.1 记忆的更新、衰减与遗忘机制记忆不是只增不减的。无用的、过时的记忆会污染检索池。我们需要设计记忆的“遗忘”机制。基于重要性的衰减每条记忆有一个初始重要性分数。每次被成功检索并利用例如LLM在回应中引用了该记忆其分数增加随着时间推移分数缓慢衰减。定期清理分数低于某个阈值的记忆。基于冲突的更新当新记忆与旧记忆矛盾时例如用户更新了偏好不是简单新增而是标记旧记忆为过时或降低其权重同时创建新记忆。可以在元数据中增加superseded_by字段指向替代它的新记忆ID。会话边界清理对于明确属于某个临时会话的记忆如typetemporary_context在会话结束后可以自动清理或归档。5.2 检索效果不佳的排查思路如果你发现智能体总是召回不相关的记忆可以按以下步骤排查检查嵌入模型用你的记忆文本和查询文本手动计算几个例子之间的相似度。如果明显不相关的文本相似度很高可能是嵌入模型不适用你的领域考虑更换或微调模型。检查预处理查看存入向量库的“文档”字段通常是摘要。它是否清晰、无噪音是否包含了必要的类型前缀尝试用不同的预处理方式如提取关键词、去除停用词进行对比实验。检查元数据过滤确认你的过滤条件是否准确。是不是因为user_id或type过滤太宽或太严导致该召回的记忆没召回或召回了太多无关记忆检查混合检索策略是否过度依赖语义搜索尝试加入关键词匹配BM25作为混合检索的一部分看看效果。很多向量数据库现在都支持混合检索。引入重排序模型在初步检索出Top N条记忆后使用一个更精细的、专门针对“问答对相关性”训练过的重排序模型如BGE-Reranker对结果进行重新排序可以显著提升Top 1的准确率。5.3 性能与成本考量嵌入成本如果使用OpenAI等付费嵌入API大量记忆的写入和查询会产生成本。对于非实时记忆可以考虑批量异步处理。对于查询可以使用缓存对相同或相似的查询复用之前的检索结果。检索延迟向量检索的延迟随着数据量增长而增加。确保对向量数据库进行索引优化。对于超大规模记忆库可以考虑分层索引或聚类索引先粗筛再精查。数据库连接管理记忆操作频繁需要做好数据库连接池管理避免成为性能瓶颈。6. 从架构到应用记忆驱动的智能体行为模式当记忆系统就绪后你会发现智能体的行为模式发生了质变。它不再是“金鱼脑”而开始展现出一些有趣的、拟人化的特性主动个性化因为记住了用户的偏好它会在建议中优先推荐用户喜欢的方式。比如当用户再次问及部署方式时它会说“考虑到您之前提过熟悉Docker我建议这次也用Docker Compose来编排服务。”连贯的项目协作在协助一个长期项目时它能记住之前讨论过的技术选型、已解决的问题、待办事项。每次对话都像是接着上次的话茬继续用户无需重复背景信息。渐进式学习你可以设计一个反馈循环。当智能体基于某条记忆做出了正确判断就强化该记忆如果判断错误就削弱甚至修正该记忆。这样智能体就能在与用户的互动中不断“成长”。反思与总结在会话结束时可以触发一个“记忆固化”流程让LLM自动总结本次会话的核心结论和需要长期记住的点并调用create_memory方法存储起来。这实现了从短期对话到长期经验的转化。实现futhgar/agent-memory-architecture所描绘的蓝图是一个持续迭代的过程。没有一劳永逸的配置你需要根据智能体的具体任务、用户的反馈和数据表现不断调整记忆的分类、重要性打分算法、检索策略和提示词模板。但一旦这套系统运转起来你的智能体就将从一个大语言模型驱动的“高级鹦鹉”进化成一个真正有“记忆”、有“上下文”、能“持续学习”的智能伙伴。这其中的体验提升和可能性拓展才是这个项目带给我们的最大价值。开始动手吧从为你最简单的智能体添加第一块“记忆碎片”开始。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2596386.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SpringBoot-17-MyBatis动态SQL标签之常用标签

文章目录 1 代码1.1 实体User.java1.2 接口UserMapper.java1.3 映射UserMapper.xml1.3.1 标签if1.3.2 标签if和where1.3.3 标签choose和when和otherwise1.4 UserController.java2 常用动态SQL标签2.1 标签set2.1.1 UserMapper.java2.1.2 UserMapper.xml2.1.3 UserController.ja…

wordpress后台更新后 前端没变化的解决方法

使用siteground主机的wordpress网站,会出现更新了网站内容和修改了php模板文件、js文件、css文件、图片文件后,网站没有变化的情况。 不熟悉siteground主机的新手,遇到这个问题,就很抓狂,明明是哪都没操作错误&#x…

网络编程(Modbus进阶)

思维导图 Modbus RTU(先学一点理论) 概念 Modbus RTU 是工业自动化领域 最广泛应用的串行通信协议,由 Modicon 公司(现施耐德电气)于 1979 年推出。它以 高效率、强健性、易实现的特点成为工业控制系统的通信标准。 包…

UE5 学习系列(二)用户操作界面及介绍

这篇博客是 UE5 学习系列博客的第二篇,在第一篇的基础上展开这篇内容。博客参考的 B 站视频资料和第一篇的链接如下: 【Note】:如果你已经完成安装等操作,可以只执行第一篇博客中 2. 新建一个空白游戏项目 章节操作,重…

IDEA运行Tomcat出现乱码问题解决汇总

最近正值期末周,有很多同学在写期末Java web作业时,运行tomcat出现乱码问题,经过多次解决与研究,我做了如下整理: 原因: IDEA本身编码与tomcat的编码与Windows编码不同导致,Windows 系统控制台…

利用最小二乘法找圆心和半径

#include <iostream> #include <vector> #include <cmath> #include <Eigen/Dense> // 需安装Eigen库用于矩阵运算 // 定义点结构 struct Point { double x, y; Point(double x_, double y_) : x(x_), y(y_) {} }; // 最小二乘法求圆心和半径 …

使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式

一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明&#xff1a;假设每台服务器已…

XML Group端口详解

在XML数据映射过程中&#xff0c;经常需要对数据进行分组聚合操作。例如&#xff0c;当处理包含多个物料明细的XML文件时&#xff0c;可能需要将相同物料号的明细归为一组&#xff0c;或对相同物料号的数量进行求和计算。传统实现方式通常需要编写脚本代码&#xff0c;增加了开…

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器的上位机配置操作说明

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器专为工业环境精心打造&#xff0c;完美适配AGV和无人叉车。同时&#xff0c;集成以太网与语音合成技术&#xff0c;为各类高级系统&#xff08;如MES、调度系统、库位管理、立库等&#xff09;提供高效便捷的语音交互体验。 L…

(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)

题目&#xff1a;3442. 奇偶频次间的最大差值 I 思路 &#xff1a;哈希&#xff0c;时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况&#xff0c;哈希表这里用数组即可实现。 C版本&#xff1a; class Solution { public:int maxDifference(string s) {int a[26]…

【大模型RAG】拍照搜题技术架构速览:三层管道、两级检索、兜底大模型

摘要 拍照搜题系统采用“三层管道&#xff08;多模态 OCR → 语义检索 → 答案渲染&#xff09;、两级检索&#xff08;倒排 BM25 向量 HNSW&#xff09;并以大语言模型兜底”的整体框架&#xff1a; 多模态 OCR 层 将题目图片经过超分、去噪、倾斜校正后&#xff0c;分别用…

【Axure高保真原型】引导弹窗

今天和大家中分享引导弹窗的原型模板&#xff0c;载入页面后&#xff0c;会显示引导弹窗&#xff0c;适用于引导用户使用页面&#xff0c;点击完成后&#xff0c;会显示下一个引导弹窗&#xff0c;直至最后一个引导弹窗完成后进入首页。具体效果可以点击下方视频观看或打开下方…

接口测试中缓存处理策略

在接口测试中&#xff0c;缓存处理策略是一个关键环节&#xff0c;直接影响测试结果的准确性和可靠性。合理的缓存处理策略能够确保测试环境的一致性&#xff0c;避免因缓存数据导致的测试偏差。以下是接口测试中常见的缓存处理策略及其详细说明&#xff1a; 一、缓存处理的核…

龙虎榜——20250610

上证指数放量收阴线&#xff0c;个股多数下跌&#xff0c;盘中受消息影响大幅波动。 深证指数放量收阴线形成顶分型&#xff0c;指数短线有调整的需求&#xff0c;大概需要一两天。 2025年6月10日龙虎榜行业方向分析 1. 金融科技 代表标的&#xff1a;御银股份、雄帝科技 驱动…

观成科技:隐蔽隧道工具Ligolo-ng加密流量分析

1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具&#xff0c;该工具基于TUN接口实现其功能&#xff0c;利用反向TCP/TLS连接建立一条隐蔽的通信信道&#xff0c;支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式&#xff0c;适应复杂网…

铭豹扩展坞 USB转网口 突然无法识别解决方法

当 USB 转网口扩展坞在一台笔记本上无法识别,但在其他电脑上正常工作时,问题通常出在笔记本自身或其与扩展坞的兼容性上。以下是系统化的定位思路和排查步骤,帮助你快速找到故障原因: 背景: 一个M-pard(铭豹)扩展坞的网卡突然无法识别了,扩展出来的三个USB接口正常。…

未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?

编辑&#xff1a;陈萍萍的公主一点人工一点智能 未来机器人的大脑&#xff1a;如何用神经网络模拟器实现更智能的决策&#xff1f;RWM通过双自回归机制有效解决了复合误差、部分可观测性和随机动力学等关键挑战&#xff0c;在不依赖领域特定归纳偏见的条件下实现了卓越的预测准…

Linux应用开发之网络套接字编程(实例篇)

服务端与客户端单连接 服务端代码 #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> #include <pthread.h> …

华为云AI开发平台ModelArts

华为云ModelArts&#xff1a;重塑AI开发流程的“智能引擎”与“创新加速器”&#xff01; 在人工智能浪潮席卷全球的2025年&#xff0c;企业拥抱AI的意愿空前高涨&#xff0c;但技术门槛高、流程复杂、资源投入巨大的现实&#xff0c;却让许多创新构想止步于实验室。数据科学家…

深度学习在微纳光子学中的应用

深度学习在微纳光子学中的主要应用方向 深度学习与微纳光子学的结合主要集中在以下几个方向&#xff1a; 逆向设计 通过神经网络快速预测微纳结构的光学响应&#xff0c;替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…