本地模型实现信息抽取:从选型到工程落地全指南
2026/8/27 23:58:04 网站建设 项目流程

过去两年,只要提到“信息抽取”,绝大多数团队的第一反应都是:把文本丢给云端大模型 API,等着拿回 JSON。这个流程确实好用,但它默认了一个前提——你的数据允许上传到第三方服务器。一旦数据涉及内部业务、客户隐私、审计留痕,或者干脆要部署在无外网的机房,这条路就断了。于是“本地模型能不能做抽取”成了越来越多团队必须回答的问题。

这篇文章想给一个明确的判断:本地模型做抽取任务,已经不是“能不能用”的问题,而是“怎么选、怎么调、怎么兜底”的问题。它在隐私、成本、可定制性上有不可替代的优势,但它的坑也很真实——Prompt 稍微写含糊,输出就不稳定;模型选小了,准确率直接崩;选大了,显存又扛不住。本文会从抽取任务的基础认知、本地模型选型、部署环境、Prompt 设计与代码实现、结果验证和工程落地方案完整展开,帮你把这条链路走通。

如果你正在做文档信息抽取、结构化数据构建、建筑与地理信息相关的属性抽取,或者只是好奇本地模型和云端 API 到底该怎么选,这篇文章值得读完。

1. 这篇文章真正要解决的问题

很多人对“本地模型做抽取”有一个误解:以为把云端 API 换成开源的模型权重,改一下base_url,剩下的事就水到渠成。真正动手后才发现,问题不是“模型能不能跑”,而是:

  • 同一个 Prompt 在云端 API 上稳定输出 JSON,换成本地小模型就频繁漏字段、套壳输出、甚至直接说“我不会”;
  • 模型量化版本选错了,回答质量下降明显,但显存占用少得有限;
  • 本地模型没有云端 API 那么好用的函数调用和结构化输出能力,必须自己设计 JSON Schema、做后处理;
  • 抽取结果没有置信度,错误数据直接进数据库,后续校验成本反而更高。

这篇文章要解决的,就是这些具体问题。

我从结论说起:本地模型做抽取,真正的价值不在于“模型本身多聪明”,而在于它让抽取这条流水线变得可落地、可审计、可离线、可长期用。它的核心壁垒不是算法,而是工程——包括 Prompt 设计、输出约束、结果校验和失败重试机制。

什么类型的读者最应该看?

  • 做 RPA、文档数字化、知识图谱构建的开发者,需要批量从非结构化文本里抽实体和关系;
  • 在地理信息、遥感、建筑行业做数据处理的工程师,需要从规划文档、勘察报告、GIS 元数据里抽取建筑属性信息;
  • 做内部数据平台,数据不允许出内网,但希望用上大模型能力的团队。

如果你是这几类人,这篇文章会给你一条完整的落地路径。

2. 信息抽取任务与本地模型的基础认知

2.1 信息抽取到底在抽什么

信息抽取(Information Extraction,IE)是把非结构化或半结构化文本,转换为结构化数据的任务。最常见的子任务包括:

子任务英文说明
命名实体识别NER从文本中识别出人名、地名、机构名、时间、金额等实体
关系抽取RE判断两个实体之间的关系,例如“张伟是项目负责人”
事件抽取EE抽取事件触发词、事件类型、参与者和时间地点
属性抽取Attribute Extraction抽取实体的属性,例如建筑的面积、层数、建造年份

一项现实的抽取任务,往往是这些子任务的组合。例如从一份建筑勘察报告里抽取“项目位置、建筑面积、建筑类型、当前状态”,本质上是先做实体识别,再做属性填充,最后输出成 JSON。

传统做法是训练专门的 NER 模型加规则模板,成本高且维护周期长。云端大模型改变了这个局面,但引入了数据出域问题。本地模型则是对这两条路线的一个折中:既能靠自然语言 Prompt 快速适配新任务,又能把数据留在自己的机器上。

2.2 building footprint extraction 到底是什么任务

