2025-11-05
C#
00

目录

什么是Semantic Kernel?
Semantic Kernel的多模态能力
图像分析
进阶版本:支持多种图像分析功能
使用说明
注意事项

在人工智能快速发展的今天,多模态AI应用已成为技术前沿的热点。微软开源的Semantic Kernel为C#开发者提供了强大的工具,使创建多模态图像分析应用变得更加简单和高效。本文将深入探讨如何利用C#和Semantic Kernel构建图像分析应用,并提供详细的代码示例。

什么是Semantic Kernel?

Semantic Kernel是微软开源的一个轻量级AI开发套件,它能让开发者轻松构建AI Agent,并将最新的AI模型集成到C#、Python或Java代码库中。它的核心优势在于将传统编程语言与大型语言模型(LLM)AI技术相结合的能力,使开发者能够利用熟悉的编程语言,同时享受先进AI技术带来的便利。

Semantic Kernel的多模态能力

多模态是现代LLM的重要能力,特别是在处理图像、文本等不同类型数据时。Semantic Kernel通过集成OpenAI、Azure OpenAI等服务,支持图像分析和其他多模态任务,包括:

  • 图像内容识别与描述
  • 图像中文本提取
  • 图像场景理解与分析
  • 基于图像的问答

图像分析

这里用的是阿里的通义千问72B,你可以去阿里注册,现在送免费TOKEN。

