本地大模型信息抽取实战:从Ollama部署到批量结构化输出

本地大模型信息抽取实战:从Ollama部署到批量结构化输出 很多团队第一次接触大模型抽取任务时第一反应往往是先接云端API。原因很简单注册快、模型强、不用操心推理环境。但真正进入生产阶段后问题开始浮出水面——数据不能出域怎么办批量处理数万条文本时成本怎么控制提示词需要频繁调优每次都等网络往返能接受吗过去一年能本地部署的开源模型在抽取任务上的表现已经有了明显变化。虽然它们和头部闭源模型还有差距但在“实体抽取”“字段抽取”“结构化输出”这类边界清晰的任务上已经能承担真实业务。更关键的是本地模型让“模型 提示词 校验规则”变成了同一个工程闭环这在数据敏感、离线批处理和高频迭代场景里很有价值。这篇文章不打算做那种“下载完模型、跑通demo就结束”的教程。我会先讲清楚本地模型做抽取的适用边界再给出完整的部署、调用、评测和排错路径。文章会以信息抽取为主线同时用建筑足迹抽取building footprint extraction作为行业案例演示如何把同一个思路套到具体业务上。如果你正在犹豫要不要把抽取任务从云端迁移到本地或者已经在用本地模型但效果不稳定这篇文章可以帮你少走一些弯路。下面内容会比较多涉及模型选型、部署命令、Python调用代码、批量处理脚本和评测方法建议收藏备用。1. 本地模型做抽取任务到底解决了什么问题先说一个容易让人误解的地方本地模型做抽取真正价值不是“省钱”而是“可控”。云端API看起来便宜按次计费一天调用几百次可能就几块钱。但如果你的业务是每天处理几十万条文本、夜间定时跑批这条成本曲线会迅速变得不可控。本地模型的优势在于只要硬件允许调用量上去之后边际成本几乎为零成本变得可预测、可规划。比成本更重要的是数据边界。很多企业做抽取任务时文本里包含客户信息、合同条款、内部编号、地图坐标这些数据不适合发送到外部接口。本地部署意味着数据从采集、处理到落库全程不出内网这在合规上是一个非常大的优势。还有一个常被忽略的点迭代速度。云端API的提示词调优受限于网络延迟和配额管理每次修改都要重新发请求、等返回、看结果。本地模型的推理延迟通常更低尤其是用GPU部署后多轮调优的节奏会明显加快。对算法工程师来说这意味着同样的时间可以尝试更多提示词方案。但本地模型也有明确代价。硬件投入、模型配置、环境维护、量化调优这些都需要工程技术能力。如果你的团队完全没有GPU服务器和推理环境运维经验本地部署的初期成本可能比想象中高。所以文章开头给出的判断是本地模型抽取值得做但不是免费的午餐。它把“按量付费”换成了“固定资产 工程维护”适合数据敏感、批量大、迭代频繁的场景。2. 抽取任务类型与本地模型的能力边界2.1 从传统NLP抽取到大模型抽取信息抽取是NLP里的经典问题常见类型包括实体抽取、关系抽取、事件抽取和属性抽取。传统做法是训练BERT类模型做序列标注或者用CRF、规则模板做匹配。这类方案的优点是推理快、结果稳定但缺点是每个新字段都要重新准备标注数据、重新训练规则稍微变一变就要动代码。大模型做抽取的思路完全不同。它以提示词为“任务说明书”把抽取规则写清楚模型根据指令直接输出结构化结果。新增一个字段往往只需要改提示词模板不需要重新训练模型。这在业务字段经常调整的场景里节省了大量标注和训练成本。但大模型抽取也有自己的问题输出不稳定。同样一段文本同一套提示词模型可能偶尔漏字段、偶尔格式错。这也是为什么真正的生产系统不能只靠模型裸奔需要加校验和兜底逻辑。后面章节会详细讲。2.2 建筑足迹抽取在LLM中的正确定位最近“building footprint extraction”这个词热度不低它在地理信息领域通常指从遥感影像中提取建筑轮廓。这件事的主力是图像分割模型比如U-Net、DeepLab、Mask R-CNN而不是大语言模型。那LLM在这个场景里有什么用答案是“文本结构化”。一个建筑足迹建库项目里除了影像轮廓还有大量非结构化文本需要处理规划文本、竣工验收描述、地名地址记录、建筑属性表。这些文本里包含建筑层数、结构类型、占地面积、用途分类等信息人工录入成本高、易出错传统规则又很难覆盖多样化的表达。大语言模型在其中的定位是把非结构化文本变成结构化建筑属性。比如从一段这样的描述中抽取字段武夷路112号地块内有一栋三层办公楼占地约850平方米 总建筑面积2550平方米钢混结构屋顶为平屋面北侧临街。模型要输出{ address: 武夷路112号, building_type: 办公楼, floor_count: 3, land_area: 850, total_area: 2550, structure_type: 钢混, roof_type: 平屋面, orientation: 北侧临街 }所以如果要聊LLM层面的building footprint extraction准确的说法是“建筑足迹相关文本的要素抽取”它和遥感图像分割是互补关系不是替代关系。把这个边界讲清楚才能避免在项目设计时选错技术方案。3. 本地模型选型与部署框架对比3.1 模型选择7B还是更大参数本地模型的选择第一件事是定参数规模。7B到9B量级的模型是当前“性价比”最均衡的范围。量化之后占用显存在8GB到16GB之间消费级显卡或者入门级服务器就能跑。对抽取这类任务来说Qwen2.5系列、Llama 3.1系列、Mistral系列都有不错的表现尤其是中文场景下Qwen系列通常更稳。13B到14B量级的模型精度通常更高但显存需求明显上升推理速度也会下降。32B以上模型在抽取任务上确实更强但已经不是普通开发机可以承受的范围需要多卡或大显存服务器。这里给一个保守建议如果你的抽取任务以中文为主、字段边界清晰、输出格式固定优先试试7B到9B量级的中文优化模型。如果抽出来的字段经常存在语义模糊、需要理解长上下文再往更大模型升级。不要一开始就上大模型工程排障成本会成倍增加。3.2 推理框架选择本地模型部署有很多框架常见的有Ollama、llama.cpp、vLLM。Ollama胜在简单一条命令就能拉模型、起服务适合快速验证和个人开发。llama.cpp偏底层支持更多量化格式适合嵌入式或CPU推理但需要自己写更多配置。vLLM面向高并发生产场景支持PagedAttention等优化吞吐量高但环境配置相对复杂。对大多数团队来说从Ollama开始是最务实的路径。先把流程跑通确认效果再根据并发需求决定是否切到vLLM。下面几个示例都基于Ollama展开因为它足够简单又能覆盖完整流程。3.3 量化方式的取舍量化是本地模型绕不开的话题。GGUF格式的Q4_K_M、Q5_K_M是常用选择参数更少的Q4量化在显存占用上有优势但精度会有一定损失。抽取任务对字段准确率敏感建议优先尝试Q5或Q8只有在显存实在不够时才降到Q4。需要提醒的是不要只看模型名称判断效果。同一个7B模型不同量化级别的输出质量可能差距很大。更稳妥的做法是在正式评估时用同一组测试样本跑一遍不同量化版本用结果说话而不是凭直觉决定。4. 环境准备与最小部署4.1 硬件与软件要求一个可以跑7B量化模型的本地环境最低配置看起来是这样资源最低要求推荐配置GPU8GB显存16GB及以上显存CPU4核8核以上内存16GB32GB磁盘20GB可用空间50GB以上操作系统Linux/macOS/WindowsLinux服务器部署纯CPU也能跑但速度会比较慢。如果只是小批量测试CPU足够如果要批量处理强烈建议上GPU。版本信息请以实际项目为准本文重点演示通用思路。4.2 安装推理工具先安装Ollama。以Linux环境为例官方提供了安装脚本# 安装 OllamaLinux 环境 curl -fsSL https://ollama.com/install.sh | shmacOS和Windows用户可以直接从官网下载对应安装包。安装完成后启动服务# 启动 Ollama 服务前台运行用于验证 ollama serve生产环境建议配置为系统服务并设置开机自启。这一步完成后Ollama默认监听在11434端口。4.3 下载模型并验证拉取一个中英文兼顾的7B模型以Qwen2.5系列为例# 拉取模型模型名以 ollama 仓库实际可用为准 ollama pull qwen2.5:7b下载完成后可以先在命令行里做一个最小验证ollama run qwen2.5:7b 从这句话中抽取城市名上海位于中国东部沿海地区。看到模型返回结构化或至少可读的结果就说明环境已经通了。如果这一步失败先检查网络、磁盘空间、显存是否满足要求。后面章节的所有示例都基于“Ollama服务已经正常运行”这个前提。5. 第一个完整示例通用信息抽取5.1 任务定义通用信息抽取很好上手比如从企业信息描述里抽取公司名称、注册地、成立年份、经营范围。这类任务字段边界清晰适合作为第一个验证场景。示例输入文本上海云帆数字科技有限公司成立于2015年注册地址位于上海市浦东新区张江高科技园区 主要经营范围包括人工智能软件开发、数据处理和存储服务。期望输出{ company_name: 上海云帆数字科技有限公司, establish_date: 2015, registered_address: 上海市浦东新区张江高科技园区, business_scope: 人工智能软件开发、数据处理和存储服务 }5.2 调用本地模型写一个Python脚本调用Ollama的chat接口。这里使用requests库不引入额外的SDK依赖。# 文件路径src/llm_extract.py import requests import json OLLAMA_URL http://localhost:11434/api/chat MODEL_NAME qwen2.5:7b def chat(model: str, user_prompt: str, system_prompt: str ) - str: payload { model: model, messages: [ {role: system, content: system_prompt}, {role: user, content: user_prompt} ], stream: False } resp requests.post(OLLAMA_URL, jsonpayload, timeout120) resp.raise_for_status() return resp.json()[message][content] def extract_company_info(text: str) - dict: system_prompt ( 你是一个信息抽取助手。请从用户输入的文本中抽取企业信息 只输出JSON对象不要输出多余解释。 ) user_prompt f 请从下面文本中抽取以下字段 - company_name公司名称 - establish_date成立年份 - registered_address注册地址 - business_scope经营范围 文本 {text} 输出格式要求JSON对象。 content chat(MODEL_NAME, user_prompt, system_prompt) # 去掉可能的代码块标记 content content.strip() if content.startswith(): lines content.splitlines() lines [line for line in lines if not line.startswith()] content \n.join(lines) return json.loads(content) if __name__ __main__: sample ( 上海云帆数字科技有限公司成立于2015年注册地址位于上海市浦东新区张江高科技园区 主要经营范围包括人工智能软件开发、数据处理和存储服务。 ) result extract_company_info(sample) print(json.dumps(result, ensure_asciiFalse, indent2))关键逻辑说明chat函数封装了Ollama的chat接口system_prompt负责定义角色user_prompt里把抽取字段和输入文本都写清楚。之所以要求“只输出JSON对象”是为了降低后续解析出错概率。代码里还做了简单的Markdown代码块清理因为部分模型在输出JSON时喜欢包一层json标记。5.3 运行与验证运行脚本python src/llm_extract.py预期输出是格式化后的JSON四个字段都从文本中正确抽出。如果输出不是合法JSON第一步应该打印原始返回内容判断是模型输出格式问题还是JSON解析逻辑漏掉了其他格式干扰。成功标准有两个字段值正确、JSON可直接解析。建议把这段代码作为模板保存后续所有抽取任务都复用同一个chat函数只更换提示词和解析逻辑。6. 第二个完整示例建筑足迹属性抽取6.1 任务定义与样本构造现在把通用抽取思路套到building footprint extraction相关的业务场景。前面说过LLM做的是建筑文本属性抽取不是影像轮廓分割。这里构造一段规划描述文本模拟实际项目中的非结构化数据。示例输入文本武夷路112号地块内有一栋三层办公楼占地约850平方米 总建筑面积2550平方米钢混结构屋顶为平屋面北侧临街 西侧紧邻小区围墙建成于2018年。期望输出{ address: 武夷路112号, building_type: 办公楼, floor_count: 3, land_area: 850, total_area: 2550, structure_type: 钢混, roof_type: 平屋面, orientation: 北侧临街、西侧紧邻小区围墙, build_year: 2018 }6.2 强制JSON输出Ollama提供了一个format参数将其设置为json可以让模型偏向输出JSON结构。虽然它不是万能保险但能显著降低格式错误率。# 文件路径src/building_extract.py import requests import json OLLAMA_URL http://localhost:11434/api/chat MODEL_NAME qwen2.5:7b def chat_json(model: str, user_prompt: str, system_prompt: str ) - dict: payload { model: model, messages: [ {role: system, content: system_prompt}, {role: user, content: user_prompt} ], stream: False, format: json } resp requests.post(OLLAMA_URL, jsonpayload, timeout120) resp.raise_for_status() text resp.json()[message][content] return json.loads(text) def extract_building_attrs(text: str) - dict: system_prompt ( 你是城市规划领域的文本抽取助手。 你只能输出JSON对象不能输出任何解释性文字。 ) user_prompt f 从下面的建筑描述文本中抽取字段 - address建筑地址 - building_type建筑类型 - floor_count层数 - land_area占地面积数字 - total_area总建筑面积数字 - structure_type结构类型 - roof_type屋顶类型 - orientation朝向和周边关系 - build_year建成年份数字 文本 {text} 请输出JSON对象字段名严格使用英文名。 return chat_json(MODEL_NAME, user_prompt, system_prompt) if __name__ __main__: sample ( 武夷路112号地块内有一栋三层办公楼占地约850平方米 总建筑面积2550平方米钢混结构屋顶为平屋面北侧临街 西侧紧邻小区围墙建成于2018年。 ) result extract_building_attrs(sample) print(json.dumps(result, ensure_asciiFalse, indent2))这里有两个关键点。第一system_prompt明确限制“只能输出JSON对象”减少模型闲聊概率。第二format参数设置为json让Ollama在采样时更偏向JSON结构。如果某个版本的Ollama对format支持不理想把这一行去掉或改回普通调用即可但解析失败率会高一些。6.3 运行与验证运行方式与第一个示例一致python src/building_extract.py如果一切正常会得到与期望结构一致的JSON对象。需要注意模型输出的数字可能是字符串比如floor_count: 3而不是3这种类型问题需要在实际项目中做一次统一清洗。可以参考下面这段# 数值字段统一转换 for k in [floor_count, land_area, total_area, build_year]: if k in result and isinstance(result[k], str): try: result[k] int(result[k]) except ValueError: pass这个细节容易被忽视但字段类型是否一致直接决定下游数据库写入是否顺畅。7. 第三个完整示例批量抽取与结果落库7.1 批量任务的关键问题单条抽取跑通之后下一步就是批量处理。批量场景下有几个问题必须提前考虑并发控制、失败重试、中间结果保存。本地模型推理虽然便宜但不是无限并发。如果同时启动几十个请求压向Ollama显存和CPU都会被打满反而拖慢整体速度。更稳妥的做法是控制并发数逐条或小批量提交。另外单条文本如果超出模型上下文窗口或者触发了模型幻觉可能导致返回内容无法解析这时需要重试机制。7.2 完整脚本下面这个脚本演示如何批量读取一个JSONLines文件逐条调用抽取接口并把结果写到输出文件。它还包含简单的失败重试和每两条打印一次进度。# 文件路径src/batch_extract.py import requests import json import time from pathlib import Path OLLAMA_URL http://localhost:11434/api/chat MODEL_NAME qwen2.5:7b MAX_RETRY 3 def chat_json(model: str, user_prompt: str, system_prompt: str ) - dict: payload { model: model, messages: [ {role: system, content: system_prompt}, {role: user, content: user_prompt} ], stream: False, format: json } resp requests.post(OLLAMA_URL, jsonpayload, timeout120) resp.raise_for_status() return json.loads(resp.json()[message][content]) def extract_from_text(text: str) - dict: system_prompt 你是信息抽取助手只输出JSON对象。 user_prompt f 从下面文本中抽取建筑属性字段 address, building_type, floor_count, land_area, total_area, structure_type, roof_type, orientation, build_year 文本 {text} 输出JSON对象。 return chat_json(MODEL_NAME, user_prompt, system_prompt) def process_file(input_path: str, output_path: str): in_file Path(input_path) out_file Path(output_path) results [] with in_file.open(r, encodingutf-8) as f: lines [line.strip() for line in f if line.strip()] for i, line in enumerate(lines): record json.loads(line) text record.get(text, ) data None for attempt in range(MAX_RETRY): try: data extract_from_text(text) break except Exception as e: print(f第{i}条第{attempt 1}次尝试失败{e}) time.sleep(2 ** attempt) if data is None: data {error: extract_failed} result_item {id: record.get(id, i), text: text, extracted: data} results.append(result_item) if (i 1) % 2 0: print(f已处理 {i 1}/{len(lines)} 条) with out_file.open(w, encodingutf-8) as f: for item in results: f.write(json.dumps(item, ensure_asciiFalse) \n) print(f处理完成共 {len(results)} 条结果写入 {out_file}) if __name__ __main__: process_file(data/input.jsonl, data/output.jsonl)这段脚本里重试逻辑是核心。每次失败后等待时间递增避免在服务短暂过载时继续硬冲冲。输出文件用JSONLines格式每行一条记录方便后续单条回溯。7.3 运行与验证准备一个最小输入文件data/input.jsonl{id: 0, text: 武夷路112号地块内有一栋三层办公楼占地约850平方米总建筑面积2550平方米钢混结构屋顶为平屋面北侧临街建成于2018年。} {id: 1, text: 中山北路800弄内有一栋六层住宅楼占地约1200平方米总建筑面积7200平方米砖混结构屋顶为坡屋面建于2005年。}然后运行python src/batch_extract.py如果一切顺利data/output.jsonl里会看到每条记录都有对应的extracted对象。判断批量任务成功的标准不是“全部成功”而是“失败是否可追踪”。即使某几条抽取失败output里也应该有error字段方便后续单独补跑而不是在日志里白屏消失。8. 如何做一次有效的模型对决“Local models head to head for extraction”这个标题最终要落到一个实际问题你本地同时有几个模型候选怎么公平对比选出一个投入生产8.1 定义评测样本和指标没有人会反对“用测试集说话”但很多对比翻车就翻在评测集太随意。比较靠谱的做法是准备三类数据第一类是标准用例覆盖业务中最常见的几种表达方式。第二类是边界用例比如文本里字段缺失、单位不一致、简称混用。第三类是错误用例比如文本里包含干扰信息模型不应抽取的字段不能乱造。对比指标不需要太学术对抽取任务来说三个指标就够指标含义计算方式字段级准确率所有期望字段中抽对的占比正确字段数 / 总字段数JSON解析成功率模型输出能被正常解析的比例可解析条数 / 总条数无效抽取率抽出了不该抽的值或凭空捏造字段无效字段条数 / 总条数不要只看第一个指标。一个模型可能字段准确率很高但经常输出格式错误照样无法直接进生产流程。JSON解析成功率反映的是模型对指令的服从性几乎同等重要。8.2 自动化对比脚本可以写一个简单的对比脚本对同一组测试样本循环跑多个模型并把结果汇总成表格。# 文件路径src/model_compare.py import requests import json OLLAMA_URL http://localhost:11434/api/chat TEST_CASES [ { text: 武夷路112号地块内有一栋三层办公楼占地约850平方米总建筑面积2550平方米钢混结构。, expected: {address: 武夷路112号, floor_count: 3, land_area: 850} }, { text: 该项目包含一栋两层的沿街商铺占地300平方米总建筑面积600平方米框架结构。, expected: {address: , floor_count: 2, land_area: 300} } ] def run_model(model: str, user_prompt: str) - str: payload { model: model, messages: [{role: user, content: user_prompt}], stream: False } resp requests.post(OLLAMA_URL, jsonpayload, timeout120) resp.raise_for_status() return resp.json()[message][content] def build_prompt(text: str) - str: return f从文本中抽取字段address, floor_count, land_area。 只输出JSON对象。 文本{text} def evaluate_model(model: str): parse_ok 0 field_correct 0 field_total 0 for case in TEST_CASES: raw run_model(model, build_prompt(case[text])) try: data json.loads(raw) parse_ok 1 except json.JSONDecodeError: data {} for k, v in case[expected].items(): field_total 1 if k in data: if str(data[k]).strip() str(v).strip(): field_correct 1 parse_rate parse_ok / len(TEST_CASES) field_acc field_correct / field_total if field_total else 0 print(f模型 {model}: JSON解析率{parse_rate:.2%}, 字段准确率{field_acc:.2%}) if __name__ __main__: for model in [qwen2.5:7b, llama3.1:8b]: evaluate_model(model)这个脚本是演示性质实际评测样本应扩充到几十条甚至上百条覆盖前面说的三类数据。跑完后把结果和失败case拿出来看比任何凭感觉的结论都有说服力。8.3 结果解读的三个陷阱第一个陷阱是只看平均分。字段准确率平均很高不代表边界case表现也好。要单独看“字段缺失”“单位不一致”这类困难样本上的表现因为生产环境最常见的返工恰恰来自这些case。第二个陷阱是忽略格式稳定性。模型A字段准确率比模型B高3个百分点但B每次都能稳定输出JSONA偶尔会输出解释性文字导致下游解析失败。在自动化流水线里B往往更适合生产。第三个陷阱是忽略输入文本长度。有些模型在短文本上表现很好一旦文本长度接近1500字就开始漏字段或幻觉。做对比时一定要包含长文本样本否则上线后会猝不及防。9. 常见问题与排查思路本地模型抽取的坑不少这里列几个高频问题问题现象可能原因排查方式解决方案启动失败端口被占用或服务未启动检查Ollama服务状态和11434端口重启服务调整端口配置模型加载慢首次加载需要载入权重观察日志是否在加载模型文件等待加载完成或提前预热模型输出不是JSON模型版本或提示词约束不足查看原始返回内容确认格式增强system_prompt使用format参数或做后处理解析字段经常漏抽文本太长或语义模糊单独测试长文本样本打印完整输出分块处理增强提示词示例或尝试更大模型抽取速度慢硬件不满足并发太高观察GPU利用率和推理耗时降低并发升级硬件或使用量化模型批量任务中途失败单次请求超时或服务过载查看错误日志确认是哪一条文本失败增加重试机制和超时时间降低并发数同一文本结果不稳定采样温度过高检查推理参数温度默认值把temperature调低至0.1到0.3之间其中一个容易被忽略的点是temperature。抽取任务期望结果稳定temperature应该调低而不是使用默认值偏高的配置。Ollama的API支持temperature参数建议在payload里显式加上payload { model: model, messages: messages, stream: False, options: { temperature: 0.2, top_p: 0.9 } }把temperature调到0.2左右可以在不损失太多表现力的情况下显著降低输出随机性。如果业务允许也可以直接调成0追求完全确定性——但要注意某些模型在temperature为0时反而可能出现重复输出需要实际验证。10. 最佳实践与工程建议10.1 提示词模板管理抽取任务的提示词不是写一次就完了它会随着业务字段调整频繁变化。建议把提示词模板当作代码管理不要散落在Python字符串里。可以把模板组织成独立文件或者至少把system_prompt和user_prompt的构造逻辑集中在一个模块里。模板里最好包含一到两个few-shot示例尤其是当字段含义不直观时。模型在示例中能学到“什么样的值该抽取什么样的值该忽略”这比单纯描述规则更有效。10.2 输出校验与兜底策略生产环境里模型输出必须经过一道校验层。校验逻辑包括JSON能否解析、必填字段是否存在、字段类型是否正确、枚举值是否在允许范围内。校验失败时至少要有三种兜底策略中的一种重试一次、降级到规则抽取、人工审核队列。不要相信模型输出直接入库。特别是字段类型问题模型可能把“3层”抽成“3层”而不是数字3也可能把“850平方米”抽成“850平方米”而不是850。这类问题在批量处理时很常见必须用清洗逻辑统一处理。10.3 性能与成本平衡批量抽取的吞吐量取决于硬件。如果发现并发过高导致服务不稳定不要一味加并发先观察GPU利用率和平均延迟。一个相对稳妥的做法是进入批量任务前先做小规模压测找到合适的并发数。文本长度也很重要。输入越长推理耗时越高。如果文本中存在大量与抽取目标无关的段落可以在送入模型前做一次预处理裁剪减少无效计算。这在实际项目中往往比换模型更有效。10.4 安全边界与规范操作本地部署不等于没有安全要求。以下几条值得注意模型服务端口不要直接暴露到公网生产环境应位于内网并配置访问控制调用模型服务的账号遵循最小权限原则输入文本如果包含个人敏感信息在处理链路中要做好脱敏和日志控制任何涉及生产数据的批量脚本先在测试环境用脱敏数据或样本数据验证再上真实数据。另外本地模型依赖开源权重使用前应确认模型许可证和商用条件是否满足团队业务。不要在项目上线后才去翻用户协议那时可能已经踩坑。11. 总结本地模型做抽取任务核心价值在于可控数据不出域、成本可预测、提示词迭代速度快。它不是云端API的完美替代品但对数据敏感、批量大、字段经常调整的团队来说是一条值得投入的路线。文章从通用信息抽取、建筑足迹属性抽取到批量落库完整跑通了一条“部署模型 → 编写抽取函数 → 批量处理 → 结果评测”的路径。三个示例覆盖了单条调用、JSON约束输出、批量重试等实际工程中真正会用到的能力。下一步建议你先做两件事第一用自己业务中20到30条真实样本跑一遍通用抽取示例感受本地模型在具体字段上的表现第二按第8章的思路构建一个最小评测集把候选模型和参数配置固定下来形成自己的对比基线。只有当你有了属于自己的测试集和评测流程后续调模型、换模型、调提示词才有据可依。本地模型抽取这条路不难走但需要耐心把工程细节打磨到位。从最小示例开始逐步补上校验、重试、评测这些生产环节你会发现它完全能承担真实业务的一部分工作。