今天借助腾讯云大模型知识引擎原子能力提供的文档解析API快速提取图片信息为MD文档的WinFomr应用小案例,感兴趣的朋友可以看一下!
官方介绍:大模型知识引擎(LLM Knowledge Engine),是面向企业客户及合作伙伴的,基于大模型的应用构建平台,结合企业专属数据,更快更高效地搭建Agent、RAG、工作流等多种模式应用,推动大语言模型在企业中的应用落地。
大模型知识引擎 LKE: https://cloud.tencent.com/product/lke
点击【产品体验】按钮进入服务开通页面大概需要半分钟左右的时间,具体如下图:
开通成功之后如下图:
大模型知识引擎主要分为四个模块:
应用管理:个人创建的大模型应用管理主界面。如果没有创建应用的话,默认为创建界面。
原子能力:已API接口的方式提供给开发者自行构建大模型专属应用。主要包括多轮改写、Embedding、重排序、文档解析四大能力。
插件中心:通过插件能帮助知识引擎开发应用拓展功能,支持有开发能力者丰富应用内容,相当于是知识引擎应用能力的补充。
体验中心:基于知识引擎推出的最佳实践应用,大家可以基于推荐的应用创建为自己的应用,然后进行功能进一步丰富。
腾讯云2月8日上线DeepSeek-R1及V3原版模型API接口,依托腾讯云强大的公有云服务,为大家提供了稳定优质的接口调用服务。这里主要依靠腾讯云提供的API接口来实现。
使用技术:C#+VS2022+WinFrom
完整的案例流程如下图:
首先打开vs2022创建一个Winfrom项目
点击下一步输入项目名称【TDeepSeekChengYuDemo】,然后点击创建按钮。
空白项目创建之后效果如下图:
Nuget包管理器(推荐)
打开NuGet包管理器搜索”TencentCloudSDK.Lke“
然后点击安装即可。安装成功之后效果如下图:
命令行方式
打开程序包管理控制台输入如下命令:
dotnet add package TencentCloudSDK.Lke
然后新建一个工具类库ImageOCRUtils.cs用来调用大模型API接口,创建如下图:
主要代码逻辑
创建文档解析任务的方法
参考官方SDK示例进行封装方法如下:
/// <summary>
/// 第一步 创建文档解析任务
/// </summary>
/// <param name="imageUrl"></param>
/// <returns></returns>
public static string CreateImageOcrTask(string imageUrl)
{
try
{
// 密钥可前往官网控制台 https://console.cloud.tencent.com/cam/capi 进行获取
Credential cred = new Credential
{
SecretId = "",
SecretKey = ""
};
// 实例化一个client选项,可选的,没有特殊需求可以跳过
ClientProfile clientProfile = new ClientProfile();
// 实例化一个http选项,可选的,没有特殊需求可以跳过
HttpProfile httpProfile = new HttpProfile();
httpProfile.Endpoint = ("lke.tencentcloudapi.com");
clientProfile.HttpProfile = httpProfile;
// 实例化要请求产品的client对象,clientProfile是可选的
LkeClient client = new LkeClient(cred, "ap-guangzhou", clientProfile);
// 实例化一个请求对象,每个接口都会对应一个request对象
CreateReconstructDocumentFlowRequest req = new CreateReconstructDocumentFlowRequest();
req.FileUrl = imageUrl;
CreateReconstructDocumentFlowConfig createReconstructDocumentFlowConfig1 = new CreateReconstructDocumentFlowConfig();
createReconstructDocumentFlowConfig1.TableResultType = "1";
createReconstructDocumentFlowConfig1.ResultType = "0";
req.Config = createReconstructDocumentFlowConfig1;
// 返回的resp是一个CreateReconstructDocumentFlowResponse的实例,与请求对象对应
CreateReconstructDocumentFlowResponse resp = client.CreateReconstructDocumentFlowSync(req);
// 输出json格式的字符串回包
Console.WriteLine(AbstractModel.ToJsonString(resp));
return resp.TaskId;
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
return "-1";
}
}
输入参数引用官方文档
参数名称 | 必选 | 类型 | 描述 |
---|---|---|---|
Action | 是 | String | 公共参数,本接口取值:CreateReconstructDocumentFlow。 |
Version | 是 | String | 公共参数,本接口取值:2023-11-30。 |
Region | 是 | String | 公共参数,详见产品支持的 地域列表。 |
FileType | 否 | String | 文件类型。支持的文件类型:PDF、DOC、DOCX、PPT、PPTX、MD、TXT、XLS、XLSX、CSV、PNG、JPG、JPEG、BMP、GIF、WEBP、HEIC、EPS、ICNS、IM、PCX、PPM、TIFF、XBM、HEIF、JP2。示例值:PDF |
FileBase64 | 否 | String | 文件的 Base64 值。支持的文件大小:所下载文件经Base64编码后不超过 8M。文件下载时间不超过 3 秒。支持的图片像素:单边介于20-10000px之间。文件的 FileUrl、FileBase64 必须提供一个,如果都提供,只使用 FileUrl。 |
FileUrl | 否 | String | 文件的Url地址。文件下载时间不超过15秒。支持的图片像素:单边介于20-10000px之间。文件存储于腾讯云的Url可保障更高的下载速度和稳定性,建议文件存储于腾讯云。非腾讯云存储的 Url 速度和稳定性可能受一定影响。所下载文件经 Base64 编码后不超过支持的文件大小:文件类型支持的文件大小PDF200MDOC200MDOCX200MPPT200MPPTX200MMD10MTXT10MXLS20MXLSX20MCSV20MPNG20MJPG20MJPEG20MBMP20MGIF20MWEBP20MHEIC20MEPS20MICNS20MIM20MPCX20MPPM20MTIFF20MXBM20MHEIF20MJP220M |
FileStartPageNumber | 否 | Integer | 当传入文件类型为PDF、DOC、DOCX、PPT、PPTX,用来指定文件识别的起始页码,识别的页码包含当前值。默认为1,表示从文件的第1页开始识别。示例值:1 |
FileEndPageNumber | 否 | Integer | 当传入文件类型为PDF、DOC、DOCX、PPT、PPTX,用来指定文件识别的结束页码,识别的页码包含当前值。默认为100,表示识别到文件的第100页。单次调用最多支持识别1000页内容,即FileEndPageNumber-FileStartPageNumber需要不大于1000。示例值:100 |
Config | 否 | CreateReconstructDocumentFlowConfig | 创建文档解析任务配置信息。示例值:{"TableResultType":"1"} |
输出参数参考官方文档如下图:
正确返回参数json示例
{
"TaskId": "cf79a3db3a3446cea2f96a14439091f3",
"RequestId": "5a734b18-cfd4-43ad-851c-511fcc8bcb03"
}
查询文档解析结果逻辑
根据上一步获取的TaskId查询文档解析结果,返回值为文件URL,文件类型为压缩包,具体代码如下:
/ /// <summary>
/// 第二步 根据任务ID获取文档地址
/// </summary>
/// <param name="taskId"></param>
/// <returns></returns>
public static string GetResultDocumentUrl(string taskId)
{
try
{
// 密钥可前往官网控制台 https://console.cloud.tencent.com/cam/capi 进行获取
Credential cred = new Credential
{
SecretId = "",
SecretKey = ""
};
// 实例化一个client选项,可选的,没有特殊需求可以跳过
ClientProfile clientProfile = new ClientProfile();
// 实例化一个http选项,可选的,没有特殊需求可以跳过
HttpProfile httpProfile = new HttpProfile();
httpProfile.Endpoint = ("lke.tencentcloudapi.com");
clientProfile.HttpProfile = httpProfile;
// 实例化要请求产品的client对象,clientProfile是可选的
LkeClient client = new LkeClient(cred, "ap-guangzhou", clientProfile);
// 实例化一个请求对象,每个接口都会对应一个request对象
GetReconstructDocumentResultRequest req = new GetReconstructDocumentResultRequest();
req.TaskId = taskId;
// 返回的resp是一个GetReconstructDocumentResultResponse的实例,与请求对象对应
GetReconstructDocumentResultResponse resp = client.GetReconstructDocumentResultSync(req);
// 输出json格式的字符串回包
Console.WriteLine(AbstractModel.ToJsonString(resp));
return resp.DocumentRecognizeResultUrl;
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
return e.ToString();
}
}
输入参数,引用官方文档如下图:
输出参数,引用官方文档如下图:
特别注意:
正确返回json示例
{
"Status": "Success",
"DocumentRecognizeResultUrl": "https://document-restruction-prod-1258344699.cos.ap-guangzhou.myqcloud.com/doc_parse%2Foutput_files%2F2025-02-25%2Fcf79a3db3a3446cea2f96a14439091f3.zip?q-sign-algorithm=sha1&q-ak=AKIDlWFap6HLNbidLwPqOrAKGzXrx40scL7l&q-sign-time=1740465273%3B1740465873&q-key-time=1740465273%3B1740465873&q-header-list=host&q-url-param-list=&q-signature=e03d151f58f281cc743c9968f6ce449c32a82cc9",
"FailedPages": [
],
"RequestId": "e3cbb116-2650-4f09-ba7a-98c339360479"
}
第三步根据文档URL下载压缩包到本地
/// <summary>
/// 第三步 根据文档url下载文档识别后的ZIP
/// </summary>
/// <param name="fileUrl"></param>
public static string DownloadFile(string fileUrl)
{
// 获取当前时间
DateTime now = DateTime.Now;
// 格式化时间戳,确保文件名合法且不包含非法字符
string timestamp = now.ToString("yyyyMMdd_HHmmss_fff");
string filePath = @"D:\OCRTest\"+ timestamp+".zip"; // 文件保存路径
try
{
using (WebClient client = new WebClient())
{
// 下载文件到指定路径
client.DownloadFile(fileUrl, filePath);
return UnzipFile(filePath, timestamp);
}
}
catch (Exception ex)
{
MessageBox.Show($"下载失败: {ex.Message}");
return "-1";
}
}
说明:根据时间戳命名下载结果文件的Zip压缩包文件。
解压压缩包到指定目录,这里使用了SharpZipLib类库,大家直接使用nuget搜索安装即可。具体如下图:
解压压缩包主要是为了得到目录结构进行TreeView控件展示,主要代码如下:
/// <summary>
/// 第四步 解压zip 用来展示结果文件
/// </summary>
/// <param name="zipFilePath"></param>
/// <param name="destinationFolder"></param>
private static string UnzipFile(string zipFilePath,string fileName)
{
try
{
string destinationFolder = @"D:\OCRTest\"+ fileName;
// 确保目标文件夹存在
if (!Directory.Exists(destinationFolder))
{
Directory.CreateDirectory(destinationFolder);
}
// 解压ZIP文件到指定的目标文件夹
(new FastZip()).ExtractZip(zipFilePath,destinationFolder, "");
Console.WriteLine("解压完成!");
return destinationFolder;
}
catch (Exception ex)
{
Console.WriteLine($"解压过程中发生错误: {ex.Message}");
return "-1";
}
}
因为接口调用为异步调用为了方便快速实现分成了三个按钮:【创建文档解析任务】、【获取解析文件URL】、【获取解析结果】按照顺序点击进行解析结果的获取,界面效果如下图:
主要代码如下:
private void LoadFolderStructure(string folderPath)
{
// 清除现有的节点
treeView1.Nodes.Clear();
// 创建根节点
TreeNode rootNode = new TreeNode(new DirectoryInfo(folderPath).Name);
rootNode.Tag = folderPath; // 存储路径信息以便后续使用
rootNode.Expand();
treeView1.Nodes.Add(rootNode);
// 开始递归加载子文件夹
PopulateTreeView(rootNode, folderPath);
}
private void PopulateTreeView(TreeNode parentNode, string folderPath)
{
try
{
// 获取所有子文件夹
DirectoryInfo dirInfo = new DirectoryInfo(folderPath);
DirectoryInfo[] subDirs = dirInfo.GetDirectories();
foreach (DirectoryInfo dir in subDirs)
{
TreeNode node = new TreeNode(dir.Name);
node.Tag = dir.FullName; // 存储路径信息以便后续使用
parentNode.Nodes.Add(node);
// 递归调用以加载子文件夹
PopulateTreeView(node, dir.FullName);
node.Expand();
}
FileInfo[] files = dirInfo.GetFiles();
foreach (FileInfo file in files)
{
TreeNode fileNode = new TreeNode(file.Name);
fileNode.Tag = file.FullName;
fileNode.ImageIndex = 1; // 文件图标索引
fileNode.SelectedImageIndex = 1;
parentNode.Nodes.Add(fileNode);
}
}
catch (UnauthorizedAccessException ex)
{
MessageBox.Show($"访问被拒绝: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
catch (Exception ex)
{
MessageBox.Show($"发生错误: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void btnFirst_Click(object sender, EventArgs e)
{
if (string.IsNullOrWhiteSpace(txtFileUrl.Text))
{
MessageBox.Show("请输入需要解析的图片URL");
}
else
{
string taskId = ImageOCRUtils.CreateImageOcrTask(txtFileUrl.Text);
txtTaskId.Text = taskId;
}
}
private void btnResult_Click(object sender, EventArgs e)
{
string documentUrl = txtDocumentUrl.Text;
if (string.IsNullOrWhiteSpace(documentUrl))
{
MessageBox.Show("请先获取解析结果文档URL");
}
else
{
if (documentUrl == "-1")
{
MessageBox.Show("解析结果文档UR获取失败!");
}
else
{
string result = ImageOCRUtils.DownloadFile(documentUrl);
// 可以在窗体初始化时加载文件夹结构
LoadFolderStructure(result);
MessageBox.Show(result);
}
}
}
/// <summary>
/// 获取文档URL
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button1_Click(object sender, EventArgs e)
{
string taskId = txtTaskId.Text;
if (string.IsNullOrWhiteSpace(taskId))
{
MessageBox.Show("请先获取创建文档任务返回的TaskId");
}
else
{
if (taskId == "-1")
{
MessageBox.Show("TaskId获取失败!");
}
else
{
string documentUrl = ImageOCRUtils.GetResultDocumentUrl(taskId);
txtDocumentUrl.Text = documentUrl;
}
}
}
说明:主要包括按钮点击事件和加载解析结果的树形结构逻辑。
这里选择我之前文章的一个图片(主要是DeepSeek-R1模型介绍的图片)进行解析,图片如下:
具体调用最终效果
说明:需要按钮步骤进行文档解析结果。
我们打开解析后的MarkDown文档查看解析的实际效果
文档结构如下:
接着使用Typoa进行打开效果如下:
整体解析的效果还是非常棒的。并且生成的MD文件进行了段落比较合理的分组。
以上是基于腾讯云大模型知识引擎原子能力提供的文档解析接口轻松实现图片解析为MarkDown文档的小案例。整体接口调用不管是稳定性还是准确度都是非常可靠的,感兴趣的朋友可以基于腾讯云大模型知识引擎提供的各种能力创造出更多提升工作效率的专属应用,针对该案例大家如果有相关问题的话欢迎沟通交流!
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。