热门搜索:和平精英 原神 街篮2 

您的位置:首页 > > 教程攻略 > ai资讯 >代码 | 使用本地大模型从文本中提取结构化信息

代码 | 使用本地大模型从文本中提取结构化信息

来源:互联网 更新时间:2026-08-15 14:30

先说个场景:手头积压了一堆电子发片PDF,想找个法子自动把它们的关键信息扒下来。比如,从一张发片里,我们希望能提取出类似这样的结构化数据:开票日期、应税货物名称、价税合计(大写)、税率、备注。说白了,就是要让AI学会“看”发片。

一、需求

现在手头有很多个电子发片PDF文件,目标很明确——用自动化工具帮我们批量提取出格式化的发片信息。举个例子,从一张发片里,我们希望得到这样一份字典数据:

DICT_DATA = {
"开票日期": "2023年01月06日",
"应税货物(或服务)名称": "*信息技术服务*技术服务费",
"价税合计(大写)": "",
"税率": "6%",
"备注": "230106163474406331"
}

这活儿如果人工做,几百张发片下来,眼睛得花。下面直接上方案。

二、准备工作

2.1 安装ollama

先到官网

https://ollama.com/

下载ollama软件,支持Windows、Mac、Linux三大平台,安装过程很省心。

2.2 下载大模型

ollama目前支持的主流模型不少,像阿里的qwen、qwen2,Meta的llama3等等。以llama3为例,根据自己电脑的显存性能选择对应版本。如果拿不准选哪个,那就先下个试试,不合适再删,反正折腾的成本不大。

打开命令行(Windows是cmd,Mac是terminal),确保网络畅通,执行下载命令:

ollama run llama3

稍等片刻,等

llama3:8b

下载完成就行。

2.3 安装python包

要在Python中调用ollama服务,需要装一个配套的包。命令行里执行:

pip3 install ollama

2.4 启动ollama服务

在Python调用之前,得先把本地ollama服务跑起来。命令行里执行:

ollama serve

如果看到类似下面的日志输出,说明服务已经成功启动,默认监听在127.0.0.1:11434端口:

2024/06/14 14:52:24 routes.go:1011: INFO server config env="map[OLLAMA_DEBUG:false ... OLLAMA_HOST:http://127.0.0.1:11434 ...]"
time=2024-06-14T14:52:24.742+08:00 level=INFO source=images.go:725 msg="total blobs: 18"
time=2024-06-14T14:52:24.742+08:00 level=INFO source=images.go:732 msg="total unused blobs removed: 0"
time=2024-06-14T14:52:24.743+08:00 level=INFO source=routes.go:1057 msg="Listening on 127.0.0.1:11434 (version 0.1.44)"
...
time=2024-06-14T14:52:24.796+08:00 level=INFO source=types.go:71 msg="inference compute" id=0 library=metal compute="" driver=0.0 name="" total="72.0 GiB" a vailable="72.0 GiB"

三、实验

3.1 读取pdf

先拿一张发片PDF试试手。用cntext库先读入文本:

import cntext as ct

text = ct.read_pdf('data/1.pdf')
print(ct.__version__)
text

输出结果:

2.1.2

' 机器编号:北京增值税电子普通发片发片代码:n发片号码:n开票日期:2023年01月06日n校 验 码:n购n买n方名 称: 哈尔滨所以然信息技术有限公司n密n码n区030898/5<32>*/0*440/63+79*08n纳税人识别号:91230109MABT7KBC4M /<54<1*6+49<-*+*>7<-8*04<+01n地 址、电 话:68+160026-45904*2<+3+15503>2n开户行及账号:98*2/*-*480145+-19*0917-1*61n货物或应税劳务、服务名称 规格型号 单 位 数 量 单 价 金 额 税率 税 额n*信息技术服务*技术服务费 1248.113208 248.11 6% 14.89n合 计 ¥248.11 ¥14.89n价税合计(大写)n 贰佰陆拾叁元整 (小写)¥263.00n销n售n方名 称: 北京n备 注230106163474406331n纳税人识别号:n地 址、电 话: n开户行及账号: n销售方:(章)'

可以看到,原始PDF读出来的文本比较杂乱,信息散布在各处,这正好是发挥大模型语义理解能力的地方。

3.2 提取信息

我们选用llama3:8b模型,然后设计一个提示词。实验里用的提示如:

“提取TEXT中的关键信息,返回DICT_DATA,DICT_DATA为dict数据格式,所含关键词依次为"开票日期", "应税货物(或服务)名称", "价税合计(大写)", "税率", "备注"; 结果只显示DICT_DATA。”