这里要澄清一个常见混淆。网络上经常会看到 building footprint extraction(建筑足迹提取)这个热词,它指的是从遥感影像中提取建筑轮廓,属于计算机视觉里的语义分割或实例分割任务,直接产出的是矢量多边形或掩膜,而不是文字。

它和信息抽取是两个方向,但都属于“从原始数据里提取结构化信息”的范畴。在 GeoAI 落地项目里,常见的工作流是:先用视觉模型从影像中提取建筑轮廓,再用 NLP 模型从规划文本、权属材料里抽取建筑的属性信息,最终把几何信息和属性信息合并成完整的建筑数据库。

所以,当你搜索 Local models extraction 相关技术方案时,需要先确认自己要做的是图像轮廓提取,还是文本属性抽取。本文后续内容主要聚焦文本信息抽取方向,但在工程架构上,这两条链路都适合接入本地模型。

2.3 本地模型与云端 API 的对比

对比维度云端大模型 API本地开源模型
数据安全数据需发送到第三方服务器数据不出本机或内网
初始成本按 Token 付费,长期累计成本高需要 GPU 硬件投入
部署复杂度低,几行代码接入较高,需环境配置和模型管理
可定制性依赖平台功能可微调、可量化、可换模型
稳定性平台维护,稳定性较好依赖自身运维能力
离线可用不支持支持
延迟受网络和平台负载影响本地推理,延迟可控

这个对比想说明一个点:本地模型不是全面替代云端 API,而是在“数据敏感、成本敏感、需要离线”的场景里成为更优解。很多团队的做法是云端模型做冷启动验证,本地模型做生产环境服务,两者通过统一的接口抽象切换。

2.4 为什么抽取任务适合本地模型

抽取任务有一个特点:实体类型和输出格式高度固定。某个项目里,可能只需要抽取“地点、建筑面积、建筑类型、用途状态”这几个字段。这类任务对模型的“常识广度”要求不高,但对“指令跟随能力”和“格式稳定性”要求很高。

这正好落在开源本地模型的能力射程内。一个 7B 到 14B 参数量的开源模型,经过合适的 Prompt 约束和 JSON Schema 引导,完全可以在限定领域的抽取任务上达到可用水平。这也解释了为什么当前本地模型最活跃的应用方向之一就是结构化抽取——它是“模型能力有限但任务边界清晰”的最佳组合。

3. 本地模型选型:从哪个模型开始

3.1 开源本地模型的常见选择

目前主流的开源本地模型系列主要有几个方向,我这里不做跑分排名,只给选型思路:

  • Qwen 系列(通义千问开源版):中文抽取能力表现出色,对中文长文本和结构化输出支持较好,是目前国内团队最常用的本地模型之一。
  • Llama 系列(Meta 开源):社区生态最丰富,几乎支持所有推理框架,适合作为底座做微调,但中文能力通常需要补充训练。
  • Mistral 系列:欧洲团队开源,英文能力强,上下文窗口和指令跟随能力优秀,但在中文场景下应用不如 Qwen 方便。

如果你处理的是中文文本,从 Qwen 系列开始是更稳妥的选择;如果业务面向英文且需要更强的推理能力,Llama 和 Mistral 也值得测试。

3.2 参数量怎么选

这可能是选型中最重要的一个决策。

参数量级建议显存适用场景
3B~4B4GB~8GB简单实体抽取、格式固定、对准确率要求不极高
7B~8B8GB~16GB大多数信息抽取任务,平衡准确率和资源消耗
14B16GB~32GB复杂关系抽取、长文档、需要更强指令跟随
32B 以上32GB 以上或需量化高难度抽取、多语言、需要接近云端 API 效果

真实项目中,我推荐先按“任务复杂度 + 显存上限”确定参数量,而不是先追求大模型。原因很直接:抽取任务通常可以拆成多个小任务,拆完之后,7B 模型往往就够用了。如果一开始就上 32B 模型,部署成本高不说,推理延迟也会制约批处理效率。

3.3 量化版本要不要用

