SemanticKernelのImageToTextについて


この記事では、ImageToTextに焦点を当て、画像内の情報を取得して活用する方法について見ていきます。一例として、ユーザーが画像をアップロードし、AIを使用してアップロードされた画像が正しいかどうかを判断するシナリオを紹介します。

```xml
<ItemGroup>
  <PackageReference Include="Microsoft.SemanticKernel" Version="1.6.2" />
</ItemGroup>
```

画像の認識について、これまで問題と画像を入力として効果が安定しなかったため、今回は調整を行いました。まず、画像にどのような特徴があるかを尋ねてモデルに答えさせ、その特徴が返ってきた後、テキストでの尋ねる二回目の問いかけを行い、判断を下します。この方法の方が効果的ですが、必要なトークンを節約することは難しいです。

後端のcsコードは以下の通りです：

```csharp
using Microsoft.SemanticKernel.ChatCompletion;
using Microsoft.SemanticKernel.Connectors.OpenAI;
using Microsoft.SemanticKernel;

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.UseStaticFiles();
var key = File.ReadAllText(@"C:\GPT\key.txt");
var kernel = Kernel.CreateBuilder()
    .AddOpenAIChatCompletion("gpt-4-vision-preview", key)
    .Build();
var chatGPT = kernel.GetRequiredService<IChatCompletionService>();
var systemMessage = @"あなたはとても真剣なアシスタントで、画像を非常に慎重に優れて認識できます。";
var chatHistory = new ChatHistory(systemMessage);
var prompt = "画像の特徴を簡単に説明してください";
app.MapGet("/iscard", async (string name) => {
    app.Logger.LogInformation("画像名：{0}", name);
    chatHistory.Clear();
    var ImageUri = $"https://github.com/axzxs2001/Asp.NetCoreExperiment/blob/master/Asp.NetCoreExperiment/SemanticKernel/GPTVision/{name}.png?raw=true";
    chatHistory.AddUserMessage(new ChatMessageContentItemCollection
        {
            new TextContent(prompt),
            new ImageContent(new Uri(ImageUri))
        });
    var reply = await chatGPT.GetChatMessageContentAsync(chatHistory, new OpenAIPromptExecutionSettings() { MaxTokens = 1000 });
    var message = reply.Content;
    chatHistory.Clear();
    app.Logger.LogInformation(message);
    var newprompt = @$"以下の特徴に基づいて：
--------------------------
{message}，
--------------------------
次の質問に答えてください。"Yes"または"No"で回答してください。識別できない場合は"No"で回答してください。
質問：この画像は「Residence Card」ですか？
「Residence Card」には以下の特徴があります：
"Residence Card"という文字が含まれています
"GOVERNMENT OF JAPAN"という文字が含まれています
"DATE OF BIRTH"という文字が含まれています
"ADDRESS"という文字が含まれています
"STATUS"という文字が含まれています
";
    chatHistory.AddUserMessage(new ChatMessageContentItemCollection
        {
            new TextContent(newprompt),
        });
    reply = await chatGPT.GetChatMessageContentAsync(chatHistory, new OpenAIPromptExecutionSettings() { MaxTokens = 100 });
    app.Logger.LogInformation(reply.Content);
    return reply.Content;
});

app.Run();
```

フロントエンドのコードは以下の通りです：

```html
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>アップロード</title>
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-ka7Sk0Gln4gmtz2MlQnikT1wXgYsOg+OMhuP+IlRH9sENBO0LRn5q+8nbTov4+1p" crossorigin="anonymous"></script>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
    <script src="https://code.jquery.com/jquery-3.7.1.min.js" integrity="sha256-/JqT3SQfawRcv/BIHPThkBvs0OEvtFFmqPF/lYI/Cxo=" crossorigin="anonymous"></script>
</head>
<body>
    <div class="container">
        <div class="row">
            <div class="col">
                <img onclick="isziliucard('a')" src="https://github.com/axzxs2001/Asp.NetCoreExperiment/blob/master/Asp.NetCoreExperiment/SemanticKernel/GPTVision/a.png?raw=true" width="330" />
            </div>
            <div class="col">
                <img onclick="isziliucard('zlk')" src="https://github.com/axzxs2001/Asp.NetCoreExperiment/blob/master/Asp.NetCoreExperiment/SemanticKernel/GPTVision/zlk.png?raw=true" width="330" />
            </div>
            <div class="col">
                <img onclick="isziliucard('c')" src="https://github.com/axzxs2001/Asp.NetCoreExperiment/blob/master/Asp.NetCoreExperiment/SemanticKernel/GPTVision/c.png?raw=true" width="330" />
            </div>
        </div>
        <div class="row">
            <span id="result"></span>
        </div>
    </div>
    <script>
        function isziliucard(name) {
            $('#result').css('color', 'black');
            $("#result").html("判断中……");
            $.ajax({
                url: '/iscard?name=' + name,
                type: 'GET',
                success: function (data) {
                    if (data.includes('No')) {
                        $('#result').css('color', 'red');
                    } else {
                        $('#result').css('color', 'green');
                    }
                    $("#result").html('判断結果:' + data);
                },
                error: function (xhr, status, error) {
                    alter(error)
                }
            });
        }
    </script>
</body>
</html>
```

結果：
![図示](https://mmbiz.qpic.cn/sz_mmbiz_png/4CAA63nvHRCV4WibUck9La1bLiax3pBq23Tq2UXAG7KHAxg6iapudubr9LibbicY50C5NfmxJCIFkGg8XiaawsicdPZCA/640?wx_fmt=png&from=appmsg&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1)

以下は質問過程でのバックエンドの返答です。「a」は最初の画像の名前、
「zlk」は2番目の画像の名前、「c」は3番目の画像の名前です。

![図示](https://mmbiz.qpic.cn/sz_mmbiz_png/4CAA63nvHRCV4WibUck9La1bLiax3pBq23SPaRJgzCEkz897FqMaSxccXwu4SCI3ERhzSriaicCaLUZCAql5Ds5VCQ/640?wx_fmt=png&from=appmsg&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1)

(Translated by GPT)

元のリンク：https://mp.weixin.qq.com/s?__biz=MzA3NDM1MzIyMQ==&mid=2247488025&idx=1&sn=09dbc03614fd2767fa6bcf729471a5db&chksm=9f004d33a877c4255ccef8b02da17a618d2e0b702ce586391b4708928580999606f230a38b7a&token=1672532928&lang=zh_CN#rd&wt.mc_id=MVP_325642