65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 Fusion 开发来升级 AI 应用(第 3 部分):使用 AI 处理的表单数据

emptyStarIconemptyStarIconemptyStarIconemptyStarIconemptyStarIcon

0/5 (0投票)

2022年5月9日

CPOL

7分钟阅读

viewsIcon

5242

downloadIcon

57

在本篇文章中,我们将把表单识别器 (Form Recognizer) 的结果发送回 Dataverse,以便在我们的 Power App 中使用。

在前两篇文章中,我们设置了一个 Power Apps 应用程序,用于将图像上传到 Dataverse 数据库。利用 Azure Event Hub、Functions 和 Form Recognizer,我们使用 OCR 技术从图像中提取了文本。设置 AI 来帮助会计部门节省时间的过程非常轻松。

在这三部分系列的最后一篇文章中,我们将把提取的数据写入 Dataverse,以便在我们的 Power Apps 应用程序中使用。我们还将把数据发送到 SQL 数据库,以便组织内的其他应用程序可以使用。

创建 Dataverse 详细信息表

在将表单识别器的数据写入 Dataverse 之前,我们需要创建一个新表来存储提取的数据。因此,请转到 Dataverse 并创建一个新表。将其命名为“FormDetail”(表单详细信息),其他设置保持默认。

表准备好后,添加两个额外的列。将第一个列命名为“TextData”,将其**数据类型**设置为“Text”,设为必填,并在**高级选项**中将长度编辑为 1,000。

第二个列略有不同,因为它将把我们的“Form”(表单)表链接到“FormDetail”(表单详细信息)表。这样,我们就知道哪些详细信息属于哪个表单。

将该列命名为“Form”(表单),因为它将存储对表单的链接。选择“Lookup”(查找)作为**数据类型**,这将使**相关表**字段可见。选择“Form”(表单)作为**相关表**。另外,将该列设为必填。

创建列后,保存您的表,然后返回到表概述。

写回 Dataverse

写回 Dataverse——尤其是连接表单和表单详细信息——可能具有挑战性。

我们需要 POST 一个对象,其中包含来自 Dataverse 的属性及其对应的值。这样做很简单,除了 Form 属性,它是一个查找。我们需要以 [property name]@odata.bind 的形式发布此属性。由于这在 C# 中不是一个有效的属性名,我们需要手动创建 JSON 或使用 Dictionary<string, object> 来生成 JSON。我们将采用后一种方法。

我们现在可以遍历表单识别器中的行,逐个插入。由于我们还不知道所有文本的含义,我们将仅将文本用作名称和值。@odata.bind 很棘手,因为 Form 属性必须以大写 F 开头,与我们迄今为止所做的其他所有内容都不同。

将此代码放在您的应用程序代码中

foreach (var value in result.Value)
{
    foreach (var line in value.Lines)
    {
        var postResult = await client.PostAsJsonAsync($"{prefix}_{detailsTableName}", new List<object>
        {
            new Dictionary<string, object>
            {
                { $"{prefix}_name", line.Text },
                { $"{prefix}_textdata", line.Text },
                { $"{prefix}_Form@odata.bind", $"/{prefix}_{tableName}({primaryEntityId})" }
            }
        });
        postResult.EnsureSuccessStatusCode();
    }
}

由于我们已经从 Dataverse 获取了数据,我们可以重用 HTTP 客户端。我们已经有了访问权限,所以除了大写的 F 之外,这里没有什么特别的。

在 Power Apps 中显示数据

接下来,我们将在 Power Apps 中显示数据。

转到您的 Power App 设计器并打开详细信息屏幕。在顶部的功能区栏中,转到**插入**,然后添加一个垂直库。将库拖到表单底部,在图像下方。

之后,我们需要设置库的源。您可以在顶部的公式字段或**高级属性**选项卡中的**项**字段中进行此操作。如果您检查 **DetailForm1** 的 **Item** 字段,您会看到“BrowserGallery1.Selected”,这是**浏览**屏幕的浏览器库中的选定项。我们将在新库中使用此项,因此将**项**字段设置为“BrowseGallery1.Selected.FormDetails”。