量化(Quantization)是把模型参数从 16 位浮点数压缩到 8 位或更低,以减少显存占用、提高推理速度,但会带来少量精度损失。

对抽取任务,我的建议是:先用原版精度跑通基准测试,确认准确率达标,再尝试 Q4 或 Q5 量化,对比输出质量。如果量化后的结果没有明显变差,就可以用量化版本部署,因为它的显存占用和推理成本会低很多。

这里有一个值得注意的坑:量化版本在大部分简单抽取任务上没有差异,但在长文本、复杂指令或多语言混合的场景下,可能出现“字段输出不完整”“格式偶尔跑偏”等问题。因此量化后的效果验证绝对不能省。

4. 本地部署环境准备

4.1 推理框架选哪个

当前部署本地模型常用的推理方案有三个,按易用性排序:

  1. Ollama:安装简单,模型管理方便,自带 OpenAI 兼容 API,适合个人和中小团队快速验证。
  2. llama.cpp:底层的 C/C++ 推理框架,适合嵌入式环境和极致性能调优。
  3. vLLM:吞吐高,适合生产环境大规模并发推理,但部署复杂度更高。

本文以 Ollama 为主线,因为它能最快跑通完整链路,也最符合“从零到一”演示需求。生产环境需要高并发时,可以迁移到 vLLM——代码改动幅度很有限。

4.2 安装 Ollama

Ollama 支持 Windows、Linux 和 macOS。Linux 和 macOS 可以执行官方安装脚本:

curl -fsSL https://ollama.com/install.sh | sh

Windows 用户下载安装包安装即可。安装完成后,检查版本:

ollama --version

启动服务:

ollama serve

在 Linux 上,Ollama 安装后通常会注册为 systemd 服务,可以通过ollama serve手动启动,方便观察日志。

4.3 下载并运行模型

以 Qwen 系列 7B 模型为例,在终端执行:

ollama run qwen2.5:7b

首次运行会先下载模型权重,完成后进入交互式对话界面,可以直接输入文本测试。

到这里,本地模型已经跑起来了。这一步的关键是确认模型标签在本机真实存在。可以用以下命令查看已下载的模型:

ollama list

如果你不确定某个标签是否存在,可以在模型库页面确认名称,或直接使用ollama pull qwen2.5:7b拉取。

5. 核心流程:用本地模型做抽取任务

5.1 先设计任务,再写 Prompt

很多人做抽取任务,一上来就写 Prompt,这是一个误区。先要明确“输出 Schema”,也就是你希望模型输出什么结构的数据。

例如,要从建筑勘察文本中抽取属性,最简单的 Schema 是:

{ "location": "项目地点", "building_type": "建筑类型", "area": "建筑面积", "status": "当前状态" }

Schema 决定了 Prompt 里的“输出要求”部分。Schema 设计得越清晰,后续解析和校验越简单。

5.2 本地抽取的 Prompt 设计原则

针对本地模型,Prompt 设计有四个原则:

第一,身份与任务要具体。不要写“你是一个助手”,要写“你是建筑信息抽取助手,负责从文本中抽取指定字段”。

第二,输出格式要显式。直接给出 JSON 示例,比单纯说“输出 JSON”有效得多。本地模型对示例的模仿能力很强,宁可多花几行 token,也要在 Prompt 里放一个完整的输出示例。

第三,指定缺失处理。告诉模型“如果某个字段没有找到,输出空字符串或 null”,避免模型自己编造内容。这一步是抽取任务里最容易出问题的地方。

第四,保持温度低。抽取是确定性任务,temperature 建议设置为 0,抑制随机性。

5.3 Prompt 模板示例

下面是一个适合本地模型的抽取 Prompt 模板:

你是建筑信息抽取助手。请从用户提供的文本中抽取以下字段: - location:项目地点 - building_type:建筑类型 - area:建筑面积,保留数字 - status:当前状态,如已建成、在建、规划中 要求: 1. 只输出 JSON 对象,不要输出任何解释文字。 2. 字段未找到时输出 null,不要编造。 3. 面积统一使用单位“平方米”。 示例输出: {"location": "上海市浦东新区", "building_type": "研发大楼", "area": 12000, "status": "在建"}

