开源AI知识库Tome:基于大语言模型与向量数据库的智能笔记系统

news2026/5/1 5:30:39
1. 项目概述当AI遇上知识管理一个开源智能笔记本的诞生如果你和我一样每天被海量的信息淹没——浏览器标签页开了一堆微信收藏夹塞满了文章笔记软件里躺着无数个“稍后阅读”的链接最后却什么也没记住——那你一定在寻找一个终极解决方案。今天要聊的这个项目runebookai/tome就是为解决这个痛点而生的。它不是一个简单的笔记应用而是一个开源的、由AI驱动的个人知识库系统。你可以把它理解为一个永远在线的、能理解你所有笔记内容的智能助手它不仅能帮你存储信息更能帮你连接、梳理和创造知识。tome这个名字本身就很有意思它既有“卷册”的意思也暗含了“归家”的寓意象征着将散落的知识碎片汇聚成一个有意义的整体。这个项目的核心是让AI成为你知识管理流程中的“第二大脑”。想象一下你随手记下的一段会议纪要、一篇技术博客的摘要、一个突然迸发的灵感tome都能自动理解其内容为你打上标签并在未来某个你需要的时候通过语义搜索精准地找出来甚至能基于你已有的知识帮你生成新的内容大纲或文章草稿。这背后依赖的是现代AI技术特别是大语言模型LLM和向量数据库的成熟应用。对于开发者、研究者、内容创作者以及任何需要深度处理信息的个人来说tome提供了一个极具吸引力的、可完全掌控的私有化方案。2. 核心架构与技术选型解析2.1 为什么是“AI-First”的知识库传统的笔记工具无论是Evernote、Notion还是Obsidian其核心是“记录”和“组织”。你需要手动建立文件夹、添加标签、创建双向链接来构建知识网络。这个过程是后置的、手动的并且严重依赖使用者的纪律性。tome的思路是“AI-First”它将AI的能力前置到了信息录入的瞬间。当你向tome添加一条笔记时系统后台会立即调用集成的AI模型如OpenAI的GPT系列、或开源的Llama等对内容进行分析。这个过程不仅仅是提取关键词而是进行深度的语义理解识别主题、实体、情感倾向并生成这段文本的“向量嵌入”。这个向量是一个高维度的数学表示可以理解为这段文本在“语义空间”中的唯一坐标。相似含义的文本其坐标在空间中也会很接近。这样一来未来的搜索就不再是基于关键词的字面匹配而是基于语义相似度的向量匹配。这意味着你搜索“如何优化数据库查询”它不仅能找到标题里含有这些字的笔记还能找到你之前记录的关于“SQL索引使用心得”或“慢查询日志分析案例”的内容因为它们语义上是相关的。注意选择“AI-First”架构意味着项目对模型API的依赖和成本变得关键。tome作为开源项目通常设计为支持多种模型后端让你可以根据需求精度、速度、成本、隐私灵活切换这是其相较于闭源SaaS产品的一大优势。2.2 技术栈深度拆解从前端到向量数据库一个完整的tome系统其技术栈可以清晰地分为四层前端交互层通常采用现代Web框架如React、Vue.js或Svelte构建一个响应式、体验良好的单页面应用。考虑到笔记编辑的富文本需求可能会集成诸如TipTap、ProseMirror或Slate这样的编辑器框架。这一层的目标是提供流畅的写作和阅读体验以及直观的知识图谱可视化界面。后端服务层这是业务逻辑的核心。采用Node.jsExpress/NestJS、PythonFastAPI/Django或Go等语言构建RESTful或GraphQL API。它负责处理用户认证、笔记的增删改查、以及最重要的——与AI模型的交互调度。当收到一篇新笔记时后端服务会将其发送给指定的AI模型接口请求生成摘要、标签和向量嵌入。AI模型层这是项目的“智能引擎”。它包含两个主要功能嵌入模型负责将文本转换为向量。可以选择OpenAI的text-embedding-ada-002或开源模型如BGE、Sentence-Transformers。选择时需权衡嵌入维度影响向量数据库性能和精度、多语言支持以及本地部署能力。大语言模型负责内容理解、摘要、问答和生成。可以选择GPT-4/3.5-Turbo效果最佳但需API调用或本地部署的Llama 3、Qwen等开源模型隐私性好但对硬件有要求。tome的后台需要精心设计提示词工程以引导LLM产出稳定、符合格式要求的结果如JSON格式的标签数组。数据存储层这是与传统笔记软件区别最大的地方采用混合存储策略。关系型数据库使用PostgreSQL或SQLite存储笔记的元数据ID、标题、创建时间、作者等和原始文本内容。这部分用于处理精确查询和事务。向量数据库这是实现语义搜索的关键。专门用于存储和检索高维向量。主流选择有Pinecone全托管服务易用但可能产生持续费用。Weaviate开源可自托管同时具备向量和对象存储能力与GraphQL集成良好。Qdrant/Milvus专注于高性能向量检索的开源项目。tome项目更可能选择Weaviate或Qdrant因为它们开源免费适合集成到自托管方案中。当用户进行搜索时查询词也会被转换成向量然后向量数据库快速找出最相似的若干个笔记向量返回对应的笔记ID给后端。2.3 开源方案的优势与自托管考量选择runebookai/tome这类开源项目最大的吸引力在于“控制权”。你可以将其部署在自己的服务器或家庭NAS上所有数据——你的笔记、生成的向量——都完全私密不经过任何第三方服务器。这对于处理商业机密、个人隐私或敏感研究材料的用户至关重要。自托管也带来了技术挑战和成本。你需要准备服务器资源CPU、内存特别是运行本地LLM需要强大的GPU、维护服务的正常运行更新、备份、监控并承担相应的电力和网络成本。不过社区生态通常会提供Docker镜像和详细的部署文档大大降低了运维门槛。对于普通用户也可以选择在VPS或一些支持容器的PaaS平台上进行部署平衡便利性与控制力。3. 核心功能实现与实操部署3.1 从零开始本地开发环境搭建假设我们选择一种经典的技术栈组合前端用React Vite后端用Python FastAPI向量数据库用QdrantLLM先用OpenAI API后期可替换为本地Ollama服务。以下是搭建步骤的核心思路。首先克隆项目仓库并了解其结构。一个组织良好的tome项目通常会包含frontend、backend、docker-compose.yml等目录或文件。git clone https://github.com/runebookai/tome.git cd tome后端环境准备进入backend目录创建Python虚拟环境并安装依赖。核心依赖通常包括fastapi,uvicornASGI服务器,openai,qdrant-client,sentence-transformers,sqlalchemy等。你需要一个.env文件来配置敏感信息例如OPENAI_API_KEYsk-your-key-here DATABASE_URLpostgresql://user:passwordlocalhost/tome_db QDRANT_URLhttp://localhost:6333 EMBEDDING_MODELtext-embedding-ada-002 LLM_MODELgpt-3.5-turbo前端环境准备进入frontend目录使用npm或yarn安装依赖。前端需要配置后端API的基地址通常在.env.development文件中设置VITE_API_BASE_URLhttp://localhost:8000/api。基础设施启动使用Docker Compose一键启动依赖服务是最方便的方式。项目提供的docker-compose.yml可能如下所示version: 3.8 services: postgres: image: postgres:15 environment: POSTGRES_DB: tome_db POSTGRES_USER: user POSTGRES_PASSWORD: password volumes: - postgres_data:/var/lib/postgresql/data ports: - 5432:5432 qdrant: image: qdrant/qdrant ports: - 6333:6333 - 6334:6334 volumes: - qdrant_data:/qdrant/storage volumes: postgres_data: qdrant_data:运行docker-compose up -d后PostgreSQL和Qdrant服务就会在后台启动。接下来分别启动后端和前端开发服务器一个基本的tome系统就运行起来了。3.2 核心工作流剖析一条笔记的“AI化”之旅理解数据流是掌握tome的关键。当你保存一篇新笔记时系统内部发生了什么内容接收与预处理前端将笔记标题和内容通过HTTP POST请求发送到后端API例如/api/notes。后端接收到Markdown或HTML格式的原始文本。AI处理流水线后端服务启动一个异步任务来处理这条笔记以避免阻塞请求。步骤A - 生成嵌入调用嵌入模型API将笔记的正文文本有时会拼接标题以增强语义转换为一个1536维如果使用text-embedding-ada-002的浮点数向量。这个向量代表了这段文本的“语义指纹”。步骤B - 生成元数据同时将笔记内容发送给LLM通过精心设计的提示词Prompt请求其生成结构化数据。提示词可能类似“请分析以下文本提取3-5个核心关键词作为标签并生成一段80字以内的摘要。以JSON格式返回{\tags\: [\tag1\, \tag2\], \summary\: \...\}”。LLM返回解析后的JSON数据。步骤C - 存储将笔记的原始内容、标题、作者、时间戳等存入PostgreSQL。将步骤A生成的向量、以及笔记的唯一ID一起存储到Qdrant集合Collection中。标签和摘要也可以作为元数据存储在Qdrant或PostgreSQL中。语义搜索的实现当用户在搜索框输入“机器学习入门资源”时前端将查询词发送到后端搜索端点如/api/search?q机器学习入门资源。后端同样使用相同的嵌入模型将查询词转换为查询向量。后端向Qdrant发起搜索请求“在‘notes’集合中查找与这个查询向量最相似的10个向量”。Qdrant使用近似最近邻算法如HNSW快速返回相似度最高的向量ID列表及其分数。后端根据这些ID从PostgreSQL中取出完整的笔记信息并按相似度排序后返回给前端展示。实操心得在调试AI处理流水线时务必做好日志记录和错误处理。LLM的API调用可能失败或返回非标准格式嵌入模型也可能有速率限制。建议将AI处理设计为幂等操作即对同一笔记内容多次处理结果一致这样可以在失败后安全重试。对于成本敏感的OpenAI API调用可以对内容长度进行限制或提供摘要后再处理。3.3 高级功能智能问答与知识图谱生成基础的CRUD和语义搜索只是开始。tome的威力体现在更高级的功能上。基于上下文的智能问答这不仅仅是搜索而是让AI“阅读”你相关的笔记后回答问题。实现流程是用户提问 - 系统将问题转换为向量 - 在向量数据库中搜索最相关的若干条笔记作为“上下文” - 将“上下文”和“问题”一起组合成一个新的提示词发送给LLM - LLM基于你的私人知识库生成答案。例如你问“我去年关于项目复盘总结了哪些教训”系统会找到相关的复盘笔记然后让LLM提炼出答案。自动知识图谱构建这是双向链接的升级版。系统可以定期运行后台任务分析所有笔记利用LLM识别笔记中提及的人物、地点、概念、项目等实体并自动发现实体之间的关系从而生成一个可视化的知识图谱。例如笔记A提到了“Python的asyncio”笔记B提到了“异步编程模型”系统可以自动将两者关联并在图谱中显示连接。这需要更复杂的实体识别和关系抽取模型或者利用LLM的强大推理能力。4. 性能优化与生产环境部署要点4.1 向量搜索的精度与效率平衡向量数据库的性能和精度取决于几个关键参数向量维度由嵌入模型决定。维度越高表征能力越强但存储和计算成本也越高。text-embedding-ada-002的1536维是一个很好的平衡点。距离度量常用余弦相似度或欧氏距离。对于文本嵌入余弦相似度更常用因为它关注向量的方向而非大小。索引算法Qdrant、Weaviate默认使用HNSW分层可导航小世界算法。它通过构建一个图结构来加速搜索其关键参数ef_construction和M影响索引构建的速度和精度。通常更高的值带来更高的精度和更慢的构建速度。对于千万级以下的笔记库默认参数通常足够。过滤搜索这是生产级应用必备功能。你可能想搜索“所有关于‘机器学习’且标签包含‘实践’的笔记”。这需要在执行向量相似度搜索的同时结合元数据存储在SQL或向量数据库自身进行过滤。Qdrant和Weaviate都支持高效的带过滤向量搜索。4.2 大语言模型成本与本地化部署策略长期使用LLM API调用成本不容忽视。优化策略包括缓存对相同的查询或内容处理结果进行缓存。例如同一篇笔记的摘要和嵌入只需计算一次。内容截断与摘要在发送给LLM生成元数据前先对过长的笔记进行自动摘要减少token消耗。模型降级非关键任务如生成标签使用更便宜的模型如gpt-3.5-turbo关键任务如智能问答再用更强大的模型。转向本地模型这是开源项目的终极优势。使用Ollama或LM Studio在本地运行Llama 3、Qwen或Mistral等开源模型。虽然响应速度可能慢于API且需要强大的GPU或利用CPU量化模型但实现了零API成本、完全离线、数据绝对隐私。tome的后台可以设计成可插拔的模型适配层方便用户切换。4.3 生产环境部署清单将tome用于日常生产你需要考虑以下方面部署方式使用Docker Compose或Kubernetes编排所有服务前端、后端、PostgreSQL、Qdrant、可能的本地LLM服务。反向代理与SSL使用Nginx或Caddy作为反向代理处理静态前端文件并将API请求转发给后端同时配置HTTPS证书如Let‘s Encrypt保障通信安全。数据备份制定定期备份策略。PostgreSQL数据可以使用pg_dumpQdrant的向量数据备份需要参考其官方方案通常涉及快照。备份应异地存储。监控与日志集成Prometheus和Grafana监控服务健康状态、API响应时间和资源使用情况。使用集中式日志系统如LokiGraylog收集和分析日志便于故障排查。用户认证与安全实现安全的用户认证如JWT并对API实施速率限制防止滥用。确保环境变量中的密钥管理安全。5. 常见问题排查与实战技巧在实际部署和使用tome的过程中你肯定会遇到各种问题。下面是一些典型场景及解决思路。5.1 搜索效果不理想怎么办语义搜索“搜不准”是最常见的问题。可以从以下几个维度排查嵌入模型不匹配如果你处理的主要是中文笔记却使用了针对英文优化的嵌入模型如早期的text-embedding-ada-002效果会大打折扣。应切换为多语言或中文优化模型如text-embedding-3系列、BGE的中文模型等。文本预处理问题在生成嵌入前是否对文本进行了适当的清洗过多的HTML标签、代码块、无关的链接可能会干扰模型的语义理解。可以尝试提取纯文本或保留关键的结构信息如标题。搜索参数问题检查向量数据库的搜索参数如返回的相似度阈值是否设置得太高或太低。可以尝试在搜索时同时返回相似度分数并在前端或日志中显示出来辅助判断。数据量问题向量搜索在数据量较少时可能无法形成有效的语义簇。坚持使用随着笔记数量增加效果通常会改善。5.2 AI处理速度慢或失败率高网络与超时如果使用云端AI API网络不稳定是首要怀疑对象。在后端代码中为AI调用设置合理的超时时间和重试机制如指数退避。速率限制免费或低阶的API账号有严格的速率限制RPM/TPM。需要在代码中实现请求队列或限流逻辑避免突发请求导致全部失败。上下文过长LLM有上下文窗口限制。如果笔记内容过长直接发送会导致失败或截断。务必实现内容截断或“分块-摘要”策略。先将长笔记分成有重叠的块分别总结再对总结进行总结。提示词工程LLM返回格式错误或不稳定往往是提示词不够精确。使用更严格的指令并要求以JSON等结构化格式返回。可以在提示词中提供输出示例Few-Shot Learning大幅提升稳定性。5.3 本地模型部署的“坑”硬件资源不足运行7B参数的模型至少需要8GB以上显存GPU或16GB以上内存CPU。务必先量化模型如GGUF格式的4位或5位量化以大幅降低资源需求。推理速度慢CPU推理速度可能无法满足实时交互。对于摘要、标签生成等后台任务可以接受但对于智能问答延迟可能很高。考虑使用GPU或只对高频、核心内容启用本地模型其他仍用API。模型效果差异开源模型与GPT-4的效果存在差距尤其在复杂推理和指令遵循上。需要调整提示词并管理好用户预期。选择社区评价高、在特定任务上微调过的模型如专门用于摘要的模型。5.4 数据迁移与同步难题从其他笔记软件导入这是刚需。需要为每个主流笔记软件如Obsidian、Notion、Evernote编写或寻找数据导出工具将导出的Markdown或HTML文件批量导入tome。批量导入时务必注意处理导入失败的情况并设计进度提示。多设备同步自托管版本的多设备同步需要自己解决。核心是后端API服务对多客户端Web、移动端的支持。前端需要实现离线编辑和冲突解决策略如操作转换OT。这是一个复杂的特性初期可以简化为“最后写入获胜”并提示用户。我个人在搭建和使用的过程中最大的体会是tome这类工具的价值随着你投入内容的增多而指数级增长。前期的部署和调优需要一些耐心但当你养成了随时将碎片信息扔进去的习惯并在几个月后通过一个模糊的回忆精准地找回那份参考资料时你会觉得所有的投入都是值得的。它不仅仅是一个工具更是在帮助你构建一个不断成长、真正属于你自己的外部智慧。

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