news 2026/9/4 14:41:03

本地大语言模型如何实现书目记录的超作品归并

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
本地大语言模型如何实现书目记录的超作品归并

把“书目记录按超作品(superwork)归并”这件事,和“本地大语言模型(Local LLMs)”放在一起,乍看是非常图情专业的题目,但它解决的问题一点都不冷门:同一部作品在图书馆目录里往往散成几十条记录,不同译本、不同出版社、电子版、丛书单册,前后字段只有细微差别。读者检索时看到一堆重复结果,却说不清哪条是母本、哪条是后代。传统规则能处理 ISBN 相同的硬重复,处理不了语义层面的同源关系。本地大语言模型解决的不是单纯“查重”,而是“判断两个描述不同的书目是否指向同一个作品或相关作品集合”。这篇实践记录适合正在做图书馆发现系统、机构知识库、数字人文整理或自建书库检索的人,下面从问题分层、技术路线、数据清洗、本地模型运行、聚类方法到批量落地逐层拆开讲。

1. 先看你聚的是什么层级,再谈怎么用大模型

1.1 书目记录、单册、作品和“超作品”差在哪

书目系统的常见字段包括题名、责任者、ISBN、出版社、出版年、版次、语言、载体形态和丛书名。很多开发者一开始把“聚合同一本书”理解成“合并 ISBN 相同的记录”,这是只处理了载体版本这一层。

图书情报领域的 FRBR 模型把对象拆成四个层级:作品、内容表达、载体表现、单件。举例来说,《百年孤独》是一部作品;中文译本和西班牙语原著是不同的内容表达;某个出版社 2011 年印刷的第 1 版是载体表现;图书馆里那一册实体书是单件。

“超作品”概念比 FRBR 的作品层更宽。它既可以收入同一作品的各种译本、版本,也可以把续集、前传、改编、甚至同一故事的不同演绎当作相关节点放入同一个簇。做发现系统时,超作品簇通常给用户呈现一个“作品页”,下面再挂各版本和各相关作品。这个层级决定了你要合并的字段范围。如果只是按 ISBN 合,老书、无 ISBN 书、译名差异大的书全部漏掉。

建议一开始就明确:你们的产品到底要合并到“版本一致”还是“作品级一致”?这决定了后续数据清洗和模型判断的严格程度。

1.2 规则能做多少,LLM 补哪一段

规则方法在干净数据上效率很高。ISBN 相同、记录 ID 能映射、出版社加题名完全一致,这类简单规则应该放在最前面,绝不交给大模型。

问题通常出现在关系型数据覆盖不到的地方:同一本书不同年份改名、繁体中文和简体中文、多语种译名、西文文献中的 title 大小写和冠词差异、中文老唱片里的改编题名、展览目录中同一作品的不同著录方式。这些情况下,连人工初审都要反复确认,单纯字符串相似度自然不稳定。

Local LLMs 在这里补的是语义理解能力。它能从两条记录的文字中判断出责任者是不是同一个人、题名是不是翻译关系、出版信息差异是版本迭代还是确实不同的书。还有一个现实理由:馆藏数据和机构内部书目往往不适合送到外部服务,本地推理在隐私边界、请求频率、长期费用上都更可控。但本地模型不是万能匹配器,它依然可能因为输入字段太少、语种不支持、指令理解偏差而给出错误判断,所以后续要搭聚簇、验证和回滚机制。

2. 三条技术路线,别一上来就全量两两判断

2.1 方案 A:用本地嵌入模型做候选召回

嵌入模型把一条书目文本编码成固定维度的向量,然后计算余弦相似度。这个路线适合先对几十万条记录做粗筛,筛选出可能相关的候选记录对。

具体做法是把题名、责任者、语种、年份、丛书名合成一段文本,例如“题名:百年孤独;责任者:加西亚·马尔克斯;语言:中文;出版年:2011”。然后交给本地嵌入模型编码。相似度较高的记录进入后续判定池。

这个方案快,但有一个明显问题:嵌入向量的相似度不等于超作品归属。两个不同作者、题名恰好接近的书也可能相似度高。因此它更适合做召回层,不适合直接输出最终簇。同时,嵌入模型对中文、小语种、译名混排的支持差别很大,落地前要拿真实语料测试,不能只看模型在通用榜单上的分数。