C#
using Microsoft.SemanticKernel.ChatCompletion; using Microsoft.SemanticKernel; using System.Net.Http; using OpenAI; using System.ClientModel; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Configuration; using System.Collections.Generic; using System.Text; using System; using System.IO; using System.Threading.Tasks; using Microsoft.Extensions.DependencyInjection; namespace AppMultimodal { internal class Program { // 最大保存的对话轮数,防止历史记录过长 private const int MaxConversationTurns = 10; static async Task Main(string[] args) { try { // 使用Host Builder模式配置应用 var builder = Host.CreateApplicationBuilder(args); // 从配置文件或环境变量加载API密钥 // 实际使用时请替换为自己的API密钥或通过环境变量配置 builder.Configuration.AddEnvironmentVariables(); var apiKey = builder.Configuration["OpenAI:ApiKey"] ?? "sk-****"; // 配置OpenAI客户端凭证和选项 var openAIClientCredential = new ApiKeyCredential(apiKey); var openAIClientOption = new OpenAIClientOptions { // DeepSeek的API端点 Endpoint = new Uri("https://dashscope.aliyuncs.com/compatible-mode/v1"), NetworkTimeout = TimeSpan.FromSeconds(60), }; // 创建OpenAI客户端 var openaiClient = new OpenAIClient(openAIClientCredential, openAIClientOption); // 注册聊天服务 builder.Services.AddOpenAIChatCompletion("qwen-vl-plus", openaiClient); // 注册Kernel builder.Services.AddTransient((serviceProvider) => { return new Kernel(serviceProvider); }); var host = builder.Build(); var kernel = host.Services.GetRequiredService<Kernel>(); var chatService = kernel.GetRequiredService<IChatCompletionService>(); // 启动图像分析程序 await RunImageAnalysisAppAsync(chatService); } catch (Exception ex) { // 全局异常处理 Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine($"发生错误: {ex.Message}"); Console.ResetColor(); } } /// <summary> /// 运行图像分析应用 /// </summary> static async Task RunImageAnalysisAppAsync(IChatCompletionService chatService) { Console.ForegroundColor = ConsoleColor.White; Console.WriteLine("欢迎使用多模态图像分析应用"); Console.WriteLine("输入图像路径进行分析,或输入 'exit' 退出程序"); // 创建聊天历史 var chatHistory = new ChatHistory("你是一个专业的图像分析AI助手,擅长分析图像内容并提供详细描述。"); while (true) { Console.ForegroundColor = ConsoleColor.Yellow; Console.Write("\n请输入图像路径或命令: "); string input = Console.ReadLine(); if (string.IsNullOrEmpty(input) || input.ToLower() == "exit") break; await ProcessImageAnalysisRequestAsync(input, chatHistory, chatService); } } /// <summary> /// 处理图像分析请求 /// </summary> static async Task ProcessImageAnalysisRequestAsync(string imagePath, ChatHistory chatHistory, IChatCompletionService chatService) { try { // 检查文件是否存在 if (!File.Exists(imagePath)) { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine($"错误: 找不到文件 '{imagePath}'"); Console.ResetColor(); return; } // 获取文件的MIME类型 string mimeType = GetMimeType(imagePath); if (mimeType == null) { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine("错误: 不支持的图像格式。请使用JPG、PNG、GIF或BMP格式的图像。"); Console.ResetColor(); return; } Console.WriteLine($"正在分析图像: {imagePath}"); // 从文件读取图像数据 byte[] imageBytes = File.ReadAllBytes(imagePath); // 添加用户消息,包含分析请求和图像 chatHistory.AddUserMessage( [ new TextContent("请详细分析这张图片中的内容,包括主要对象、场景、颜色和可能的含义。"), new ImageContent(imageBytes, mimeType) ] ); // 管理聊天历史长度 ManageChatHistorySize(chatHistory); Console.ForegroundColor = ConsoleColor.White; Console.WriteLine("AI分析结果:"); // 获取AI的响应 var response = await chatService.GetChatMessageContentAsync(chatHistory); // 打印响应 Console.WriteLine(response.Content); // 添加AI回复到历史记录 chatHistory.AddAssistantMessage(response.Content ?? string.Empty); } catch (Exception ex) { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine($"处理图像时出错: {ex.Message}"); Console.ResetColor(); } } /// <summary> /// 获取文件的MIME类型 /// </summary> static string GetMimeType(string filePath) { string extension = Path.GetExtension(filePath).ToLower(); return extension switch { ".jpg" or ".jpeg" => "image/jpeg", ".png" => "image/png", ".gif" => "image/gif", ".bmp" => "image/bmp", _ => null // 不支持的格式 }; } /// <summary> /// 管理聊天历史大小,防止过长导致token超限或内存问题 /// </summary> static void ManageChatHistorySize(ChatHistory chatHistory) { // 保留最近的对话,移除较早的对话 // 注意: ChatHistory类的处理方式与List<ChatMessage>不同 while (chatHistory.Count > MaxConversationTurns * 2 + 1) // +1 是为系统消息 { // 移除最早的用户消息和助手回复 // 从索引1开始移除(保留系统消息) chatHistory.RemoveAt(1); if (chatHistory.Count > 1) // 如果还有助手消息,也移除 chatHistory.RemoveAt(1); } } } }

image.png

进阶版本:支持多种图像分析功能

以下是一个更完整的多模态图像分析应用程序,支持多种分析功能:

C#
using Microsoft.SemanticKernel.ChatCompletion; using Microsoft.SemanticKernel; using System.Net.Http; using OpenAI; using System.ClientModel; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Configuration; using System.Collections.Generic; using System.Text; using System; using System.IO; using System.Threading.Tasks; using Microsoft.Extensions.DependencyInjection; namespace AppMultimodal { internal class Program { // 最大保存的对话轮数,防止历史记录过长 private const int MaxConversationTurns = 10; static async Task Main(string[] args) { try { // 使用Host Builder模式配置应用 var builder = Host.CreateApplicationBuilder(args); // 从配置文件或环境变量加载API密钥 builder.Configuration.AddEnvironmentVariables(); var apiKey = builder.Configuration["OpenAI:ApiKey"] ?? "sk-*****"; // 配置OpenAI客户端凭证和选项 var openAIClientCredential = new ApiKeyCredential(apiKey); var openAIClientOption = new OpenAIClientOptions { // DeepSeek的API端点 Endpoint = new Uri("https://dashscope.aliyuncs.com/compatible-mode/v1"), NetworkTimeout = TimeSpan.FromSeconds(60), }; // 创建OpenAI客户端 var openaiClient = new OpenAIClient(openAIClientCredential, openAIClientOption); // 注册聊天服务 builder.Services.AddOpenAIChatCompletion("qwen-vl-plus", openaiClient); // 注册Kernel builder.Services.AddTransient((serviceProvider) => { return new Kernel(serviceProvider); }); var host = builder.Build(); var kernel = host.Services.GetRequiredService<Kernel>(); var chatService = kernel.GetRequiredService<IChatCompletionService>(); // 启动图像分析程序 await RunAdvancedImageAnalysisAppAsync(chatService); } catch (Exception ex) { // 全局异常处理 Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine($"发生错误: {ex.Message}"); Console.ResetColor(); } } /// <summary> /// 运行高级图像分析应用 /// </summary> static async Task RunAdvancedImageAnalysisAppAsync(IChatCompletionService chatService) { Console.ForegroundColor = ConsoleColor.Cyan; Console.WriteLine("========================================"); Console.WriteLine(" 多模态图像分析应用 - Semantic Kernel"); Console.WriteLine("========================================"); Console.WriteLine("支持的功能:"); Console.WriteLine("1. 常规分析 - 分析图像中的主要内容"); Console.WriteLine("2. 文本提取 - 提取图像中的文本内容"); Console.WriteLine("3. 物体识别 - 识别图像中的物体"); Console.WriteLine("4. 情感分析 - 分析图像的情感基调"); Console.WriteLine("5. 场景描述 - 创意描述图像场景"); Console.WriteLine("6. 自定义问题 - 向图像提问"); Console.WriteLine("输入 'exit' 退出程序"); Console.WriteLine("========================================"); // 创建聊天历史 var chatHistory = new ChatHistory("你是一个专业的图像分析AI助手,擅长分析图像内容并提供详细描述。"); while (true) { Console.ForegroundColor = ConsoleColor.Yellow; Console.Write("\n请输入图像路径: "); string imagePath = Console.ReadLine(); if (string.IsNullOrEmpty(imagePath) || imagePath.ToLower() == "exit") break; if (!File.Exists(imagePath)) { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine($"错误: 找不到文件 '{imagePath}'"); Console.ResetColor(); continue; } // 获取文件的MIME类型 string mimeType = GetMimeType(imagePath); if (mimeType == null) { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine("错误: 不支持的图像格式。请使用JPG、PNG、GIF或BMP格式的图像。"); Console.ResetColor(); continue; } // 读取图像数据 byte[] imageBytes = File.ReadAllBytes(imagePath); // 显示功能菜单 Console.ForegroundColor = ConsoleColor.Yellow; Console.Write("请选择分析功能 (1-6): "); string option = Console.ReadLine(); // 根据用户选择执行不同的分析功能 await ExecuteImageAnalysisAsync(option, imageBytes, mimeType, imagePath, chatService, chatHistory); } } /// <summary> /// 执行图像分析 /// </summary> static async Task ExecuteImageAnalysisAsync(string option, byte[] imageBytes, string mimeType, string imagePath, IChatCompletionService chatService, ChatHistory chatHistory) { // 创建新的聊天历史,以避免之前的分析影响当前结果 var analysisHistory = new ChatHistory("你是一个专业的图像分析AI助手,擅长分析图像内容并提供详细描述。"); string prompt = option switch { "1" => "请详细分析这张图片中的内容,包括主要对象、场景、颜色和可能的含义。", "2" => "请识别并提取这张图片中的所有文本内容,按照原始格式输出。如果没有检测到文本,请说明。", "3" => "请列出并描述这张图片中所有可识别的物体,并说明它们的位置和特征。", "4" => "请分析这张图片传达的情感和氛围。考虑色调、构图、主题等因素,给出全面的情感分析。", "5" => "请以文学性的语言创意描述这张图片展示的场景,使用生动的形容词和比喻。", "6" => await GetCustomPromptAsync(), _ => "请详细描述这张图片中的内容。" }; Console.WriteLine($"正在分析图像: {Path.GetFileName(imagePath)}"); Console.WriteLine($"分析类型: {GetAnalysisTypeName(option)}"); // 添加用户消息,包含分析请求和图像 analysisHistory.AddUserMessage( [ new TextContent(prompt), new ImageContent(imageBytes, mimeType) ] ); Console.ForegroundColor = ConsoleColor.White; Console.WriteLine("\nAI分析结果:"); // 获取AI的响应 var response = await chatService.GetChatMessageContentAsync(analysisHistory); // 打印响应 Console.WriteLine(response.Content); // 询问是否要保存结果 Console.ForegroundColor = ConsoleColor.Yellow; Console.Write("\n是否保存分析结果? (y/n): "); string saveOption = Console.ReadLine(); if (saveOption?.ToLower() == "y") { string resultPath = Path.Combine( Path.GetDirectoryName(imagePath), $"{Path.GetFileNameWithoutExtension(imagePath)}_分析结果_{DateTime.Now:yyyyMMdd_HHmmss}.txt" ); File.WriteAllText(resultPath, response.Content, Encoding.UTF8); Console.WriteLine($"结果已保存到: {resultPath}"); } } /// <summary> /// 获取自定义提示 /// </summary> static async Task<string> GetCustomPromptAsync() { Console.ForegroundColor = ConsoleColor.Yellow; Console.Write("请输入您想问关于图片的问题: "); return Console.ReadLine(); } /// <summary> /// 获取分析类型名称 /// </summary> static string GetAnalysisTypeName(string option) { return option switch { "1" => "常规分析", "2" => "文本提取", "3" => "物体识别", "4" => "情感分析", "5" => "场景描述", "6" => "自定义问题", _ => "未知分析类型" }; } /// <summary> /// 获取文件的MIME类型 /// </summary> static string GetMimeType(string filePath) { string extension = Path.GetExtension(filePath).ToLower(); return extension switch { ".jpg" or ".jpeg" => "image/jpeg", ".png" => "image/png", ".gif" => "image/gif", ".bmp" => "image/bmp", _ => null // 不支持的格式 }; } } }

image.png

使用说明

  1. 将代码保存到一个C#控制台应用项目中
  2. 确保已安装以下NuGet包:
    • Microsoft.SemanticKernel
    • OpenAI
    • Microsoft.Extensions.Hosting
    • Microsoft.Extensions.Configuration
  3. 运行前请替换代码中的API密钥或通过环境变量设置
  4. 运行程序并按提示输入图像路径
  5. 选择所需的分析功能
  6. 查看AI返回的分析结果

注意事项

  1. 代码中使用的是DeepSeek API,确保API支持多模态图像分析功能
  2. 图像分析需要消耗较多的API资源,请注意控制使用频率
  3. 对于大图像,建议先进行压缩以提高处理速度
  4. 不同的模型对图像分析的能力有所差异,请根据实际需求选择合适的模型

这个实现充分利用了Semantic Kernel的多模态能力,可以帮助您快速构建具有图像分析功能的应用程序。您可以根据自己的需求进一步扩展这个基础框架。

本文作者:技术老小子

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!