Memor:为LLM对话构建结构化记忆引擎,实现可重现、可移植的AI交互管理

news2026/5/12 17:27:57
1. 项目概述Memor为LLM对话赋予结构化记忆如果你和我一样长期和各类大语言模型打交道从早期的GPT-3到现在的Claude、Gemini一个绕不开的痛点就是对话历史的管理。默认的聊天界面里历史记录就是一条条堆叠的文本想回溯、想复用、想分析其中的参数和上下文都得靠手动复制粘贴或者依赖特定平台的导出功能既零散又低效。更别提当你需要在不同模型间切换或者想把一次高质量的对话片段作为“知识”喂给另一个任务时那种无处下手的无力感。Memor的出现就是为了解决这个“记忆碎片化”的问题。它不是一个前端聊天工具而是一个Python库一个专门为LLM对话设计的“结构化记忆引擎”。简单来说Memor把一次对话抽象成Session会话把用户输入和模型回复分别封装成Prompt提示和Response回复。这听起来简单但关键在于它记录的不仅仅是文本内容还包括了生成这条回复时的温度temperature、使用的模型、消耗的Token数、推理时间等元数据。这就好比给你的每一次对话都建立了一份带时间戳和详细参数的“实验记录”。这种结构化的好处是显而易见的。首先它让对话历史变得可重现。你可以精确地知道当时是用什么参数、在什么上下文下得到了那个精彩的回答。其次它让对话内容变得可移植、可复用。你可以轻松地从一次长对话中筛选出关于“Python异步编程”的所有问答打包成一个新的Session然后丢给另一个更擅长代码生成的模型去继续深化。Memor官方称之为“模型无关”的设计我深以为然它真正把对话的“内容”和“执行引擎”解耦了。2. 核心设计思路为什么是“结构化”与“可重现”2.1 从“聊天记录”到“对话资产”在没有Memor之前我们是怎么管理对话的无非几种依赖聊天平台的存档功能、自己用文本文件或笔记软件记录、或者写脚本把API返回的JSON存下来。这些方法都有硬伤。平台存档是黑盒数据不透明且难以导出文本记录丢失了所有元数据原始JSON虽然信息全但结构混乱不同模型的API返回格式天差地别想从中提取有效信息并进行二次处理每次都得写一堆解析代码。Memor的设计哲学是把每一次LLM交互的输入和输出都视为有价值的“资产”Artifacts。就像软件开发中的代码、文档、测试用例一样这些对话资产也需要版本管理、结构化存储和便捷的检索能力。Prompt和Response类就是这些资产的标准化容器。它们不仅存储内容还通过统一的接口如.render(),.to_json()来操作这些资产使得后续的处理流程变得一致且自动化。2.2 可重现性的基石元数据与模板“可重现”在AI应用开发中至关重要。一个提示词Prompt这次效果好下次效果差问题出在哪里是温度设高了导致答案发散还是上下文窗口没给够如果只有对话文本你永远在猜。Memor的Response对象强制性地记录了temperature,top_p,model,inference_time等关键参数。当你需要复现某个结果时你可以完整地还原当时的生成环境当然前提是模型本身没有更新。另一个支撑可重现性的设计是PromptTemplate提示模板。很多高级用法比如思维链Chain-of-Thought或系统指令System Instruction都依赖于固定的提示结构。Memor允许你将一个提示词与一个模板绑定。这个模板定义了如何将Prompt的内容、角色、乃至自定义变量渲染成最终发送给LLM API的字符串。这意味着你可以把成功的提示模式保存为模板后续只需替换核心问题就能保证相同的指令框架被复用极大提升了提示工程的工作流效率。2.3 模型无关的会话管理Session类是Memor抽象层的核心。它本质上是一个Prompt和Response对象的有序列表。但它强大的地方在于其“渲染”能力。不同的LLM API如OpenAI、Anthropic、Mistral对输入消息的格式要求略有不同。Memor的Session.render()方法可以接受一个RenderFormat参数将内部统一的结构化会话转换成特定API所需的格式列表。例如你可以用OpenAI的GPT-4开始一个对话中途将整个会话历史通过session.render(RenderFormat.ANTHROPIC)传给Claude上下文不会丢失。这实现了真正的跨模型对话延续。在实际项目中我常用这个特性来做“模型接力”先用一个检索增强模型如结合了RAG的收集和总结资料生成一个包含背景信息的Session再把这个Session渲染后发送给另一个更擅长推理或创作的模型去完成最终任务。3. 核心类深度解析与实操要点3.1 Prompt类不只是文本更是交互的起点Prompt对象远不止一个字符串。创建一个Prompt时除了核心的message你应该有意识地填充其他字段尤其是responses和template。from memor import Prompt, Response, PresetPromptTemplate, Role # 一个完整的Prompt创建示例 prompt Prompt( message请用Python实现一个快速排序函数并说明其时间复杂度。, roleRole.USER, # 明确角色 tokenslen(请用Python实现一个快速排序函数并说明其时间复杂度。) // 4, # 简单估算实际可用tokenizer templatePresetPromptTemplate.BASIC.PROMPT_WITH_LABEL, # 使用预设模板 init_checkTrue # 初始化时检查模板渲染是否正常 ) # 关联多个可能的回复例如从不同模型或不同参数得到 prompt.add_response(Response(messagedef quicksort(arr):..., modelgpt-4, temperature0.7)) prompt.add_response(Response(messageHere is a quicksort implementation:..., modelclaude-3-opus, temperature0.3), index0) # 插入到首位 # 选择一个作为“最佳”回复 prompt.select_response(0)实操心得init_check参数建议在开发阶段设为True它能立即验证当前message和template是否能正确渲染避免在后续流程中埋下错误。responses列表的管理add_response方法可以指定插入位置index。这对于管理同一提示词下的多次采样sampling结果非常有用你可以把质量最高的回复放在前面。模板的威力template不是必须的但对于构建复杂工作流至关重要。例如你可以创建一个要求模型“先分析问题再给出代码”的模板并将其应用于所有编程类提问确保回答结构的一致性。3.2 Response类记录生成的每一刻Response对象是对话的“结果快照”。尽可能详细地记录元数据这些数据在后续分析、优化和成本核算时是无价之宝。from memor import Response, LLMModel import datetime response Response( message快速排序的平均时间复杂度为O(n log n)最坏情况为O(n^2)。, score0.95, # 你可以用自己的评估函数给回复打分 temperature0.8, top_p0.95, modelLLMModel.GPT_4_TURBO, # 使用内置的模型枚举也支持字符串 tokens150, inference_time2.3, # 单位秒 gpuNVIDIA A100, # 记录硬件信息 datedatetime.datetime.now() ) # 事后更新信息 response.update_score(0.98) # 经过人工评估后更新分数 response.update_inference_time(2.5) # 修正时间注意事项tokens字段Memor本身不自动计算Token需要你在调用API后从返回结果中提取并填入。像OpenAI的API响应里就包含usage字段。建议封装一个统一的API调用函数在其中自动创建Response对象并填充这些数据。score字段这是一个非常有扩展性的字段。你可以用它存储基于规则的评分、基于模型的质量评估如使用GPT-4给回复打分甚至是人工反馈的分数。这为构建基于质量的对话筛选和排序提供了可能。模型枚举LLMModel枚举类提供了一些常见模型的常量但直接使用字符串如claude-3-5-sonnet-20241022也是完全支持的保证了灵活性。3.3 PromptTemplate类实现提示工程的标准化PromptTemplate是提升提示复用性的关键。Memor提供了丰富的预设模板PresetPromptTemplate也支持完全自定义。from memor import PromptTemplate, Prompt # 1. 使用预设模板最方便 from memor.preset_templates import PresetPromptTemplate basic_template PresetPromptTemplate.BASIC.PROMPT_RESPONSE_STANDARD # 渲染结果类似: Prompt: {message}\nResponse: {response_message} # 2. 创建自定义模板 custom_template PromptTemplate( title代码评审模板, content你是一位资深{language}开发工程师。请评审以下代码{code_snippet}请重点关注{focus_areas}。你的回复应包含优点、潜在问题和改进建议。, custom_map{language: Python} # 提供模板中部分变量的默认值 ) # 使用自定义模板 prompt Prompt( message, # 注意当模板需要时主message可能为空或作为一部分 templatecustom_template ) # 渲染前需要提供模板中所有变量的值 prompt.template.custom_map.update({code_snippet: def foo(): pass, focus_areas: 可读性和异常处理}) rendered_text prompt.render() print(rendered_text)核心技巧模板变量模板中的{variable}可以从两个地方获取值一是Prompt对象自身的属性如{message}会自动映射到prompt.message二是template.custom_map字典。custom_map的优先级更高。预设模板分类PresetPromptTemplate按用途分类如BASIC,INSTRUCTION1等每个类别下又有不同变体PROMPT,RESPONSE_WITH_LABEL等。INSTRUCTION系列的模板会在渲染内容前加上一段指导性文字非常适合用于构建包含历史上下文的提示。版本控制PromptTemplate对象可以方便地save()到JSON文件这意味着你可以对成功的提示模板进行版本管理跟踪其迭代过程。3.4 Session类对话的指挥中枢Session是你最常打交道的类。它管理着Prompt和Response的序列并提供了丰富的操作和导出功能。from memor import Session, Prompt, Response, RenderFormat import json # 创建会话 session Session(titlePython算法讨论) # 添加交互 session.add_message(Prompt(message什么是快速排序)) session.add_message(Response(message快速排序是一种分治排序算法..., modelgpt-4)) # 搜索功能快速定位内容 indices session.search(分治) print(f找到‘分治’在消息索引: {indices}) # 消息激活/禁用灵活控制上下文 session.disable_message(0) # 禁用第一个消息索引0 # 渲染时被禁用的消息不会包含在内 openai_format_messages session.render(RenderFormat.OPENAI) print(f渲染给OpenAI API的消息数已禁用第一条: {len(openai_format_messages)}) session.enable_message(0) # 重新启用 # 导出与持久化 # 保存到文件 session.save(python_algorithm_session.json) # 导出为Pandas DataFrame进行分析 df session.to_dataframe() print(df[[type, message, model, tokens]].head()) # 从文件加载 new_session Session.load(python_algorithm_session.json)高级用法与避坑指南render()方法这是Session的灵魂。它遍历所有激活状态的消息调用每个消息自己的render()方法最终拼接或组合成目标格式。目前主要支持RenderFormat.OPENAI列表套字典含role和content和RenderFormat.PLAIN_TEXT纯文本拼接。确保在调用前你的Prompt和Response都设置了正确的模板。消息状态管理enable_message/disable_message或mask_message/unmask_message这对方法极其有用。在长对话中LLM的上下文窗口有限。你可以通过禁用一些早期的、不相关的消息来为更重要的上下文腾出空间而无需物理删除它们。这在实现“滑动窗口”式的上下文管理时非常有效。search()方法支持字符串和正则表达式搜索返回的是消息在列表中的索引列表。注意搜索是在渲染后的文本内容上进行的因此受模板影响。性能提示estimate_tokens()是一个估算功能对于精确的Token计数尤其是在使用非OpenAI模型时建议使用模型对应的官方tokenizer库。Memor的估算可以作为一个快速的参考。4. 实战工作流从零构建一个可记忆的AI助手让我们通过一个完整的例子将Memor融入一个真实的AI对话应用。假设我们要构建一个支持历史记录、可跨模型切换的本地命令行聊天工具。4.1 环境搭建与初始化首先安装Memor和必要的LLM SDK。这里以OpenAI和Mistral为例。pip install memor openai mistralai然后我们创建一个会话管理器并设计一个简单的循环。# chatbot_with_memory.py import os from memor import Session, Prompt, Response, RenderFormat from openai import OpenAI from mistralai import Mistral class MemoryChatbot: def __init__(self): # 初始化会话可以加载已有文件 self.session_file chat_history.json if os.path.exists(self.session_file): self.session Session.load(self.session_file) print(f已加载历史会话: {self.session.title}) else: self.session Session(title跨模型对话记录) print(新建会话。) # 初始化客户端请将API密钥放入环境变量 self.openai_client OpenAI(api_keyos.getenv(OPENAI_API_KEY)) self.mistral_client Mistral(api_keyos.getenv(MISTRAL_API_KEY)) self.current_model gpt-4 # 默认模型 def switch_model(self, model_name: str): 切换当前使用的模型 supported_models [gpt-4, gpt-3.5-turbo, mistral-large-latest] if model_name in supported_models: self.current_model model_name print(f已切换模型至: {model_name}) else: print(f不支持的模型。当前支持: {supported_models}) def chat_loop(self): print(\n 记忆增强型聊天机器人 ) print(输入消息开始聊天。) print(特殊命令: /switch [模型名] - 切换模型, /save - 保存, /quit - 退出) print(f当前模型: {self.current_model}\n) while True: try: user_input input( 你: ).strip() if not user_input: continue # 处理命令 if user_input.startswith(/): self._handle_command(user_input) continue # 1. 创建Prompt对象并加入会话 user_prompt Prompt(messageuser_input) self.session.add_message(user_prompt) # 2. 根据当前模型选择客户端并渲染会话历史 if mistral in self.current_model: client self.mistral_client model_for_api self.current_model # Mistral AI API的messages格式与OpenAI兼容 messages self.session.render(RenderFormat.OPENAI) else: client self.openai_client model_for_api self.current_model messages self.session.render(RenderFormat.OPENAI) # 3. 调用API print(f [{self.current_model} 正在思考...]) if mistral in self.current_model: response client.chat.complete(modelmodel_for_api, messagesmessages) content response.choices[0].message.content else: response client.chat.completions.create(modelmodel_for_api, messagesmessages) content response.choices[0].message.content print(f {self.current_model}: {content}) # 4. 创建Response对象尽可能记录元数据 # 注意需要从API响应中提取token等信息这里为简化使用估算 model_response Response( messagecontent, modelself.current_model, # 以下信息应从API响应中实际获取此处为示例 tokenslen(content) // 4, # 粗略估算 inference_timeresponse.usage.total_tokens / 50.0 if hasattr(response, usage) else 0.5, # 示例计算 ) self.session.add_message(model_response) except KeyboardInterrupt: print(\n中断接收。) self._save_session() break except Exception as e: print(f出错: {e}) def _handle_command(self, command: str): parts command.split() cmd parts[0].lower() if cmd /switch and len(parts) 1: self.switch_model(parts[1]) elif cmd /save: self._save_session() elif cmd /quit: self._save_session() print(再见) exit(0) else: print(未知命令。) def _save_session(self): self.session.save(self.session_file) print(f会话已保存至: {self.session_file}) if __name__ __main__: bot MemoryChatbot() bot.chat_loop()4.2 实现高级功能上下文修剪与精华提取随着对话进行会话会越来越长。我们可以添加功能自动将不重要的早期消息禁用mask或者将整个会话总结成一个新的Prompt。# 在MemoryChatbot类中添加方法 def summarize_and_compress(self, keep_last_n: int 10): 总结会话并压缩历史。 策略保留最后keep_last_n轮对话将之前的对话总结为一个Prompt。 total_messages len(self.session.messages) if total_messages keep_last_n * 2: # 每轮包含一问一答 print(对话轮次较少无需压缩。) return # 1. 获取需要被总结的旧消息 cutoff_index total_messages - (keep_last_n * 2) old_messages self.session.messages[:cutoff_index] new_messages self.session.messages[cutoff_index:] # 2. 将旧消息渲染成文本用于生成总结 old_session Session(messagesold_messages) old_conversation_text old_session.render(RenderFormat.PLAIN_TEXT) # 3. 调用LLM生成总结 summary_prompt f请将以下对话历史总结成一个简洁的段落保留核心事实、结论和决策。总结将用于后续对话的上下文。 对话历史 {old_conversation_text} 总结 # 这里简化为调用一次API实际应用可加入错误处理 summary_response self.openai_client.chat.completions.create( modelgpt-3.5-turbo, messages[{role: user, content: summary_prompt}] ) summary summary_response.choices[0].message.content # 4. 创建一个代表“历史总结”的Prompt替换掉旧消息 summary_prompt_obj Prompt( messagef[之前对话的总结]: {summary}, roleRole.SYSTEM # 可以作为系统指令或用户指令根据场景定 ) # 5. 重建会话总结Prompt 保留的新消息 compressed_messages [summary_prompt_obj] new_messages self.session.update_messages(compressed_messages) print(f已压缩会话。将{len(old_messages)}条旧消息总结为1条当前共{len(self.session.messages)}条消息。)4.3 会话的分析与导出Memor的to_dataframe()方法让对话分析变得异常简单。你可以用Pandas进行各种数据分析。import pandas as pd def analyze_session(self): 分析当前会话的统计数据 df self.session.to_dataframe() if df.empty: print(会话为空。) return print(\n 会话分析报告 ) print(f总消息数: {len(df)}) print(f用户提问数: {len(df[df[type] Prompt])}) print(f模型回复数: {len(df[df[type] Response])}) if model in df.columns: model_counts df[model].value_counts() print(\n模型使用分布:) for model, count in model_counts.items(): print(f {model}: {count}次) if tokens in df.columns and df[tokens].notna().any(): total_tokens df[tokens].sum() avg_tokens_per_response df[df[type] Response][tokens].mean() print(f\n总Token消耗估算: {total_tokens:.0f}) print(f平均每次回复Token数: {avg_tokens_per_response:.1f}) # 找出最长的回复 if message in df.columns: df[msg_length] df[message].str.len() longest_resp df[df[type] Response].nlargest(1, msg_length) if not longest_resp.empty: print(f\n最长的回复{longest_resp[msg_length].iloc[0]}字符: ) print(f {longest_resp[message].iloc[0][:200]}...) # 截断显示5. 常见问题、排查技巧与进阶思考5.1 安装与导入问题问题pip install memor失败提示找不到版本或依赖错误。排查确认Python版本3.8。Memor依赖于较新的Python特性。尝试安装开发版pip install githttps://github.com/openscilab/memor.gitdev。检查网络环境确保能正常访问PyPI。解决最稳定的方式是按照项目README下载特定版本如1.1的源码进行安装pip install https://github.com/openscilab/memor/archive/v1.1.zip。5.2 会话渲染与API调用不匹配问题session.render(RenderFormat.OPENAI)返回的消息列表直接发给某个LLM API时报错。排查检查消息角色确保Prompt和Response的role属性设置正确。通常用户输入是Role.USERAI回复是Role.ASSISTANT系统指令是Role.SYSTEM。错误的角色会导致API拒绝。检查模板如果你为Prompt设置了自定义模板render()的输出可能不是纯消息内容而是包含了标签如“Prompt: ”。某些API要求content字段是纯净的文本。此时应使用PresetPromptTemplate.BASIC.PROMPT这类只输出消息本身的模板或者在调用API前对渲染结果进行后处理。验证格式打印出render()的结果肉眼检查是否符合目标API的要求。OpenAI格式应为[{role: ..., content: ...}, ...]。解决为不同的API目标创建不同的Session渲染方法封装。例如def render_for_openai(session): # 临时将所有消息的模板设为最简格式 for msg in session.messages: if hasattr(msg, template): msg.update_template(PresetPromptTemplate.BASIC.PROMPT) # 假设是Prompt对象 return session.render(RenderFormat.OPENAI)5.3 性能与大规模会话处理问题当会话包含成千上万条消息时search()、render()或to_dataframe()操作变慢。优化建议分页加载Memor本身不直接支持分页但你可以通过Session的messages列表进行切片操作来实现。例如只加载最近1000条消息到活跃会话中更早的历史存档到另一个文件。异步操作如果search操作非常耗时例如在极长的纯文本中搜索考虑将session.messages导出为列表后使用Python的concurrent.futures进行并行搜索。使用数据库后端对于生产环境Memor的纯JSON文件存储可能成为瓶颈。一个进阶方案是继承Session类重写其load/save/search等方法将数据持久化到SQLite或PostgreSQL数据库中利用索引提升查询性能。Memor的类结构清晰非常适合做这样的扩展。5.4 自定义扩展与集成Memor的设计是模块化的鼓励扩展。以下是一些思路集成向量数据库为每个Prompt或Response对象计算文本嵌入embedding并存储起来。然后可以重写Session.search()方法使其不仅支持关键词匹配还支持语义搜索。自动化评估流水线利用Response对象的score字段构建一个自动化评估流程。每次生成回复后自动调用另一个评估模型或规则进行打分并将分数记录到Response中。后续可以根据分数筛选高质量对话片段。构建对话数据集利用Memor的结构化特性可以轻松地将多次对话的Session对象整理成标准格式如JSONL用于微调模型或进行学术研究。在我自己的使用中Memor逐渐从一个简单的历史记录工具演变成了AI应用开发的基础设施。它强迫我以结构化的方式思考与LLM的每一次交互而这种结构化的思维反过来又极大地提升了工作流的可靠性和可维护性。最开始你可能觉得为每次API调用多写几行代码创建Prompt和Response对象有些麻烦但当你需要回溯一周前的某次对话、需要批量提取所有关于某个主题的问答、或者需要在不同模型间无损迁移一个复杂对话时你会庆幸当初做了这个“麻烦”的决定。它带来的长期收益远大于初期的那点额外编码成本。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2606734.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;替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…