2.2 方案 B:用本地大模型做两两判定

当候选记录对已经缩小到一个可控范围时,可以用本地对话式大模型判断“这两条是否属于同一个超作品”。输入一般是一段结构化、带规则说明的提示词,输出要求是确定的 JSON 结构,包括是否同簇、置信度和核心理由。

这个路线的优势是解释性强。模型能说出“中文题名与英文题名指向同一原文,责任者拼写一致,译者和出版者不同只是版本差异”这类判断路径。这个理由既可以进入人工审核列表,也可以写入日志,方便后期追溯。

代价是速度。直接对所有记录两两比对是不可行的。一万条记录就是接近五千万个候选对,即便本地模型一次推理只要一秒,也会跑到让人失去耐心。所以方案 B 必须搭配候选召回或者分块策略,只对少量高疑似记录执行。

2.3 方案 C:让大模型输出规范化的“作品键”,再做归并

比两两判断更省算力的做法是,让模型为每条记录生成一个规范化作品键。这个键可以包含原始作品的标准题名、责任者的规范名、作品语言、初版年份等信息。

比如中文版《百年孤独》和英文版 One Hundred Years of Solitude,经过模型处理后,都可能落到同一个作品键:“百年孤独 / One Hundred Years of Solitude / 加西亚·马尔克斯”。之后再用字符串精确匹配或简单相似度对这个作品键做归并。

这个路线把聚类决策从“无数对记录的关系判断”简化成“每个记录生成一个稳定的归一化标签”,速度更快,也更容易人工复核。难点在于模型输出的键不稳定:同一模型不同温度下可能给出不同写法,两个翻译版本对标准题名的提取也可能不一致。所以方案 C 通常只用于生成候选,随后仍需小范围的聚类验证。

三条路线并不互斥。我建议的组合是:规则先去掉硬重复,嵌入模型做候选召回,本地大模型对高疑似记录做两两判定,再用一次轻量聚簇输出最终簇。

技术路线适合规模主要成本可解释性建议角色
嵌入向量 + 相似度召回几十万条记录以上中等较低候选召回
本地大模型两两判定数千到数万候选对最终判定
模型生成规范化作品键十万条记录左右中低快速归并 + 预分组

3. 数据清洗和极小标注集,决定了聚类质量的上限

3.1 先做一个“我知道标准答案”的测试集

很多人上手就开始跑大模型,跑了几天发现结果完全没法解释。更稳妥的做法是,先抽出 100 到 200 条真实书目,手工整理成几组“已知正确簇”。

测试集不需要太大,但要包含典型情况:完全相同的版本、同一作品的不同译本、同一作品的再版与改名、真正的不同作品但题名和作者接近、缺少责任者或 ISBN 的记录。有了这个测试集之后,每次换提示词、换模型、调阈值,都能跑一遍,用一组数字判断变化方向。

这个环节不好省。因为本地模型的输出没有稳定保证,提示词里换一个标点都可能影响结果。没有测试集的时候,人只能凭感觉判断“好像变好了”,有了测试集才能确认“准确率确实提高了”。

3.2 字段归一化:题名、责任者、语种、ISBN、年份

给模型的数据应该先做基础归一化。常见操作包括:全角转半角、去掉多余空格、统一大小写、去掉题名结尾的句点和副题名分隔符、中文繁简体根据库内主语言做统一、ISBN 去掉连字符并统一到 13 位。

责任者字段更麻烦。同一个人在不同记录里可能写成“加西亚·马尔克斯”和“马尔克斯,加西亚”,也可能写成西文原名。如果没有作者规范库,至少要把姓名里的逗号、空格、头衔这类噪声清除,让模型看到的是比较干净的“姓名主体”。

出版年建议拆分成年份和版本说明。很多记录在版本说明里写“第 3 版”“修订版”“影印本”,这些内容对判断是不是同一作品有参考价值,但直接混在题名里会干扰语义。

注意:清洗的目的是让输入稳定,不是把原始信息抹掉。清洗后的文本和原始字段都要保留,方便排查。

