Trying to implement function calling in c#, need some advice

Hi,
Im trying to implement a function calling in c# in webapi,
I’ve wrote a service that connects to open-ai and get an image from the user, then return a list of data based on the image.
in the examples, they’re using a do-while loop, i’ve tried that, but it went into an infinite loop which increased the usage by few cents, so I wanted to change the code so it will use a for each loop instead, Im not sure if Id consider it a good implementation, but it works, what Im asking is if you guys can review it and see if an improvement can be made, Im open to suggestion.
Thanks in an advance

The service I’ve wrote:

using System.Text.Json;
using backend.DTOs;
using OpenAI.Chat;

namespace backend.Services
{
    public class OpenAiService
    {
        private readonly ChatClient _chatClient;
        private readonly ChatCompletionOptions _options;

        public OpenAiService(IConfiguration config)
        {
            var apiKey = config.GetValue<string>("OpenAI:Key");
            _chatClient = new ChatClient("gpt-4o", apiKey);

            // Define a function tool that the model can call after processing the image
            var processReceiptTool = ChatTool.CreateFunctionTool(
                functionName: nameof(ProcessReceipt),
                functionDescription: "Process a receipt and extract items",
                functionParameters: BinaryData.FromString(
                    @"
                    {
                        ""type"": ""object"",
                        ""properties"": {
                            ""storeName"": { ""type"": ""string"" },
                            ""purchaseDate"": { ""type"": ""string"", ""format"": ""date-time"" },
                            ""items"": {
                                ""type"": ""array"",
                                ""items"": {
                                    ""type"": ""object"",
                                    ""properties"": {
                                        ""itemName"": { ""type"": ""string"" },
                                        ""itemPrice"": { ""type"": ""number"" },
                                        ""quantity"": { ""type"": ""integer"" },
                                        ""totalItemPrice"": { ""type"": ""number"" }
                                    },
                                    ""required"": [ ""itemName"", ""itemPrice"", ""quantity"", ""totalItemPrice"" ]
                                }
                            }
                        },
                        ""required"": [ ""storeName"", ""purchaseDate"", ""items"" ]
                    }
                    ")
            );

            _options = new ChatCompletionOptions
            {
                MaxTokens = 300,
                Tools = { processReceiptTool }
            };
        }

        private static ReceiptDto ProcessReceipt(string storeName, DateTime purchaseDate, List<ItemDto> items)
        {
            return new ReceiptDto
            {
                StoreName = storeName,
                Purchase = new PurchaseDto
                {
                    PurchaseDate = purchaseDate,
                    Items = items
                }
            };
        }

        public async Task<ReceiptDto> ExtractListOfItems(Stream imageStream)
        {
            var imageBytes = await BinaryData.FromStreamAsync(imageStream);

            var messages = new List<ChatMessage>
            {
                new UserChatMessage(new List<ChatMessageContentPart>
                {
                    ChatMessageContentPart.CreateTextMessageContentPart(
                        @"This receipt is written in Hebrew. Extract the list of items, including:
                        - item name (שם המוצר)
                         - item price (מחיר יחידה)
                        - quantity (כמות)
                        - total price (מחיר כולל).
                        Please make sure to return the extracted data in a structured format and call the ProcessReceipt function with this data."),
                    ChatMessageContentPart.CreateImageMessageContentPart(imageBytes, "image/png")
                })
            };

            ChatCompletion completion = await _chatClient.CompleteChatAsync(messages, _options);

            if (completion is null || completion.FinishReason != ChatFinishReason.ToolCalls)
            {
                throw new Exception("Failed to get a valid response from the OpenAI API.");
            }

            ReceiptDto receiptDto = null;

            // Handle the tool calls directly from the completion response
            foreach (var toolCall in completion.ToolCalls)
            {
                switch (toolCall.FunctionName)
                {
                    case nameof(ProcessReceipt):
                        using (var doc = JsonDocument.Parse(toolCall.FunctionArguments))
                        {
                            var storeName = doc.RootElement.GetProperty("storeName").GetString();
                            var purchaseDate = doc.RootElement.GetProperty("purchaseDate").GetDateTime();
                            var items = JsonSerializer.Deserialize<List<ItemDto>>(doc.RootElement.GetProperty("items").GetRawText());

                            receiptDto = ProcessReceipt(storeName, purchaseDate, items);
                        }
                        break;

                    default:
                        throw new NotImplementedException($"Function {toolCall.FunctionName} is not implemented.");
                }
            }

            return receiptDto;
        }
    }
}

This isn’t really a code review forum. You might want to use stack overflow or something like that. Good luck