这个模板的关键在于“只输出 JSON”和“未找到时输出 null”,它们能显著提高后续解析的成功率。

5.4 输出后处理与校验

即便 Prompt 写得再好,本地模型仍然可能输出 Markdown 代码块、多余解释、或者字段名跑偏。因此后处理是必须的,不能跳过。

后处理通常包括三步:

  1. 去掉 Markdown 代码块标记;
  2. json.loads解析,失败时进入重试;
  3. 用 JSON Schema 校验字段是否齐全,缺失的字段标记为 null。

这套后处理逻辑虽然简单,但它决定了整个抽取流水线的稳定性。生产环境下,建议把“解析失败”和“字段缺失”统计成指标,用于衡量模型的实际效果。

6. 完整示例代码实现

6.1 安装依赖

需要安装 Ollama 的 Python 库,以及用于测试的 OpenAI SDK。

pip install ollama openai

如果后续要切换到 vLLM 或其他 OpenAI 兼容服务,openai这个依赖会非常有用。

6.2 示例一:使用 Ollama Python 库做实体抽取

新建文件extract_entities.py,代码如下:

# 文件路径:extract_entities.py import ollama response = ollama.chat( model="qwen2.5:7b", messages=[ { "role": "system", "content": ( "你是信息抽取助手。请从用户输入文本中抽取实体," "并输出 JSON 对象,字段包括:person、organization、" "location、date。没有找到的字段输出空列表。" ), }, { "role": "user", "content": ( "2024年6月,绿城建筑公司在杭州完成了智慧园区项目的验收," "项目负责人是张伟,验收日期是6月28日。" ), }, ], format="json", ) print(response["message"]["content"])

运行验证:

python extract_entities.py

预期输出是一个 JSON 对象,例如:

{ "person": ["张伟"], "organization": ["绿城建筑公司"], "location": ["杭州"], "date": ["2024年6月", "6月28日"] }

这里format="json"参数会让 Ollama 尽量以 JSON 格式输出,能大幅度降低解析难度。

6.3 示例二:使用 OpenAI 兼容接口抽取建筑属性

Ollama 启动后默认在11434端口提供 OpenAI 兼容 API,可以用标准 OpenAI SDK 调用,方便以后切换后端。

新建文件extract_building.py

# 文件路径:extract_building.py from openai import OpenAI client = OpenAI( base_url="http://localhost:11434/v1", api_key="ollama", # 本地服务不校验真实 key,但字段不能为空 ) resp = client.chat.completions.create( model="qwen2.5:7b", temperature=0, response_format={"type": "json_object"}, messages=[ { "role": "system", "content": ( "你是建筑信息抽取助手。请从文本中抽取字段:location、" "building_type、area、status。只输出 JSON,不要输出解释。" ), }, { "role": "user", "content": ( "上海市浦东新区张江科技园的研发大楼,建筑面积约12000平方米," "目前正在建设中。" ), }, ], ) print(resp.choices[0].message.content)

运行验证:

python extract_building.py

预期输出:

{ "location": "上海市浦东新区张江科技园", "building_type": "研发大楼", "area": 12000, "status": "在建" }

这个示例的关键点是:base_url只要指向http://localhost:11434/v1,本地模型和云端 API 的切换就只剩配置差异,业务代码基本不用改。

6.4 示例三:批量抽取与 JSON 解析后处理

真实项目中,抽取往往面向批量文本。我们把后处理逻辑封装成一个函数,并在循环中批量执行。

新建文件batch_extract.py