3.3 没有 ISBN、题名变体、缺责任者时怎么办

没有 ISBN 是老数据里最常见的情况。这时候不要把 ISBN 作为必填条件,否则候选召回从源头就把正确记录过滤掉了。

缺责任者时,可以退回到“题名 + 语种 + 出版年范围 + 版本信息”的组合。缺题名的情况很少,但一旦出现,最好保留该条记录并标记为“低置信待人工”,不要硬让模型去猜。

题名变体里最让模型头疼的是并列题名、原文题名和翻译题名同时出现。比如一条中文记录里有“题名:百年孤独;原题名:Cien años de soledad”,另一条英文记录只有“Title: One Hundred Years of Solitude”。如果清洗时把原文题名丢掉,模型只能靠作者猜;如果保留,模型能通过原文题名建立联系。因此构造提示词时,要尽量同时提供正题名和并列题名字段。

4. 本地模型环境:从两条记录跑通开始

4.1 本地推理需要什么条件

Local LLMs 的落地条件和“训练大模型”完全不同。做书目聚簇通常只做推理,不需要从零训练。普通环境里跑一个 7B 量级量化模型,显存 8GB 左右是一次常见的起步配置;如果只有 CPU,也能跑小模型,只是批量任务会很慢,适合先跑通流程和验证小样本。

我的建议是先检查三样东西:模型权重是否已经下载到本地、推理服务的端口或命令行调用方式是否可用、输出目录是否有写入权限。表面上是模型没反应,实际上往往卡在这三个前置条件上。

工具链上,常见的本地推理方式包括 llama.cpp 提供的命令行和 server 模式、Ollama 这类本地服务,以及 Transformers 系列的 Python 脚本。具体选哪个取决于你的原有技术栈。如果后面要写批量脚本,选一个带 HTTP 接口的推理服务会更舒服,否则每次调用都从命令行启动会浪费大量时间。

4.2 最小可运行的记录比对流程

第一次测试不要直接处理全量数据。先取两条你已知属于同一个超作品的记录,人工确认模型能不能判断对。

一条标准的书目记录构造出来后,大概长这样:

record_a = { "record_id": "A0001", "title": "百年孤独", "origin_title": "Cien años de soledad", "author": "加西亚·马尔克斯", "lang": "zh", "publisher": "南海出版公司", "year": "2011", "edition": "第1版" } record_b = { "record_id": "B0017", "title": "One Hundred Years of Solitude", "origin_title": "Cien años de soledad", "author": "Gabriel García Márquez", "lang": "en", "publisher": "Harper & Row", "year": "1970" }

然后把这两条记录合并成一段文本,发送给本地推理服务。提示词里要写明任务、字段含义、输出格式和判断维度,不能只丢两行题名,否则模型没法分辨“版本差异”和“不同作品”。

示例提示词结构:

请比较以下两条书目记录,判断它们是否属于同一个“超作品”。 同一个超作品包括同一作品的不同译本、不同版本、影印本、再版, 以及与原作有明确衍生关系的改编作品。 输出 JSON,字段包括 same_superwork、confidence、reason。

reason 必须要求模型写具体证据,比如“责任者一致,原文题名一致,语言和出版信息不同属于版本差异”,而不是笼统写“语义相似”。这个 reason 不只是给调试看的,也是后面人工复核和生成簇说明的素材。

4.3 把输出格式固定下来,聚簇才有依据

本地模型不一定每次都能输出干净 JSON。建议在提示词里给一个完整的 JSON 模板,并在解析时做容错:

  • 先尝试解析完整 JSON;
  • 解析失败时,用正则提取布尔字段和 reason;
  • 仍然失败时,把该条标记为“解析失败”,不要直接跳过,也不要把默认值当正确结果写进簇里。

两两判定的结果文件建议一行一个 JSON,字段包括 record_a_id、record_b_id、判定结果、置信度、原因、模型名称、提示词版本、时间戳。保存中间结果比只保存最终簇有用得多,因为大多数聚类错误都要回到这两两判断层面去找原因。

5. 相似度不是答案,聚簇算法和阈值才是最终决策

