From 61320dc9365efec423370e3e0166651acb5e619f Mon Sep 17 00:00:00 2001 From: bicijinlian Date: Sun, 10 Aug 2025 13:03:16 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- OllamaStudy.UseExtensionsAI/OpenAISdkTest.cs | 291 +++++++++++++++++- .../OllamaApiTest.cs | 16 +- OllamaStudy.UseOllamaSharp/OllamaApiTest.cs | 7 +- 3 files changed, 296 insertions(+), 18 deletions(-) diff --git a/OllamaStudy.UseExtensionsAI/OpenAISdkTest.cs b/OllamaStudy.UseExtensionsAI/OpenAISdkTest.cs index 83858f4..d52e9bf 100644 --- a/OllamaStudy.UseExtensionsAI/OpenAISdkTest.cs +++ b/OllamaStudy.UseExtensionsAI/OpenAISdkTest.cs @@ -465,15 +465,23 @@ public class OpenAISdkTest } #endregion - [Fact] #region 如何将响应与文件搜索一起使用 + //[Fact] + [Fact(Skip = "因本地Ollama测试环境不支持,忽略测试")] public async Task Respones_With_FileSearch_Test() { #pragma warning disable OPENAI001 - OpenAIResponseClient client = new( - model: "gpt-4o-mini", - apiKey: Environment.GetEnvironmentVariable("OPENAI_API_KEY")); + OpenAIResponseClient client = new + ( + "gpt-4o-mini", + new ApiKeyCredential("sk-4azuOUkbzNGP22pQkND8ad1vZl7ladwBQyqGKlWWZyxYgX1L"), + new OpenAIClientOptions() + { + Endpoint = new Uri("https://sg.uiuiapi.com/v1") + } + ); + //已经存在的文件向量IDS(提前将文件向量化) ResponseTool fileSearchTool = ResponseTool.CreateFileSearchTool(vectorStoreIds: ["sssssssss"]); OpenAIResponse response = await client.CreateResponseAsync ( @@ -504,11 +512,21 @@ public class OpenAISdkTest #endregion #region 如何将响应与网络搜索结合使用 - [Fact] + + [Fact(Skip = "因本地Ollama测试环境不支持,忽略测试")] + //[Fact] public async Task WebSearch_ChatClient_Test() { #pragma warning disable OPENAI001 - OpenAIResponseClient client = _defaultOpenAIClient.GetOpenAIResponseClient(ModelSelecter.ModelWithRawmodel); + OpenAIResponseClient client = new + ( + "gpt-4o-mini", + new ApiKeyCredential("sk-4azuOUkbzNGP22pQkND8ad1vZl7ladwBQyqGKlWWZyxYgX1L"), + new OpenAIClientOptions() + { + Endpoint = new Uri("https://sg.uiuiapi.com/v1") + } + ); OpenAIResponse response = await client.CreateResponseAsync ( @@ -535,15 +553,274 @@ public class OpenAISdkTest #endregion #region 如何生成文本嵌入 + [Fact] + public void Embedding_ChatClient_Test() + { + EmbeddingClient embeddingClient = _defaultOpenAIClient.GetEmbeddingClient(ModelSelecter.ModelWithEmbedding); + + string description = "Best hotel in town if you like luxury hotels. They have an amazing infinity pool, a spa," + + " and a really helpful concierge. The location is perfect -- right downtown, close to all the tourist" + + " attractions. We highly recommend this hotel."; + + OpenAIEmbedding embedding = embeddingClient.GenerateEmbedding(description); + ReadOnlyMemory vector = embedding.ToFloats(); + + Assert.True(vector.Length>0); + } #endregion #region 如何生成图像 + [Fact(Skip = "因本地Ollama测试环境不支持,忽略测试")] + //[Fact] + public void Image_ChatClient_Test() + { + ImageClient imageClient = new + ( + "dall-e-3", + new ApiKeyCredential("sk-4azuOUkbzNGP22pQkND8ad1vZl7ladwBQyqGKlWWZyxYgX1L"), + new OpenAIClientOptions() + { + Endpoint = new Uri("https://sg.uiuiapi.com/v1") + } + ); + + string prompt = """ + The concept for a living room that blends Scandinavian simplicity with Japanese minimalism for a serene and cozy atmosphere. + It's a space that invites relaxation and mindfulness, with natural light and fresh air. + Using neutral tones, including colors like white, beige, gray, and black, that create a sense of harmony. + Featuring sleek wood furniture with clean lines and subtle curves to add warmth and elegance. Plants and flowers in ceramic pots adding color and life to a space. + They can serve as focal points, creating a connection with nature. Soft textiles and cushions in organic fabrics adding comfort and softness to a space. + They can serve as accents, adding contrast and texture. + """; + prompt = """ + 画一个中国古代的将军。身披铠甲,手持长剑,眼神坚定,表情严肃,看起来很威严。国字脸,在战场上指挥作战! + """; + + ImageGenerationOptions options = new() + { + Quality = GeneratedImageQuality.High, + Size = GeneratedImageSize.W1792xH1024, + Style = GeneratedImageStyle.Vivid, + ResponseFormat = GeneratedImageFormat.Bytes + }; + + GeneratedImage image = imageClient.GenerateImage(prompt, options); + BinaryData bytes = image.ImageBytes; + + using FileStream stream = File.OpenWrite($"{Guid.NewGuid()}.png"); + bytes.ToStream().CopyTo(stream); + } #endregion #region 如何转录音频 + [Fact(Skip = "因本地Ollama测试环境不支持,忽略测试")] + //[Fact] + public void Tranacribe_Audio_AudioClient_Test() + { + AudioClient client = new + ( + "whisper-1", + new ApiKeyCredential("sk-4azuOUkbzNGP22pQkND8ad1vZl7ladwBQyqGKlWWZyxYgX1L"), + new OpenAIClientOptions() + { + Endpoint = new Uri("https://sg.uiuiapi.com/v1") + } + ); + + string audioFilePath = Path.Combine("Assets", "dongdong.mp3"); + + AudioTranscriptionOptions options = new() + { + ResponseFormat = AudioTranscriptionFormat.Verbose, + TimestampGranularities = AudioTimestampGranularities.Word | AudioTimestampGranularities.Segment, + }; + + AudioTranscription transcription = client.TranscribeAudio(audioFilePath, options); + + _output.WriteLine("Transcription:"); + _output.WriteLine($"{transcription.Text}"); + + _output.WriteLine(""); + _output.WriteLine($"Words:"); + foreach (TranscribedWord word in transcription.Words) + { + _output.WriteLine($" {word.Word,15} : {word.StartTime.TotalMilliseconds,5:0} - {word.EndTime.TotalMilliseconds,5:0}"); + } + + _output.WriteLine(""); + _output.WriteLine($"Segments:"); + foreach (TranscribedSegment segment in transcription.Segments) + { + _output.WriteLine($" {segment.Text,90} : {segment.StartTime.TotalMilliseconds,5:0} - {segment.EndTime.TotalMilliseconds,5:0}"); + } + } #endregion - #region 如何将助手与检索增强生成 (RAG) 结合使用。 + #region 如何将助手与检索增强生成 (RAG) 结合使用 + /// + /// 在此示例中,您有一个包含不同产品每月销售信息的 JSON 文档,并且您希望构建一个能够分析它并回答有关它的问题的助手 + /// 请同时使用 OpenAI.Files 命名空间中的 OpenAIFileClient 和 OpenAI.Assistants 命名空间中的 AssistantClient + /// + [Fact] + public void RAG_Assistant_ChatClient_Test() + { +#pragma warning disable OPENAI001 + + OpenAIClientOptions clientOptions = new() + { + Endpoint = new Uri("https://sg.uiuiapi.com/v1"), + }; + + OpenAIClient openAIClient = new(new ApiKeyCredential("sk-4azuOUkbzNGP22pQkND8ad1vZl7ladwBQyqGKlWWZyxYgX1L")); + OpenAIFileClient fileClient = openAIClient.GetOpenAIFileClient(); + AssistantClient assistantClient = openAIClient.GetAssistantClient(); + + using Stream document = BinaryData.FromBytes(""" + { + "description": "This document contains the sale history data for Contoso products.", + "sales": [ + { + "month": "January", + "by_product": { + "113043": 15, + "113045": 12, + "113049": 2 + } + }, + { + "month": "February", + "by_product": { + "113045": 22 + } + }, + { + "month": "March", + "by_product": { + "113045": 16, + "113055": 5 + } + } + ] + } + """u8.ToArray()).ToStream(); + //使用 OpenAIFileClient 的 UploadFile 方法将此文档上传到 OpenAI,确保使用 FileUploadPurpose.Assistants 以允许助手稍后访问它 + OpenAIFile salesFile = fileClient.UploadFile + ( + document, + "monthly_sales.json", + FileUploadPurpose.Assistants + ); + + //使用 AssistantCreationOptions 类的实例创建新助手以对其进行自定义。 + AssistantCreationOptions assistantOptions = new() + { + Name = "Example: Contoso sales RAG", + Instructions ="You are an assistant that looks up sales data and helps visualize the information based on user queries. When asked to generate a graph, chart, or other visualization, use the code interpreter tool to do so.", + Tools = + { + new FileSearchToolDefinition(), + new CodeInterpreterToolDefinition(), + }, + ToolResources = new() + { + FileSearch = new() + { + NewVectorStores = + { + new VectorStoreCreationHelper([salesFile.Id]), + } + } + }, + }; + + Assistant assistant = assistantClient.CreateAssistant("gpt-4o", assistantOptions); + + //接下来,创建一个新线程。出于说明目的,可以包含询问给定产品的销售信息的初始用户消息,然后使用 AssistantClient 的 CreateThreadAndRun 方法启动它: + ThreadCreationOptions threadOptions = new() + { + InitialMessages = { "How well did product 113045 sell in February? Graph its trend over time." } + }; + + ThreadRun threadRun = assistantClient.CreateThreadAndRun(assistant.Id, threadOptions); + + //轮询运行的状态,直到它不再排队或正在进行: + do + { + Thread.Sleep(TimeSpan.FromSeconds(1)); + threadRun = assistantClient.GetRun(threadRun.ThreadId, threadRun.Id); + } while (!threadRun.Status.IsTerminal); + + //如果一切顺利,运行的终端状态将为 RunStatus.Completed + //最后,可以使用 AssistantClient 的 GetMessages 方法检索与此线程关联的消息,这些消息现在包括助手对初始用户消息的响应。 + //出于说明目的,您可以将消息打印到控制台,并将助手生成的任何图像保存到本地存储: + + CollectionResult messages = assistantClient.GetMessages(threadRun.ThreadId, new MessageCollectionOptions() { Order = MessageCollectionOrder.Ascending }); + + foreach (ThreadMessage message in messages) + { + Console.Write($"[{message.Role.ToString().ToUpper()}]: "); + foreach (MessageContent contentItem in message.Content) + { + if (!string.IsNullOrEmpty(contentItem.Text)) + { + Console.WriteLine($"{contentItem.Text}"); + + if (contentItem.TextAnnotations.Count > 0) + { + Console.WriteLine(); + } + + // Include annotations, if any. + foreach (TextAnnotation annotation in contentItem.TextAnnotations) + { + if (!string.IsNullOrEmpty(annotation.InputFileId)) + { + Console.WriteLine($"* File citation, file ID: {annotation.InputFileId}"); + } + if (!string.IsNullOrEmpty(annotation.OutputFileId)) + { + Console.WriteLine($"* File output, new file ID: {annotation.OutputFileId}"); + } + } + } + if (!string.IsNullOrEmpty(contentItem.ImageFileId)) + { + OpenAIFile imageInfo = fileClient.GetFile(contentItem.ImageFileId); + BinaryData imageBytes = fileClient.DownloadFile(contentItem.ImageFileId); + using FileStream stream = File.OpenWrite($"{imageInfo.Filename}.png"); + imageBytes.ToStream().CopyTo(stream); + + Console.WriteLine($""); + } + } + Console.WriteLine(); + + } + + //它会产生这样的结果 + var output = + """ + [USER]: How well did product 113045 sell in February? Graph its trend over time. + + + [ASSISTANT]: Product 113045 sold 22 units in February【4:0†monthly_sales.json】. + + Now, I will generate a graph to show its sales trend over time. + + * File citation, file ID: file-hGOiwGNftMgOsjbynBpMCPFn + + [ASSISTANT]: + The sales trend for Product 113045 over the past three months shows that: + + - In January, 12 units were sold. + - In February, 22 units were sold, indicating significant growth. + - In March, sales dropped slightly to 16 units. + + The graph above visualizes this trend, showing a peak in sales during February. + """; + + #pragma warning restore OPENAI001 + } #endregion #region 如何将助手与流媒体和视觉结合使用 diff --git a/OllamaStudy.UseHttpClientTest/OllamaApiTest.cs b/OllamaStudy.UseHttpClientTest/OllamaApiTest.cs index 5dae57f..d1948b9 100644 --- a/OllamaStudy.UseHttpClientTest/OllamaApiTest.cs +++ b/OllamaStudy.UseHttpClientTest/OllamaApiTest.cs @@ -350,10 +350,10 @@ public class OllamaApiTest var requetData = new { model = defaultOllamaOption.Model, - prompt = """Why is the sky blue?""", + prompt = """列出世界四大洋""", stream = false, think = false, - options = new { seed = 123 }, + options = new { seed = 123, temperature = 0 }, }; //第一次请求 @@ -595,12 +595,12 @@ public class OllamaApiTest model = defaultOllamaOption.Model, messages = new[] { - new - { - role = "user", - content = "你好", - } - }, + new + { + role = "user", + content = "你好", + } + }, think = false, stream = false, options = new { seed = 123, temperature = 0 }, diff --git a/OllamaStudy.UseOllamaSharp/OllamaApiTest.cs b/OllamaStudy.UseOllamaSharp/OllamaApiTest.cs index 7298ca6..cbcde3f 100644 --- a/OllamaStudy.UseOllamaSharp/OllamaApiTest.cs +++ b/OllamaStudy.UseOllamaSharp/OllamaApiTest.cs @@ -269,13 +269,14 @@ namespace OllamaStudy.UseOllamaSharp //第一次请求 var generateRequest1 = new GenerateRequest() { - Prompt = """天空为什么是蓝色的? """, + Prompt = """中华人民共和国的首都是不是北京?回答是或否""", Stream = false, Options = new RequestOptions() { Seed = 999999999, Temperature = 0, - } + }, + }; //处理响应 @@ -287,7 +288,7 @@ namespace OllamaStudy.UseOllamaSharp //第二次请求 var generateRequest2 = new GenerateRequest() { - Prompt = """天空为什么是蓝色的? """, + Prompt = """中华人民共和国的首都是不是北京?回答是或否""", Stream = false, Options = new RequestOptions() {