接下来,在**属性**中,将库布局更改为“标题和副标题”。在**字段**中,分别将 **name** 和 **text** 数据字段设置为“title”和“subtitle”。

当您运行您的 Function app 并上传发票图片(本文的源代码中提供了一个虚拟发票)后,稍作延迟,其文本应该会出现在您的表单中。

提取发票

不幸的是,提取的文本缺乏意义。让我们来解决这个问题。

我们可以训练 Form Recognizer 来识别特定表单上的特定值,例如身份证、发票和名片。Form Recognizer 有一些预训练的模型,支持英语和西班牙语。

更改您应用程序代码中的此行

var operation = await recognizer.StartRecognizeContentAsync(stream);

to

var operation = await recognizer.StartRecognizeInvoicesAsync(stream);

响应也会改变,所以我们需要稍微重写我们的 foreach 循环

foreach (var value in result.Value)
{
    foreach (var field in value.Fields)
    {
        var postResult = await client.PostAsJsonAsync($"{prefix}_{detailsTableName}", new List<object>
        {
            new Dictionary<string, object>
            {
                { $"{prefix}_name", field.Key },
                { $"{prefix}_textdata", field.Value.ValueData?.Text },
                { $"{prefix}_Form@odata.bind", $"/{prefix}_{tableName}({primaryEntityId})" }
            }
        });
        var resultContext = await postResult.Content.ReadAsStringAsync();
        postResult.EnsureSuccessStatusCode();
    }
}dw

我们现在有字段而不是行。字段有一个适合 Dataverse **Name** 字段的键。我们可以使用 field.Value.ValueData.Text 获取值。请注意,ValueData 可能为 null,因此我们在这里使用空传播运算符。

现在,如果我们上传同一张发票,我们就能获得有用的数据。

如截图所示,Form Recognizer 识别出了客户地址、发票日期、发票 ID 和总金额。其他字段包括小计和税金。

您可能需要清理数据,或者使用列而不是行来更新您的发票。但是,您可以根据需要使用这些有价值的数据。

现在您知道如何将数据写入 Dataverse 并在 Power App 中使用它了。

创建 Azure SQL 数据库

接下来,我们将把 Form Recognizer 的结果写入 Azure SQL 数据库。首先,我们需要创建数据库。

转到 Azure 门户并找到您的 SQL 数据库。创建一个新的数据库,并将其放入本系列中一直使用的资源组中。将数据库命名为“powerapps-db”。

您可能还需要创建一个新的 SQL Server。输入任何全局唯一的服务器名称,选择您的位置,然后输入用户名和密码。对于服务和计算层,请选择无服务器计划或基于 DTU 的基本层。另外,选择本地冗余备份存储。保留所有其他默认设置。然后,单击**创建**。

部署可能需要几分钟时间。

Azure 部署数据库后,转到您的 SQL Server,找到防火墙设置,并将您的客户端 IP 地址添加到允许的 IP 地址列表中。

接下来,转到 Azure 门户中的 SQL 数据库,找到其查询编辑器。您也可以使用 SQL Server Management Studio 中更强大的编辑器。使用您的用户名和密码登录,并使用以下查询创建两个表

CREATE TABLE dbo.Form
(
[Id] [int] IDENTITY(1,1) NOT NULL,
[Name] nvarchar NOT NULL,
[Base64Image] nvarchar NOT NULL,
CONSTRAINT [PK_Form] PRIMARY KEY CLUSTERED (Id)
)
GO

CREATE TABLE dbo.FormDetail
(
[Id] [int] IDENTITY(1,1) NOT NULL,
[Name] nvarchar NOT NULL,
[TextData] nvarchar NOT NULL,
[FormId] INT NOT NULL,
CONSTRAINT [PK_FormDetail] PRIMARY KEY CLUSTERED (Id)
)
GO