5.1 为什么两两判定不能直接形成簇

很多第一次做这个任务的人会觉着,只要每对记录都判断过,把有连接的记录放一起就是簇。这看起来顺理成章,实际会踩传递性陷阱。

假设记录 A 是西班牙语原著,记录 B 是中文译本,相似度很高;记录 B 和记录 C 是同一个中文译者校订的不同版本,相似度也很高;但 A 和 C 之间的年份相差五十年,出版社和版式差异很大,模型给出的相似度只有临界值以下。如果只看两两连线再合并,A、B、C 还是可能全部进一个簇。这个结果不一定错,但当数据集变大后,一连一排的“长链合并”会把本来完全无关的作品全部串进同一个超作品里,用户看到的就是一个包含几十种书的大杂烩。

所以在两两判定之后,还要用聚簇算法做一次全局控制,而不是让相似度自然扩散。

5.2 分块召回、相似度阈值与聚簇方法怎么配

对几十万条记录,不能直接算全量相似度矩阵。常见思路是先分块,再用局部候选对建图。

分块键可以用责任者姓氏、出版年份前三位、语种、题名词首字母组合。分块的作用是降低无效比对。同一个超作品内部通常有至少一个稳定分块键相同,比如同一作者或同一原始语种。如果分块键设得太粗,候选池会很大;设得太细,又会把真正相关的记录切到不同块。建议先用测试集分别做几组分块实验,看召回能不能保住绝大部分正确对。

得到候选对后,有两种落地选择:

  • 对候选对做相似度阈值过滤,再用连通分量合并。适合数据量中等、对召回要求较高的场景。阈值要设高一些,避免长链合并。
  • 对候选对向量做 DBSCAN 或 HDBSCAN。这类密度聚类能识别出“核心点、边缘点、噪声点”,比简单的连通分量更容易控住边界。但需要调邻域参数,参数含义不如相似度阈值直观。

如果项目里已经有图数据库或图计算框架,也可以把候选对建成图,跑社区发现算法。社区发现的好处是能从全局结构判断哪些节点应该属于同一簇,不只是依赖单条边的权重。

5.3 阈值调整顺序:先看错例,再动参数

有一种很常见的错误做法:打开聚类结果,发现“分割太多”,就把相似度阈值降 0.05;发现“合并太狠”,又把阈值升 0.05,完全靠感觉绕圈。

我更建议按下面的顺序调:

  1. 先抽 20 条错误簇,看错误类型是“应该合并但没合并”,还是“不该合并却合并了”。
  2. 如果是漏并,优先检查候选召回阶段有没有把正确对筛掉,不要只动聚类阈值。
  3. 如果是错并,查看连接这些记录最多的中间节点,确认是不是长链合并导致。
  4. 阈值的每次调整都要在固定测试集上重跑,记录精确率和召回率的变化。

阈值没有标准值。常见相似度阈值从 0.7 到 0.9 都有人用,具体要看你的语种、字段完整度、嵌入模型和分块方式。测试集存在的作用,就是把这种不确定性控制在一个可比较的范围内。

6. 结果验证:抽检、日志和人工复核不能省

6.1 抽检三类样本:高置信、低置信、边界样本

聚类跑完后不要只输出“簇数变少了”之类的结论。建议抽检三类样本。

高置信样本是模型判断两个同簇记录且置信度很高的对。这类样本看起来最安全,也要抽查,因为如果提示词写偏了,可能把一种固定模式当成正确信号。

低置信样本是关系比较模糊、紧贴阈值的对。这类样本最容易暴露字段缺失和语种支持问题。发现低置信样本大量无法确认时,应该回到数据清洗阶段,而不是继续调阈值。

边界样本指那些恰好被切分在不同簇、但责任者和题名都接近的记录。边界样本检验的是召回能力,漏在这些地方,用户搜索时依然看不到完整作品聚合。

注意:抽检要从完整中间结果里抽样,不要只看最终产物。没有中间对判断的日志,很多错误根本定位不了。

6.2 让本地大模型给判断理由

超作品聚类项目最怕变成黑盒:问结果怎么来的,只能回答“模型算的”。这在图书情报场景里不够用,因为最终进入发现系统的数据需要能被解释、被审核。

