Semantic Kernel 对接 阿里百炼OCR-简单案例
参考网址-阿里云官方SDK:https://bailian.console.aliyun.com/cn-beijing?spm=5176.12818093_47.resourceCenter.1.2c9a2cc9qa85FB&tab=api#/api/?type=model&url=2996283
参考网址-阿里云工作空间查看:https://help.aliyun.com/zh/model-studio/obtain-the-app-id-and-workspace-id?spm=a2c4g.11186623.0.0.3d9f23derMPGjK#d3eb3cd37b7fu
项目架构
┌─────────────────────────────────────────────────────────────────┐ │ 项目整体架构 │ ├─────────────────────────────────────────────────────────────────┤ │ │ │ ┌─────────────────────────────────────────────────────────┐ │ │ │ Program.cs │ │ │ │ (程序入口 + DI 配置) │ │ │ └─────────────────────────────────────────────────────────┘ │ │ │ │ │ ▼ │ │ ┌─────────────────────────────────────────────────────────┐ │ │ │ Semantic Kernel │ │ │ │ (AI 编排 + 插件系统) │ │ │ └─────────────────────────────────────────────────────────┘ │ │ │ │ │ ▼ │ │ ┌─────────────────────────────────────────────────────────┐ │ │ │ OcrPlugin │ │ │ │ (SK 插件封装) │ │ │ └─────────────────────────────────────────────────────────┘ │ │ │ │ │ ▼ │ │ ┌─────────────────────────────────────────────────────────┐ │ │ │ DashScopeOcrClient │ │ │ │ (HTTP 调用百炼 API) │ │ │ └─────────────────────────────────────────────────────────┘ │ │ │ │ │ ▼ │ │ ┌─────────────────────────────────────────────────────────┐ │ │ │ 阿里云百炼平台 (qwen3.5-ocr) │ │ │ │ https://{WorkspaceId}.cn-beijing.maas.aliyuncs.com │ │ │ └─────────────────────────────────────────────────────────┘ │ │ │ └─────────────────────────────────────────────────────────────────┘
🔑 核心技术点
1️⃣ 百炼平台 API 调用
| 项目 | 配置 |
|---|---|
| 端点 | https://{WorkspaceId}.cn-beijing.maas.aliyuncs.com/api/v1/assistants/messages |
| 模型 | qwen3.5-ocr (ocr专用) |
| 认证 | Bearer Token (API Key) |
| 请求格式 | JSON (含 image + parameters.task) |
2️⃣ 图片输入方式
| 方式 | 代码 | 适用场景 |
|---|---|---|
| 本地文件 | RecognizeAsync("C:/test.jpg") |
✅ 最推荐,稳定 |
| Base64 | RecognizeAsync("data:image/jpeg;base64,...") |
✅ 小图片 (<7MB) |
| 公开 URL | RecognizeAsync("https://...") |
⚠️ 需要公网可访问 |
3️⃣ Semantic Kernel 集成
// 1. 创建 Kernel var builder = Kernel.CreateBuilder(); builder.AddOpenAIChatCompletion(...); // 2. 注册插件 var ocrPlugin = new OcrPlugin(ocrClient); kernel.Plugins.AddFromObject(ocrPlugin, "OcrPlugin"); // 3. 调用 var text = await kernel.InvokeAsync<string>("OcrPlugin", "recognize_text", ...);
✅ 项目成果
| 功能 | 状态 | 说明 |
|---|---|---|
| 图片 OCR 识别 | ✅ 完成 | 支持本地文件/Base64/URL |
| SK 插件封装 | ✅ 完成 | 可被其他 AI 任务调用 |
| 多模态模型调用 | ✅ 完成 | 百炼平台 qwen-vl-max |
| 错误处理 | ✅ 完成 | 完整异常捕获 + 日志 |
| 调试日志 | ✅ 完成 | 请求/响应全链路打印 |
🚀 后续扩展方向
| 扩展 | 说明 | 难度 |
|---|---|---|
| 发票识别 | 提取发票结构化信息 | ⭐⭐ |
| 身份证识别 | 提取姓名/号码等 | ⭐⭐ |
| 营业执照识别 | 提取企业信息 | ⭐⭐ |
| 表格识别 | 识别表格并转 Excel | ⭐⭐⭐ |
| 手写体识别 | 识别手写文字 | ⭐⭐⭐ |
| 多语言 OCR | 中英混合识别 | ⭐⭐ |
代码片段
main
using ConsoleApp1; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Microsoft.SemanticKernel; using System.Text.Json; namespace ConsoleApp8 { internal class Program { static Kernel CreateKernel() { var builder = Kernel.CreateBuilder(); builder.AddOpenAIChatCompletion( serviceId: "dashscope_qwen3.5-ocr", modelId: "qwen3.5-ocr", apiKey: ConstParm.apiKey, endpoint: new Uri(ConstParm.endpoint)); builder.Services.AddSingleton<DashScopeOcrClient>( sp => new DashScopeOcrClient(ConstParm.apiKey)); return builder.Build(); } static async Task Main(string[] args) { Console.WriteLine("╔════════════════════════════════════════╗"); Console.WriteLine("║ 阿里云图片 OCR + Semantic Kernel ║"); Console.WriteLine("╚════════════════════════════════════════╝\n"); var kernel = CreateKernel(); var ocrClient = kernel.GetRequiredService<DashScopeOcrClient>(); var ocrPlugin = new OcrPlugin(ocrClient); kernel.Plugins.AddFromObject(ocrPlugin, "OcrPlugin"); // ========== 测试:本地图片 ========== Console.WriteLine("\n═══════════════════════════════════════"); Console.WriteLine("【测试】本地图片 OCR 识别"); Console.WriteLine("═══════════════════════════════════════\n"); // 准备测试图片路径 var testImagePath = Path.Combine(AppContext.BaseDirectory, "test.jpg"); // 检查图片是否存在 if (!File.Exists(testImagePath)) { Console.WriteLine($"❌ 测试图片不存在:{testImagePath}"); Console.WriteLine($"💡 请把 test.jpg 放到:{AppContext.BaseDirectory}"); Console.WriteLine("\n按任意键退出..."); Console.ReadKey(); return; } Console.WriteLine($"📷 图片路径:{testImagePath}"); Console.WriteLine($"📏 文件大小:{new FileInfo(testImagePath).Length / 1024} KB\n"); try { // 调用 OCR 识别 var text = await kernel.InvokeAsync<string>("OcrPlugin", "recognize_text", new() { ["imageUrl"] = testImagePath // 传文件路径,自动转 Base64 }); Console.WriteLine("\n═══════════════════════════════════════"); Console.WriteLine("✅ 识别结果:"); Console.WriteLine("═══════════════════════════════════════"); Console.WriteLine(text); Console.WriteLine("═══════════════════════════════════════\n"); } catch (Exception ex) { Console.WriteLine($"\n❌ 识别失败:{ex.Message}\n"); Console.WriteLine($"💡 详细信息:\n{ex.InnerException?.Message}\n"); } // ========== 测试 2:公开 URL ========== Console.WriteLine("\n═══════════════════════════════════════"); Console.WriteLine("【测试 2】公开图片 URL"); Console.WriteLine("═══════════════════════════════════════"); var publicUrl = "https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20241108/ctdzex/biaozhun.jpg"; try { var text2 = await kernel.InvokeAsync<string>("OcrPlugin", "recognize_text", new() { ["imageUrl"] = publicUrl }); Console.WriteLine($"📝 识别结果:\n{text2}\n"); } catch (Exception ex) { Console.WriteLine($"❌ URL 测试失败:{ex.Message}\n"); Console.WriteLine("💡 建议用本地图片测试(Base64 方式)"); } Console.WriteLine("\n按任意键退出..."); Console.ReadKey(); } } }
Plugins
using Microsoft.SemanticKernel; using System; using System.Collections.Generic; using System.ComponentModel; using System.Linq; using System.Text; using System.Threading.Tasks; namespace ConsoleApp8 { public class OcrPlugin { private readonly DashScopeOcrClient _ocrClient; public OcrPlugin(DashScopeOcrClient ocrClient) { _ocrClient = ocrClient; } [KernelFunction("recognize_text")] [Description("从图片中提取文字内容")] public async Task<string> RecognizeTextAsync( [Description("图片 URL 或本地路径或 Base64")] string imageUrl) { Console.WriteLine($"📷 开始识别:{imageUrl}"); var text = await _ocrClient.RecognizeAsync(imageUrl); Console.WriteLine($"✅ 识别完成,文字长度:{text.Length}"); return text; } } }
services
using ConsoleApp1; using System; using System.Collections.Generic; using System.Linq; using System.Net.Http.Headers; using System.Text; using System.Text.Json; using System.Threading.Tasks; namespace ConsoleApp8 { /// <summary> /// 阿里云 DashScope OCR 客户端 /// 百炼平台多模态接口 /// </summary> public class DashScopeOcrClient { private readonly HttpClient _httpClient; private readonly string _apiKey; // ✅ 完整端点 private string ApiEndpoint => $"https://{ConstParm.WorkspaceId}.cn-beijing.maas.aliyuncs.com/api/v1/services/aigc/multimodal-generation/generation"; public DashScopeOcrClient(string apiKey) { _apiKey = apiKey; _httpClient = new HttpClient(); _httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", apiKey); _httpClient.DefaultRequestHeaders.UserAgent.ParseAdd("dashscope-sdk-csharp"); } /// <summary> /// 识别图片中的文字 /// </summary> public async Task<string> RecognizeAsync(string imageSource) { string imageData; if (imageSource.StartsWith("http://") || imageSource.StartsWith("https://")) { imageData = imageSource; } else if (imageSource.StartsWith("data:") || imageSource.StartsWith("/9j/") || imageSource.StartsWith("iVBOR")) { imageData = imageSource; } else { imageData = ImageToBase64(imageSource); } // ✅ 百炼平台格式:content 只有 image,text 放外面 var requestBody = new { model = "qwen3.5-ocr", input = new { messages = new[] { new { role = "user", content = new object[] { new { image = imageData } } } } }, parameters = new { task = "image_text_recognition" // ✅ OCR 任务类型 } }; var json = JsonSerializer.Serialize(requestBody); //Console.WriteLine($"📤 端点:{ApiEndpoint}"); //Console.WriteLine($"📤 请求 JSON: {json}"); var content = new StringContent(json, Encoding.UTF8, "application/json"); var response = await _httpClient.PostAsync(ApiEndpoint, content); var responseJson = await response.Content.ReadAsStringAsync(); //Console.WriteLine($"📥 响应状态码:{response.StatusCode}"); //Console.WriteLine($"📥 响应内容:{responseJson}"); if (!response.IsSuccessStatusCode) { throw new Exception($"OCR API 失败:HTTP {response.StatusCode} - {responseJson}"); } var result = JsonSerializer.Deserialize<JsonElement>(responseJson); // 百炼平台响应格式 var text = result.GetProperty("output") .GetProperty("choices")[0] .GetProperty("message") .GetProperty("content")[0] .GetProperty("text") .GetString() ?? ""; return text; } private string ImageToBase64(string filePath) { var bytes = File.ReadAllBytes(filePath); var base64 = Convert.ToBase64String(bytes); return $"data:image/jpeg;base64,{base64}"; } } }
运行效果

相关图片

及


浙公网安备 33010602011771号