# 文件路径:batch_extract.py import json import ollama def parse_json_response(content: str) -> dict: """清理模型输出并解析 JSON,解析失败时抛出异常。""" content = content.strip() # 去掉常见的 markdown 代码块标记 if content.startswith("```"): lines = content.splitlines() if lines and lines[0].startswith("```"): lines = lines[1:] if lines and lines[-1].strip() == "```": lines = lines[:-1] content = "\n".join(lines) return json.loads(content) def extract_fields(text: str, model: str = "qwen2.5:7b") -> dict: """抽取文本中的建筑字段。""" resp = ollama.chat( model=model, messages=[ { "role": "system", "content": ( "抽取以下字段:location、building_type、area、status。" "只输出 JSON,没有的信息输出 null,不要编造。" ), }, {"role": "user", "content": text}, ], format="json", ) return parse_json_response(resp["message"]["content"]) texts = [ "北京朝阳区望京 SOHO 塔一,写字楼,2014年投入使用。", "成都高新区天府软件园,办公园区,园区面积约100万平方米。", "武汉东湖新技术开发区的地下综合管廊项目,仍在规划中。", ] for text in texts: try: result = extract_fields(text) print(json.dumps(result, ensure_ascii=False)) except json.JSONDecodeError as e: print("解析失败,原始输出:", e)

运行验证:

python batch_extract.py

如果某条数据解析失败,程序不会整体中断,而是打印错误信息,方便后续定位 Prompt 或模型问题。

7. 运行结果与效果验证

7.1 验证步骤

本地模型做抽取,验证不能只看一两条结果,要做三件事:

第一,准备一个测试集。至少 20 到 50 条真实业务文本,覆盖正常情况、缺失字段情况、长文本情况。

第二,统计指标。抽取任务的常用指标是字段级准确率和字段级召回率。字段级准确率衡量“抽出来的字段是否正确”,字段级召回率衡量“应该抽到的字段是否被漏掉”。

第三,检查失败案例。对每一条解析失败或字段错误的数据,记录原因,是 Prompt 不清晰,还是模型能力不足,还是后处理有 bug。

7.2 简单评估脚本

这里给一个最小评估思路:

# 文件路径:evaluate.py import json from batch_extract import extract_fields test_cases = [ { "text": "上海市浦东新区张江科技园,研发大楼,12000平方米,在建。", "expected": { "location": "上海市浦东新区张江科技园", "building_type": "研发大楼", "area": 12000, "status": "在建", }, }, ] total = len(test_cases) correct = 0 for case in test_cases: result = extract_fields(case["text"]) if result == case["expected"]: correct += 1 else: print("期望:", case["expected"]) print("实际:", result) print(f"准确率:{correct}/{total}")

这个脚本只做说明,实际项目里还需要处理字段级部分匹配和未知字段等问题,但思路是一致的。

7.3 失败时先看哪里

如果结果不理想,按以下顺序排查:

  1. 先看原始输出。用ollama run或脚本直接打印模型输出,确认是“格式不对”还是“内容不对”。
  2. 格式不对,优先修 Prompt 和后处理;内容不对,优先换模型和调 Prompt。
  3. 确认是否使用了低温度。抽取场景 temperature 必须低,否则同样的输入可能输出不同结果。

8. 常见问题与排查思路

本地模型做抽取的坑不少,这里把高频问题整理成表格。

问题现象可能原因排查方式解决方案
模型输出不是 JSON,而是解释文字Prompt 约束不够强查看原始输出内容在 Prompt 中强调“只输出 JSON”,并加示例;开启 format="json"
字段总是丢,特别是面积、日期模型参数量小,长文本注意力不足检查缺失字段是否在输入中出现拆分长文本,降低单次抽取字段数,或换更大模型
同一个样本多次运行结果不同temperature 设置过高检查推理参数将 temperature 设置为 0
启动时显存不足模型量化等级低或并发过高观察启动日志和显存占用换更小参数量模型,或启用 Q4/Q5 量化
首次运行很慢,卡在下载模型权重未下载完成查看ollama list和网络状态确认已执行ollama pull,磁盘空间充足
批量处理时单条失败导致整体中断后处理没有做异常捕获查看错误堆栈对每条数据捕获json.JSONDecodeError,失败时记录日志并继续
本地模型准确率低于云端 API模型能力或 Prompt 设计问题做小规模对比测试先优化 Prompt 和输出约束;仍不达标再换更大模型
换模型后行为差异大不同模型对 Prompt 的敏感度不同对比两个模型的原始输出针对模型调整 Prompt,不要期望一套 Prompt 通吃

