https://www.bilibili.com/video/BV1CL6MYKEGd/?vd_source=c47fbb8166930edc486d8fdc405bf569
(项目作者:BannyLon)

BillPic2Web—AI智读票据,它能够实现票据图片的自动解析并生成网页。该AI应用支持用户上传票据图片并选定票据类型。系统首先校验用户所选类型与模型识别图片所得类型是否一致。若一致,应用将自动识别票据内容,并将其转化为可预览的HTML网页;若不一致,则提示用户确认类型后重试。简而言之,BillPic2Web能快速将票据图片转换成可视化的HTML页面,提升工作效率与便捷性。它集成了票据类型识别、内容提取及HTML生成等功能,旨在为用户提供全面的票据数字化解决方案。

使用指南

1、下载文件夹bBillPic2Web到本地任意目录;
2、在BillPic2Web文件夹上右键单击,选择“服务——新建位于文件夹位置的终端窗口“;
3、在打开的终端窗口中输入执行flask服务命令:Python invoice.py
4、运行dify,在dify中导入 “Dify AI 应用:BillPic2Web.yml” DSL文件:在打开的工作流中修改LLM节点模型,以及修改HTTP请求节点的get请求的URL。

silent=True

data = request.get_json(silent=True) # 使用silent=True防止无效请求报错!!!这点可以需学习

代码解析

from flask import Flask, request, jsonify, send_from_directory
import os
import uuid
import shutil
import time
import logging

app = Flask(__name__)

# 配置日志
logging.basicConfig(level=logging.DEBUG)
logger = logging.getLogger(__name__)

STATIC_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'data')
if not os.path.exists(STATIC_DIR):# DATA_DIR是否存在
    os.makedirs(STATIC_DIR)# 创建路径
logging.info(f'DATA_DIR的路径:{STATIC_DIR}')


@app.route('/invoice', methods=['POST'])
def receive_invoice():
    data = request.get_json(silent=True)  # 使用silent=True防止无效请求报错!!!这点可以需学习
    if not data:
        return jsonify({"error": "No JSON data provided"}), 400
    print(data)

    # 生成唯一的文件名
    file_name = f"{uuid.uuid4()}.html"
    file_path = os.path.join(STATIC_DIR, file_name)

    try:
        # 生成HTML内容
        app.logger.debug("Generating HTML content...")
        html_content = generate_html(data)

        # 确保generate_html返回了字符串
        if html_content is None or not isinstance(html_content, str):
            return jsonify({"error": "HTML content generation failed"}), 500

        # 写入文件,写成html
        app.logger.debug("Writing HTML content to file...")
        with open(file_path, 'w') as file:
            file.write(html_content)

        # 生成完整的预览链接
        base_url = request.host_url.rstrip('/')
        preview_url = f"{base_url}/static/{file_name}"
        app.logger.debug(f"Generated file: {file_name}")

        # 构建完整的响应消息
        response_message = f"文件已保存\n预览链接:{preview_url}"
        return jsonify({"message": response_message}), 200
    except Exception as e:
        app.logger.error(f"An error occurred: {e}")
        return jsonify({"error": str(e)}), 500  # 使用标准的500状态码

@app.route('/preview/<path:filename>')
def preview(filename):
    return send_from_directory(STATIC_DIR, filename)


# 处理字典类型值
# 处理列表类型值
# 处理普通值

def generate_html(data):
    # 生成HTML内容的逻辑
    title = data.get('title', 'BillPic2Web')
    content = data.get('content', '- AI智读票据 自动生成网页 -')

    # 添加CSS引用 预留样式表引用位置(需确保项目中有 static/styles.css 文件)
    css_link = '<link rel="stylesheet" type="text/css" href="styles.css">'

    # 创建HTML模板
    html_content = f"""
<!DOCTYPE html>
<html>
<head>
    <title>{title}</title>
    {css_link}  <!-- 将CSS引用插入到<head>标签内 -->
</head>
<body>
    <h1>{title}</h1>
    <p class="special-p">{content}</p>

    <!-- 动态添加其他内容 -->
    <div>
    """

    # 动态添加其他内容
    for key, value in data.items():
        if key not in ['title', 'content']:
            if isinstance(value, dict):
                # 处理嵌套字典
                html_content += f"<p><strong>{key}:</strong></p>"
                for k, v in value.items():
                    if v:  # 只显示非空值
                        html_content += f"<p>&nbsp;&nbsp;&nbsp;{k}: {v}</p>"
            elif isinstance(value, list):
                # 处理列表
                html_content += f"<p><strong>{key}:</strong></p>"
                for index, item in enumerate(value):
                    if isinstance(item, dict):
                        for k, v in item.items():
                            if v:  # 只显示非空值
                                html_content += f"<p>&nbsp;&nbsp;&nbsp;{k}: {v}</p>"
                    else:
                        html_content += f"<p>&nbsp;&nbsp;&nbsp;{index + 1}. {item}</p>"
            else:
                if value:  # 只显示非空值
                    html_content += f"<p><strong>{key}:</strong> {value}</p>"

    # 结束HTML模板
    html_content += """
    </div>
</body>
</html>
"""

    return html_content

if __name__ == '__main__':
    # 启动Flask应用,绑定到所有网络接口
    app.run(host='192.168.122.2', port=8805,debug=True)

Dify流程

首先上传图片

在这里插入图片描述

变量赋值

要赋值的变量
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

识别票据

你是一位专业的发票识别专家。您的专长包括发票类型识别、图像分析及文字识别。凭借多年处理各类发票和票据的经验,您具备精准识别不同类型发票特征的能力。

目标是根据用户上传的发票图像准确识别发票类型,并返回对应的发票类型名称。

规则如下:

仔细分析发票上的所有视觉和文字信息。

只返回指定的发票类型名称,不做其他解释。

如果无法确定发票类型,返回 "无法识别"。

工作流程:

接收用户上传的发票图像。

分析图像中的关键信息和特征。

对比不同类型发票的特征。

确定发票类型。

返回对应的类型名称。

请根据图片内容识别票据类型,并从以下列表中选择一个最匹配的类型进行输出:

增值税电子普通发票;特征为电子版式,有"增值税电子普通发票"字样,含二维码,有密码区,有"税局监制"字样。

全电发票;特征为电子版式,有"电子发票(增值税专用发票)""电子发票(普通发票)"字样,发票号码长度有20位。

增值税普通发票(卷票);特征为纸质卷式,较窄,有"增值税普通发票(卷票)发票联"字样,通常为红色或蓝色。

定额发票;特征为小型纸质票据,预先印制金额,通常用于小额交易。

电子发票(铁路电子客票);特征为电子版式,有"电子发票(铁路电子客票)"标志,包含乘车日期、车次、座位等信息,有发票号码,发票号码长度20位。

如果图像模糊,无法辨识关键信息,请输出 "无法识别"。

请仅输出票据类型名称,不要添加任何额外的信息。

分类型识别之后LLM

在这里插入图片描述

变量聚合器

可以有这个
在这里插入图片描述
在这里插入图片描述

是我图片的问题嘛,就是识别不出来
😔

Logo

技术共进,成长同行——讯飞AI开发者社区

更多推荐