解决方法是让两两判定阶段的大模型必须输出 reason,并在聚簇阶段保留“哪些候选对参与了这条连接”的路径。用户问“为什么这本书和另外几本归在一起”时,系统至少能回答“根据责任者、原文题名和版本信息判定为同一作品的不同表达”。

理由不必特别长,但要落到字段级别。如果模型只写“两段文本主题相近”,那这条判断基本不可信。主题相近完全可能是两本同题材但毫不相关的书。

6.3 评价指标不要太复杂,但必须能复现

做信息检索和知识组织的人可能会想到非常细的评估指标。对实际书目数据,我建议先看三个指标就够了:

  • 合并准确率:抽检样本中,人工确认归并正确的簇占抽检簇的比例;
  • 漏并率:人工确认本应属于同一超作品、但系统拆成了多簇的比例;
  • 错并率:人工确认本不属于同一超作品、但系统放进了同一个簇的比例。

这三个指标要靠人工审核样本数算出来。测试集固定后,每次调整提示词、模型、阈值、分块键,都记录一遍指标,项目才能从“跑了一次”变成“持续可优化”。

如果项目后续要写论文或做成开放数据,可以再补 B-Cubed 这类面向聚类的综合评价。但项目早期别追求公式复杂,先让审核的人能看懂,能快速判断这次改动是变好还是变差。

7. 批量落地的稳定做法:断点、重试、版本记录

7.1 按规则先行、候选召回、LLM 兜底的分层流程跑批

到批量阶段,最忌讳的是把所有数据一次性全部丢给本地大模型。这样一旦中途失败,前面所有结果都可能作废,而且很难定位是哪一个环节出了问题。

推荐的批量流程是分四层:

  1. 规则层:先用 ISBN、完整题名加责任者这类硬规则把一定能合并的记录合并掉;
  2. 候选召回层:对剩余记录做分块和向量召回,生成候选对;
  3. LLM 判定层:只对候选对做两两判断;
  4. 聚簇决策层:把规则结果和 LLM 判定结果统一建模,输出最终簇。

规则层处理掉的记录不需要进入模型,节省的不只是时间,还有错误率。你可以先观察规则层能解决多少硬重复,再确定模型层需要处理多少候选对。不同馆藏质量差异很大,有些数据里硬重复率本身就低,规则层很快就结束了。

7.2 失败任务与中间结果怎么保存

本地推理虽然不依赖外部服务,但也不是一直稳定。批量任务可能遇到显存占用过高、进程被杀、输出文件被占用、电脑休眠导致连接中断。因此从第一天起就要做断点。

建议每个批次处理完 500 或 1000 条后就写一次中间结果。文件命名里带上批次号和时间戳,比如 pairs_0001_20250426.jsonl。这样重新跑的时候只要从失败的批次号继续,不需要重新处理全部数据。

批量脚本还应提供幂等性:重新运行某批次时,先读已有的中间文件,如果某对记录已经判断过,直接读取结果,不做重复推理。这既节省时间,也避免同一对记录在不同轮次得到不同结果时,后面的人不知道以哪次为准。

7.3 真正会坑你的是版本漂移和输出目录

模型和提示词的版本记录很容易被忽略。上周跑出来的簇和这周跑出来的簇不同,可能是因为本地模型的权重被更新过,也可能是因为提示词里一个字的改动。如果不记录版本,人只能对着两份结果猜测差异来源。

建议每个运行批次保存一个 meta 文件,内容包含:输入数据快照标识、模型名称和量化格式、推理服务地址、提示词版本、嵌入模型名称、相似度阈值、聚簇算法参数、运行时间、输出文件路径。这组信息并不难记录,但能在问题排查时帮你排除大量干扰项。

另外,输出目录不要随意覆盖。每次批跑都新建一个带时间戳的目录,至少保留最近三个版本,确认结果稳定后再清理旧文件。目录到底放本地磁盘还是共享存储,取决于你的实际环境,但必须确认写入权限和路径内容不会因为系统重启而丢失。

8. 常见问题排查顺序:先输入,再环境,后参数