这组问题里,最高频的还是“输出不稳定”和“字段缺失”。它们通常不是独立问题,而是 Prompt、模型参数量、任务拆分三者共同作用的结果。建议一次只改一个变量,不要同时换模型、改 Prompt、改后处理,否则很难定位瓶颈。

9. 最佳实践与工程建议

9.1 把抽取任务拆小,不要追求一次搞定

本地模型的能力上限决定了,一个 Prompt 里塞太多字段,抽取质量会明显下降。更稳妥的做法是:先抽实体,再做关系或属性匹配,最后拼接成结构化结果。看似多跑了几次模型,但每次任务边界清晰,准确率反而更高。

9.2 输出 Schema 先行,Prompt 与后处理共用一份定义

把字段定义、JSON Schema、Prompt 模板放在一个配置文件里维护,避免 Prompt 和后处理各写一份。这样字段变更时,只改一处,不会出现 Prompt 里写了area,后处理却在找building_area的尴尬。

# 文件路径:schema.py EXTRACTION_SCHEMA = { "location": "项目地点", "building_type": "建筑类型", "area": "建筑面积", "status": "当前状态", }

9.3 建立失败样本回收机制

生产环境中,建议把解析失败、字段缺失、置信度不高的样本统一存储,定期人工复核,再把这些样本加入测试集或微调数据。这是本地模型抽取效果持续提升的最可靠路径。很多团队用久了效果变差,就是因为没有做失败样本回收,模型和 Prompt 都停在原地。

9.4 用缓存提升批量抽取效率

同一段文本被重复抽取的情况很常见。可以按文本内容哈希做结果缓存,重复任务直接读取历史结果,减少 GPU 占用和耗时。对于大体量历史数据处理,这一步能省下大量推理成本。

9.5 安全与合规提醒

如果处理的数据涉及个人或敏感业务信息,请确保部署环境、模型下载渠道和输出存储都符合公司内部的安全规范。本地模型虽然解决了“数据不出域”的问题,但模型权重本身、Prompt 内容、抽取结果日志都属于需要管理的数据资产,建议做好访问控制和审计。

9.6 从 Ollama 迁移到 vLLM 的时机

当单机并发要求提高,比如需要同时处理几十个在线抽取请求时,Ollama 的并发能力会逐渐成为瓶颈。此时可以迁移到 vLLM。因为代码层使用的是 OpenAI 兼容接口,迁移时只需要把base_url指向 vLLM 服务地址,业务代码基本不用动。这个架构设计,建议在项目一开始就预留。

10. 总结与后续学习方向

本文围绕“本地模型做 extraction”这条主线,讲清楚了几个关键点:本地模型适合固定边界的信息抽取任务;选型上按任务复杂度和显存上限决定参数量;Prompt 设计和 JSON 后处理是决定效果的核心工程环节;模型能力不够时,靠拆分任务和失败样本回收比盲目换大模型更有效。

下一步建议你按这个顺序实践:先找一个真实业务字段,设计 Schema;用本地 7B 模型跑通 20 条测试样本;统计准确率,针对失败样本迭代 Prompt;稳定后接入批量处理脚本;并发需求出现时再迁移到 vLLM。

如果你想继续深入,有三个方向值得关注:一是结构化输出约束,许多推理框架已经支持 JSON Schema 级别的强约束输出,这是提升稳定性的关键;二是针对领域数据的轻量微调,用几百条标注样本微调底座模型,往往比反复调 Prompt 更可靠;三是多模态本地模型在 building footprint extraction 这类视觉任务上的应用,那是另一条同样值得投入的技术路线。

信息抽取这个领域,最终拼的不是单次召回率有多高,而是整条流水线在真实数据和长期运维中能有多稳。本地模型把主动权交还给了工程师,剩下的,就看工程做得够不够细了。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询