实际调用代码:

import ollama

response = ollama.chat(model='llama3:8b', messages=[
{
'role': 'user',
'content': f'提取TEXT中的关键信息,返回DICT_DATA, DICT_DATA为dict数据格式,所含关键词依次为"开票日期", "应税货物(或服务)名称", "价税合计(大写)", "税率", "备注"; 结果只显示DICT_DATA。TEXT: {text1}',
},
])

result = response['message']['content']
result

运行结果:

'DICT_DATA = {n    "开票日期": "2023年01月06日",n      "应税货物(或服务)名称": "*信息技术服务*技术服务费",n    "价税合计(大写)": "",n    "税率": "6%",n    "备注": "230106163474406331"n}'

从结果看,大模型准确提取到了我们需要的信息,耗时大约10秒。不过有一点要注意:有时大模型会返回带多余解释的文本,比如:

'Here is the extracted key information in dictionary format:\n\n```\n{\n    "开票日期": "2023年01月06日",\n      "应税货物(或服务)名称": "*信息技术服务*技术服务费",\n    "价税合计(大写)": "贰佰陆拾叁元整",\n    "税率": "6%",\n    "备注": "230106163474406331"\n}\n```\n\nLet me know if you ha ve any further requests! ?'

所以需要做一步后处理,把真正的字典部分从回答中提取出来:

import re

result = response['message']['content']
result = [r for r in re.split('```|DICT_DATA = ', result) if '{' in r][0]

print(type(eval(result)))
print(eval(result))

输出:


{'开票日期': '2023年01月06日',
'应税货物(或服务)名称': '*信息技术服务*技术服务费',
'价税合计(大写)': '贰佰陆拾叁元整',
'税率': '6%',
'备注': '230106163474406331'}

3.3 封装成函数extract_info

实验跑通了,下一步就是把流程封装成通用函数:

import ollama
import re

def extract_info(text):
response = ollama.chat(model='llama3:8b', stream=False, messages=[
{
'role': 'user',
'content': f'提取TEXT中的关键信息,返回DICT_DATA, DICT_DATA为dict数据格式,所含关键词依次为"开票日期", "应税货物(或服务)名称", "价税合计(大写)", "税率", "备注"; 结果只显示DICT_DATA。TEXT: {text}',
},
])

result = response['message']['content']
result = [r for r in re.split('```|DICT_DATA = ', result) if '{' in r][0]
return eval(result)

result = extract_info(text)
result

运行结果:

{'开票日期': '2023 02 14',
'应税货物(或服务)名称': '*家用厨房电器具*米家 小米电热水 MJDSH03YM',
'价税合计(大写)': '壹佰贰拾叁圆玖角玖分',
'税率': '13%',
'备注': None}

3.4 批量提取

假设data文件夹里躺着成百上千张发片(虽然本例只有一张),批量提取并保存为csv文件:

%%time

import os
import cntext as ct
import pandas as pd

#获取data内所有pdf的路径
pdf_files = [f'data/{file}' for file in os.listdir('data') if '.pdf' in file]

dict_datas = []
for pdf_file in pdf_files:
pdf_text = ct.read_pdf(pdf_file)
dict_data = extract_info(pdf_text)
dict_datas.append(dict_data)

df = pd.DataFrame(dict_datas)
df

运行结果:

CPU times: user 32 ms, sys: 2.17 ms, total: 15.2 ms
Wall time: 3.8 s

四、讨论

必须得说,本文只用了一张发片做实验,实际跑起来准确率可没这么高。最容易出错的字段是销售方纳税识别号(案例中没有展示这个字段的识别),问题出在ct.read_pdf读出来的文本比较杂乱,对大模型的语义理解是个不小的挑战。好在现在的大模型已经支持文本、图片、音频、视频甚至网址输入,所以这个问题在不久的将来应该能迎刃而解。

另外一点需要留意:大模型对每个输入给出的是概率最大的回答,所以提取数据时存在一定的错误识别风险。要降低这个风险,尽量选那些特征特别特殊、显眼的信息。比如价税合计(大写),因为它用的是中文大写数字,在所有文本中最为醒目、最特别,大模型在处理这类信息时会下意识地给更高权重,回答的准确率自然就上来了。

关于宇宙的好的网名有哪些
关于宇宙的好的网名有哪些

类型:角色扮演

大小:1

语言:简体中文

平台:互联网

游戏下载

热门手游

手机号码测吉凶
本站所有软件,都由网友上传,如有侵犯你的版权,请发邮件haolingcc@hotmail.com 联系删除。 版权所有 Copyright@2012-2013 haoling.cc