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

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

一、需求

现在有很多个电子发票PDF文件, 使用自动化工具帮我们批量自动从发票PDF提取出格式化信息。如从发票

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

提取出DICT_DATA

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

二、准备工作

2.1 安装ollama

点击前往网站 https://ollama.com/ ,下载ollama软件,支持win、Mac、linux

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

2.2 下载LLM

ollama软件目前支持多种大模型, 如阿里的(qwen、qwen2)、meta的(llama3),

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

以llama3为例,根据自己电脑显存性能, 选择适宜的版本。如果不知道选什么,那就试着安装,不合适不能用再删除即可。

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

打开电脑命令行cmd(mac是terminal), 网络是连网状态,执行模型下载(安装)命令

ollama run llama3  

等待 llama3:8b 下载完成。

2.3 安装python包

在python中调用ollama服务,需要ollama包。

打开电脑命令行cmd(mac是terminal), 网络是连网状态,执行安装命令

pip3 install ollama  

2.4 启动ollama服务

在Python中调用本地ollama服务,需要先启动本地ollama服务, 打开电脑命令行cmd(mac是terminal), 执行

ollama serve  

Run

2024/06/14 14:52:24 routes.go:1011: INFO server config env="map[OLLAMA_DEBUG:false OLLAMA_FLASH_ATTENTION:false OLLAMA_HOST:http://127.0.0.1:11434 OLLAMA_KEEP_ALIVE: OLLAMA_LLM_LIBRARY: OLLAMA_MAX_LOADED_MODELS:1 OLLAMA_MAX_QUEUE:512 OLLAMA_MAX_VRAM:0 OLLAMA_MODELS:/Users/deng/.ollama/models OLLAMA_NOHISTORY:false OLLAMA_NOPRUNE:false OLLAMA_NUM_PARALLEL:1 OLLAMA_ORIGINS:[http://localhost https://localhost http://localhost:* https://localhost:* http://127.0.0.1 https://127.0.0.1 http://127.0.0.1:* https://127.0.0.1:* http://0.0.0.0 https://0.0.0.0 http://0.0.0.0:* https://0.0.0.0:* app://* file://* tauri://*] OLLAMA_RUNNERS_DIR: OLLAMA_TMPDIR:]"  
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.744+08:00 level=INFO source=payload.go:30 msg="extracting embedded files" dir=/var/folders/y0/4gqxky0s2t94x1c1qhlwr6100000gn/T/ollama4239159529/runners  
time=2024-06-14T14:52:24.772+08:00 level=INFO source=payload.go:44 msg="Dynamic LLM libraries [metal]"  
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" available="72.0 GiB"  

cmd(mac是terminal)看到如上的信息,说明本地ollama服务已开启。

三、实验

3.1 读取pdf

www.zeeklog.com  - 代码 | 使用本地大模型从文本中提取结构化信息
import cntext as ct  
  
  
text = ct.read_pdf('data/1.pdf')  
print(ct.__version__)  
text  

Run

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

3.2 提取信息

使用ollama服务中的大模型 llama3:8b , 需要大模型提示信息及数据。这是我实验里设计的提示信息prompt

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

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  

Run

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

从运行结果看出, 大模型从发票PDF中准确提取到我们需要的信息,耗时大概10s。需要注意,有时候大模型还会返回

'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 have any further requests! 😊'  

现在我们需要将 DICT_DATA 变为真正的字典数据

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))  

Run

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

3.3 封装成函数extract_info

实验成功,我们将其封装为函数_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  

Run

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

3.4 批量提取

假设data文件夹内有成百上千的发票(实际上只有一张发票), 对data文件夹进行批量信息提取,结果存储为csv。

%%time  
  
import os  
#cntext版本为2.1.2,非开源,  
#需联系大邓372335839获取  
import cntext as ct  
import pandas as pd  
  
#当前代码所在的代码文件与data文件夹处于同一个文件夹内  
#获取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  

Run

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

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

四、讨论