8.1 返回空结果或解析 JSON 失败

先不要怀疑模型能力,按下面的顺序查:

  1. 看提示词里要求输出 JSON 的模板是不是太多层,模型容易在嵌套结构上出错;
  2. 看输入记录里是否有乱码字符、不可见换行符、引号未转义;
  3. 看推理服务返回的原始内容是否被日志截断,有时候 JSON 本身是对的,只是读取端用了错误的编码;
  4. 如果持续失败,把提示词里的 JSON 模板改成更扁平的键值结构,减少嵌套;
  5. 每一轮都把失败样本单独存起来,不要和成功样本混在一个结果文件里。

8.2 把不相关的作品合并在一起

出现这种问题的第一反应应该是查候选召回,而不是立刻调低模型置信阈值。合并错误往往不是模型判断不对,而是它在错误的候选对上做了正常判断:这两条记录在某些分块键下被放在一起,模型只能尽力判断关系,给出的是“相关但不是同一超作品”的结论,后续聚簇却把这个低置信关系也用了进去。

排查时先打开错误簇的连接路径,看是哪一条边把两个明显无关的簇连起来的。删掉这条边后,如果错误簇能正确分裂,问题多半出在相似度阈值设得过低或聚簇算法允许长链合并,而不是模型本身。

8.3 显存不足、速度慢、批量任务中断

显存不足时先降并发,再降上下文长度,最后才考虑换更小的模型。很多本地推理默认会同时处理多条请求,书目字段并不长,但批量并发一旦拉满,显存会立刻吃紧。先在两条记录上确认推理速度,再按资源情况调整并发数。

批量任务中断最常见的原因是输出目录空间不足和进程被系统杀掉。排查时先看磁盘剩余空间、日志输出目录、进程结束时的系统日志,再看模型服务端日志。如果每次都在同一批量的固定位置中断,很可能是那一批输入记录里有特殊格式导致推理服务异常,而不是资源问题。

8.4 我的最终建议是按最小闭环重复验证

在图书馆和书目数据这个方向上,本地大模型的真正价值不在于替代原有规则,而在于补上语义判断这一层。按我个人的落地经验,最有效的推进路径是:先做一个 100 条左右的人工标注测试集,再跑通两条记录的两两判定,接着扩展到候选召回和聚簇,最后再进入全量批跑。

这个闭环的好处是每一步都能验证。模型换一个、提示词改一句、阈值调一点,都能用固定测试集的指标反馈来确认变化方向。如果一上来直接让本地大模型处理全部书目,最后你得到的不是聚类结果,而是一堆无法解释、无法重现、无法修正的“黑盒簇”。

真正值得长期盯住的,是输入字段的完整性、候选召回是否漏掉正确记录、聚簇方法会不会长链合并,以及每一轮运行能否复现。把这几件事控制住了,Local LLMs 在书目发现场景里才能从“看起来能用”变成“可长期可靠运行”。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/4 14:39:29

技术写作中的结构化剪辑:从零散信息到高质量文档的实战方法

在实际内容创作和技术分享领域,我们经常需要处理各种格式的素材,将它们整合、重构,最终输出结构清晰、逻辑严谨、可读性强的作品。这个过程本身,就与“剪辑”这一概念高度契合——它不是简单的拼接,而是基于对原始素材…

作者头像 李华
网站建设 2026/9/4 14:39:21

用OpenCode高效补环境:AI辅助JS逆向流程实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/4 14:37:08

3步完成Node.js安全响应头配置:新手避坑指南

3步完成Node.js安全响应头配置:新手避坑指南 【免费下载链接】nodebestpractices ✅ The Node.js best practices list (July 2026) 项目地址: https://gitcode.com/GitHub_Trending/no/nodebestpractices 你刚把Express项目部署上线,被问了一句&…

作者头像 李华
网站建设 2026/9/4 14:35:58

Codex 2500万用户背后:AI编程Agent如何重塑开发流程

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/4 14:35:02

Android服药提醒App开发全解析:从SQLite数据库到AlarmManager精准提醒

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/4 14:33:43

Grok Bot 能否复现“ChatGPT 时刻”?关键看产品破圈与用户留存

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华