ALTER TABLE dbo.FormDetail WITH CHECK ADD CONSTRAINT [FK_FormDetail_Form] FOREIGN KEY(FormId)
REFERENCES dbo.Form (Id)
GO

现在我们可以从 Azure Function 写入这些表了。

写入 Azure SQL

写入 Azure SQL 有几种方法。我们将使用 Entity Framework (EF)。

首先,使用 NuGet 包管理器或 NuGet CLI 安装 Microsoft.EntityFrameworkCore.SqlServer NuGet 包。有工具可以根据现有数据库生成 EF 模型,您也可以选择代码优先数据库生成。但是,对于这个简单的示例,我们将直接在代码中编写数据库。为简单起见,我们将不注入 DbContext,而是将连接字符串直接粘贴到代码中。

您可以在 Azure SQL 数据库资源中找到您的连接字符串。不要忘记在字符串中输入您的密码。

将这些类添加到您的应用程序中

public class Form
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Base64Image { get; set; }
    public ICollection<FormDetail> FormDetails { get; set; }
}

public class FormDetail
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string TextData { get; set; }
    public int FormId { get; set; }
}

public class ApplicationDbContext : DbContext
{
    public DbSet<Form> Forms { get; set; }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder.UseSqlServer("<Your connection string>"
        base.OnConfiguring(optionsBuilder);
    }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);

        modelBuilder.Entity<Form>().ToTable(nameof(Form));
    }
}

现在保存到 Azure 很容易。

string name = JsonConvert.DeserializeObject<dynamic>(content)[$"{prefix}_name"];
var form = new Form
{
    Base64Image = image,
    Name = name,
    FormDetails = result.Value.SelectMany(v => v.Fields.Select(f => new FormDetail
    {
        Name = f.Key,
        TextData = f.Value.ValueData?.Text
    })).ToList()
};
context.Forms.Add(form);
await context.SaveChangesAsync();

我们将名称列添加到了 Dataverse OData GET $select 参数中,以便在此处使用。我们现在可以复制完整的表单以及我们刚刚提取的表单数据。

您可以通过转到 Azure 并在查询编辑器中运行 SELECT * FROM FormDetail 来测试数据是否已插入到您的数据库中。

GitHub 上查找完整的代码。

结论

融合开发提供了两全其美。

Power Apps 和 Dataverse 使公民开发者能够相对轻松地创建复杂的应用程序。同时,经验丰富的开发人员可以通过编程语言利用 Azure 平台的全部功能,而无需担心用户详细的前端需求。

在本系列中,我们创建了一个应用程序,允许用户使用 Power Apps 上传发票图片。然后,我们使用 Azure Form Recognizer 提取了有意义的信息。最后,我们将数据存储在 Dataverse 和 Azure SQL 数据库中,供我们的应用程序和其他应用程序访问。

我们假设的会计部门的公民开发者通过创建一个无代码应用程序来收集发票,从而快速获得了他们所需的标准功能。然后,我们假设的经验丰富的开发者介入,连接所有移动部件并利用 Azure 的 AI 功能,使应用程序更加健壮。

会计部门通过自动提取发票信息并将其保存在数据库中来节省时间。最重要的是,他们可以自行调整用户界面,以满足他们的需求。而且,如果将来需要更多功能,他们始终可以使用 Power Apps 添加这些功能。

Power Apps 特别适合融合开发。它使用 Microsoft Azure Cloud,使开发人员可以轻松连接和扩展 Power App,并利用 Azure 的众多解决方案,包括人工智能。 探索 Power Apps 和其他 Azure 云工具,以获得灵感并创建您自己的 AI 解决方案。

要详细了解如何构建结合 Power Apps 和 Azure 服务的复杂、功能齐全的解决方案,请查看电子书 使用 Power Apps 构建应用程序的融合开发方法

© . All rights reserved.