本文只使用了一张发票进行实验, 实际上准确率没有这么高, 识别错误字段集中在销售方纳税识别号(案例没有展示销售方纳税识别号的识别)。原因主要是ct.read_pdf读入pdf时,文本比较杂乱。对大模型的语义理解有一定的挑战。目前大模型已经支持文本、图片、音频、视频、网址, 所以各位看官,不用等太久,就可克服此问题。

大模型会对每个输入,给出正确概率最大的回答,因此大模型提取数据时存在一定的错误识别风险。为降低该风险,尽量选择特别特殊、显眼,例如三张发票的价税合计(大写), 因为信息是特殊的中文大写数字, 在所有文本中是最醒目最特别的文本信息,这样大模型处理这类信息时会给这类信息尽可能高的权重,增大回答的准确率。

如何学习AI大模型?

作为一名热心肠的互联网老兵,我决定把宝贵的AI知识分享给大家。 至于能学习到多少就看你的学习毅力和能力了 。我已将重要的AI大模型资料包括AI大模型入门学习思维导图、精品AI大模型学习书籍手册、视频教程、实战学习等录播视频免费分享出来。

Read more

前端防范 XSS(跨站脚本攻击)

目录 一、防范措施 1.layui util  核心转义的特殊字符 示例 2.js-xss.js库 安装 1. Node.js 环境(npm/yarn) 2. 浏览器环境 核心 API 基础使用 1. 基础过滤(默认规则) 2. 自定义过滤规则 (1)允许特定标签 (2)允许特定属性 (3)自定义标签处理 (4)自定义属性处理 (5)转义特定字符 常见场景示例 1. 过滤用户输入的评论内容 2. 允许特定富文本标签(如富文本编辑器内容) 注意事项 更多配置 XSS(跨站脚本攻击)是一种常见的网络攻击手段,它允许攻击者将恶意脚本注入到其他用户的浏览器中。

详细教程:如何从前端查看调用接口、传参及返回结果(附带图片案例)

详细教程:如何从前端查看调用接口、传参及返回结果(附带图片案例)

目录 1. 打开浏览器开发者工具 2. 使用 Network 面板 3. 查看具体的API请求 a. Headers b. Payload c. Response d. Preview e. Timing 4. 实际操作步骤 5. 常见问题及解决方法 a. 无法看到API请求 b. 请求失败 c. 跨域问题(CORS) 作为一名后端工程师,理解前端如何调用接口、传递参数以及接收返回值是非常重要的。下面将详细介绍如何通过浏览器开发者工具(F12)查看和分析这些信息,并附带图片案例帮助你更好地理解。 1. 打开浏览器开发者工具 按下 F12 或右键点击页面选择“检查”可以打开浏览器的开发者工具。常用的浏览器如Chrome、Firefox等都内置了开发者工具。下面是我选择我的一篇文章,打开开发者工具进行演示。 2. 使用

Cursor+Codex隐藏技巧:用截图秒修前端Bug的保姆级教程(React/Chakra UI案例)

Cursor+Codex隐藏技巧:用截图秒修前端Bug的保姆级教程(React/Chakra UI案例) 前端开发中最令人头疼的莫过于那些难以定位的UI问题——元素错位、样式冲突、响应式失效...传统调试方式往往需要反复修改代码、刷新页面、检查元素。现在,通过Cursor编辑器集成的Codex功能,你可以直接用截图交互快速定位和修复这些问题。本文将带你从零开始,掌握这套革命性的调试工作流。 1. 环境准备与基础配置 在开始之前,确保你已经具备以下环境: * Cursor编辑器最新版(v2.5+) * Node.js 18.x及以上版本 * React 18项目(本文以Chakra UI 2.x为例) 首先在Cursor中安装Codex插件: 1. 点击左侧扩展图标 2. 搜索"Codex"并安装 3. 登录你的OpenAI账户(需要ChatGPT Plus订阅) 关键配置项: // 在项目根目录创建.