Microsoft me contactó sobre la transición de esta biblioteca a una nueva biblioteca oficial de C# OpenAi y ¡ahora está listo para comenzar! A partir de v2.0.0-beta.3, la biblioteca oficial ahora tiene cobertura completa y se mantendrá actualizado. Más detalles en la publicación del blog aquí: https://devblogs.microsoft.com/dotnet/openai-dotnet-library
Este repositorio de GitHub permanecerá aquí para documentar mi versión original de la biblioteca a través de la versión 1.11, que también está disponible en Nuget. ?
Una simple biblioteca de envoltura C# .NET para usar con la API de OpenAI. Más contexto en mi blog. Esta es mi biblioteca original de envoltura no oficial alrededor de la API de Operai.
var api = new OpenAI_API . OpenAIAPI ( " YOUR_API_KEY " ) ;
var result = await api . Chat . CreateChatCompletionAsync ( " Hello! " ) ;
Console . WriteLine ( result ) ;
// should print something like "Hi! How can I help you?" Comenzando con V2.0.0-beta, esta biblioteca ha sido adoptada por Microsoft. La nueva versión oficial de la biblioteca tendrá cobertura completa y se mantendrá completamente actualizado. Más detalles en la publicación del blog aquí: https://devblogs.microsoft.com/dotnet/openai-dotnet-library/ Este repositorio de GitHub permanecerá aquí para documentar mi versión original de la biblioteca a través de la versión 1.11, que también está disponible en Nuget.
Esta biblioteca se basa en .NET Standard 2.0, por lo que debería funcionar en todas las versiones de .NET, desde el marco .NET tradicional> = 4.7.2 a .NET (Core)> = 3.0. Debería funcionar a través de aplicaciones de consola, Winforms, WPF, ASP.NET, Unity, Xamarin, etc. Debe funcionar en Windows, Linux y Mac, y posiblemente incluso en dispositivos móviles. Hay dependencias mínimas y tiene licencia en el dominio público.
Instale el paquete OpenAI V1.11 desde Nuget. Así es como a través de la línea de comandos:
Install-Package OpenAI - Version 1.11 . 0Hay 3 formas de proporcionar sus claves API, en orden de precedencia:
APIAuthentication(string key).openai y contiene la línea: OPENAI_API_KEY=sk-aaaabbbbbccccddddd Utiliza la APIAuthentication cuando inicializa la API como se muestra:
// for example
OpenAIAPI api = new OpenAIAPI ( " YOUR_API_KEY " ) ; // shorthand
// or
OpenAIAPI api = new OpenAIAPI ( new APIAuthentication ( " YOUR_API_KEY " ) ) ; // create object manually
// or
OpenAIAPI api = new OpenAIAPI ( APIAuthentication LoadFromEnv ( ) ) ; // use env vars
// or
OpenAIAPI api = new OpenAIAPI ( APIAuthentication LoadFromPath ( ) ) ; // use config file (can optionally specify where to look)
// or
OpenAIAPI api = new OpenAIAPI ( ) ; // uses default, env, or config fileOpcionalmente, puede incluir una OpenaAiorganization (OpenAI_organization en el archivo ENV o config) que especifica qué organización se utiliza para una solicitud API. El uso de estas solicitudes de API contará con la cuota de suscripción de la organización especificada. Los ID de organización se pueden encontrar en la página de configuración de su organización.
// for example
OpenAIAPI api = new OpenAIAPI ( new APIAuthentication ( " YOUR_API_KEY " , " org-yourOrgHere " ) ) ; Se accede a la API de chat a través de OpenAIAPI.Chat . Hay dos formas de usar el punto final de chat, ya sea a través de conversaciones simplificadas o con los métodos completos de solicitud/respuesta.
La clase de conversación le permite interactuar fácilmente con ChatGPT agregando mensajes a un chat y pidiéndole a ChatGPT que responda.
var chat = api . Chat . CreateConversation ( ) ;
chat . Model = Model . GPT4_Turbo ;
chat . RequestParameters . Temperature = 0 ;
/// give instruction as System
chat . AppendSystemMessage ( " You are a teacher who helps children understand if things are animals or not. If the user tells you an animal, you say " yes " . If the user tells you something that is not an animal, you say " no " . You only ever respond with " yes " or " no " . You do not say anything else. " ) ;
// give a few examples as user and assistant
chat . AppendUserInput ( " Is this an animal? Cat " ) ;
chat . AppendExampleChatbotOutput ( " Yes " ) ;
chat . AppendUserInput ( " Is this an animal? House " ) ;
chat . AppendExampleChatbotOutput ( " No " ) ;
// now let's ask it a question
chat . AppendUserInput ( " Is this an animal? Dog " ) ;
// and get the response
string response = await chat . GetResponseFromChatbotAsync ( ) ;
Console . WriteLine ( response ) ; // "Yes"
// and continue the conversation by asking another
chat . AppendUserInput ( " Is this an animal? Chair " ) ;
// and get another response
response = await chat . GetResponseFromChatbotAsync ( ) ;
Console . WriteLine ( response ) ; // "No"
// the entire chat history is available in chat.Messages
foreach ( ChatMessage msg in chat . Messages )
{
Console . WriteLine ( $" { msg . Role } : { msg . Content } " ) ;
} La transmisión le permite obtener resultados si se generan, lo que puede ayudar a que su aplicación se sienta más receptiva.
Usando los nuevos iteradores de Async C# 8.0:
var chat = api . Chat . CreateConversation ( ) ;
chat . AppendUserInput ( " How to make a hamburger? " ) ;
await foreach ( var res in chat . StreamResponseEnumerableFromChatbotAsync ( ) )
{
Console . Write ( res ) ;
}O si usa .NET Framework clásico o C# <8.0:
var chat = api . Chat . CreateConversation ( ) ;
chat . AppendUserInput ( " How to make a hamburger? " ) ;
await chat . StreamResponseFromChatbotAsync ( res =>
{
Console . Write ( res ) ;
} ) ; Puede enviar imágenes al chat para usar el nuevo modelo de visión GPT-4. Esto solo funciona con el modelo Model.GPT4_Vision . Consulte https://platform.openai.com/docs/guides/Vision para obtener más información y limitaciones.
// the simplest form
var result = await api . Chat . CreateChatCompletionAsync ( " What is the primary non-white color in this logo? " , ImageInput . FromFile ( " path/to/logo.png " ) ) ;
// or in a conversation
var chat = api . Chat . CreateConversation ( ) ;
chat . Model = Model . GPT4_Vision ;
chat . AppendSystemMessage ( " You are a graphic design assistant who helps identify colors. " ) ;
chat . AppendUserInput ( " What are the primary non-white colors in this logo? " , ImageInput . FromFile ( " path/to/logo.png " ) ) ;
string response = await chat . GetResponseFromChatbotAsync ( ) ;
Console . WriteLine ( response ) ; // "Blue and purple"
chat . AppendUserInput ( " What are the primary non-white colors in this logo? " , ImageInput . FromImageUrl ( " https://rogerpincombe.com/templates/rp/center-aligned-no-shadow-small.png " ) ) ;
response = await chat . GetResponseFromChatbotAsync ( ) ;
Console . WriteLine ( response ) ; // "Blue, red, and yellow"
// or when manually creating the ChatMessage
messageWithImage = new ChatMessage ( ChatMessageRole . User , " What colors do these logos have in common? " ) ;
messageWithImage . images . Add ( ImageInput . FromFile ( " path/to/logo.png " ) ) ;
messageWithImage . images . Add ( ImageInput . FromImageUrl ( " https://rogerpincombe.com/templates/rp/center-aligned-no-shadow-small.png " ) ) ;
// you can specify multiple images at once
chat . AppendUserInput ( " What colors do these logos have in common? " , ImageInput . FromFile ( " path/to/logo.png " ) , ImageInput . FromImageUrl ( " https://rogerpincombe.com/templates/rp/center-aligned-no-shadow-small.png " ) ) ; Si el historial de conversación de chat da demasiado tiempo, puede no encajar en la duración del contexto del modelo. De manera predeterminada, los primeros mensajes que no son del sistema se eliminarán del historial de chat y la llamada API se volverá a jugar. Puede deshabilitar esto configurando chat.AutoTruncateOnContextLengthExceeded = false , o puede anular el algoritmo de truncamiento como este:
chat . OnTruncationNeeded += ( sender , args ) =>
{
// args is a List<ChatMessage> with the current chat history. Remove or edit as nessisary.
// replace this with more sophisticated logic for your use-case, such as summarizing the chat history
for ( int i = 0 ; i < args . Count ; i ++ )
{
if ( args [ i ] . Role != ChatMessageRole . System )
{
args . RemoveAt ( i ) ;
return ;
}
}
} ; También es posible que desee utilizar un nuevo modelo con una mayor longitud de contexto. Puede hacer esto configurando chat.Model = Model.GPT4_Turbo o chat.Model = Model.ChatGPTTurbo_16k , etc.
Puede ver el uso del token a través de chat.MostRecentApiResult.Usage.PromptTokens y propiedades relacionadas.
Puede acceder al control completo de la API de chat utilizando OpenAIAPI.Chat.CreateChatCompletionAsync() y métodos relacionados.
async Task < ChatResult > CreateChatCompletionAsync ( ChatRequest request ) ;
// for example
var result = await api . Chat . CreateChatCompletionAsync ( new ChatRequest ( )
{
Model = Model . ChatGPTTurbo ,
Temperature = 0.1 ,
MaxTokens = 50 ,
Messages = new ChatMessage [ ] {
new ChatMessage ( ChatMessageRole . User , " Hello! " )
}
} )
// or
var result = api . Chat . CreateChatCompletionAsync ( " Hello! " ) ;
var reply = results . Choices [ 0 ] . Message ;
Console . WriteLine ( $" { reply . Role } : { reply . Content . Trim ( ) } " ) ;
// or
Console . WriteLine ( results ) ; Devuelve un ChatResult que es principalmente metadatos, así que use su método .ToString() para obtener el texto si todo lo que desea es el texto de respuesta del asistente.
También hay una API de transmisión Async que funciona de manera similar a los resultados de transmisión de punto final de finalización.
Con el nuevo Model.GPT4_Turbo o gpt-3.5-turbo-1106 , puede configurar ChatRequest.ResponseFormat en ChatRequest.ResponseFormats.JsonObject para habilitar el modo JSON. Cuando el modo JSON está habilitado, el modelo está limitado a generar solo cadenas que analizan el objeto JSON válido. Consulte https://platform.openai.com/docs/guides/text-generation/json-mode para obtener más detalles.
ChatRequest chatRequest = new ChatRequest ( )
{
Model = model ,
Temperature = 0.0 ,
MaxTokens = 500 ,
ResponseFormat = ChatRequest . ResponseFormats . JsonObject ,
Messages = new ChatMessage [ ] {
new ChatMessage ( ChatMessageRole . System , " You are a helpful assistant designed to output JSON. " ) ,
new ChatMessage ( ChatMessageRole . User , " Who won the world series in 2020? Return JSON of a 'wins' dictionary with the year as the numeric key and the winning team as the string value. " )
}
} ;
var results = await api . Chat . CreateChatCompletionAsync ( chatRequest ) ;
Console . WriteLine ( results ) ;
/* prints:
{
"wins": {
2020: "Los Angeles Dodgers"
}
}
*/ Las terminaciones son consideradas heredadas por OpenAI. Se accede a la API de finalización a través de OpenAIAPI.Completions :
async Task < CompletionResult > CreateCompletionAsync ( CompletionRequest request ) ;
// for example
var result = await api . Completions . CreateCompletionAsync ( new CompletionRequest ( " One Two Three One Two " , model : Model . CurieText , temperature : 0.1 ) ) ;
// or
var result = await api . Completions . CreateCompletionAsync ( " One Two Three One Two " , temperature : 0.1 ) ;
// or other convenience overloads Puede crear su CompletionRequest con anticipación o usar una de las sobrecargas auxiliar para conveniencia. Devuelve un CompletionResult que es principalmente metadatos, por lo que usa su método .ToString() para obtener el texto si todo lo que desea es la finalización.
La transmisión le permite obtener resultados si se generan, lo que puede ayudar a que su aplicación se sienta más receptiva, especialmente en modelos lentos como Davinci.
Usando los nuevos iteradores de Async C# 8.0:
IAsyncEnumerable < CompletionResult > StreamCompletionEnumerableAsync ( CompletionRequest request ) ;
// for example
await foreach ( var token in api . Completions . StreamCompletionEnumerableAsync ( new CompletionRequest ( " My name is Roger and I am a principal software engineer at Salesforce. This is my resume: " , Model . DavinciText , 200 , 0.5 , presencePenalty : 0.1 , frequencyPenalty : 0.1 ) ) )
{
Console . Write ( token ) ;
}O si usa .NET Framework clásico o C# <8.0:
async Task StreamCompletionAsync ( CompletionRequest request , Action < CompletionResult > resultHandler ) ;
// for example
await api . Completions . StreamCompletionAsync (
new CompletionRequest ( " My name is Roger and I am a principal software engineer at Salesforce. This is my resume: " , Model . DavinciText , 200 , 0.5 , presencePenalty : 0.1 , frequencyPenalty : 0.1 ) ,
res => ResumeTextbox . Text += res . ToString ( ) ) ;Las API de audio son texto a discurso, transcripción (discurso a texto) y traducción (texto no inglés a inglés).
Se accede a la API TTS a través de OpenAIAPI.TextToSpeech :
await api . TextToSpeech . SaveSpeechToFileAsync ( " Hello, brave new world! This is a test. " , outputPath ) ;
// You can open it in the defaul audio player like this:
Process . Start ( outputPath ) ; También puede especificar todos los parámetros de solicitud con un objeto TextToSpeechRequest :
var request = new TextToSpeechRequest ( )
{
Input = " Hello, brave new world! This is a test. " ,
ResponseFormat = ResponseFormats . AAC ,
Model = Model . TTS_HD ,
Voice = Voices . Nova ,
Speed = 0.9
} ;
await api . TextToSpeech . SaveSpeechToFileAsync ( request , " test.aac " ) ; En lugar de guardar en un archivo, puede obtener la transmisión de byte de audio con api.TextToSpeech.GetSpeechAsStreamAsync(request) :
using ( Stream result = await api . TextToSpeech . GetSpeechAsStreamAsync ( " Hello, brave new world! " , Voices . Fable ) )
using ( StreamReader reader = new StreamReader ( result ) )
{
// do something with the audio stream here
} La API de la transcripción de audio le permite generar texto desde audio, en cualquiera de los idiomas compatibles. Se accede a través de OpenAIAPI.Transcriptions :
string resultText = await api . Transcriptions . GetTextAsync ( " path/to/file.mp3 " ) ;Puede solicitar resultados detallados, lo que le dará información de segmento y a nivel de token, así como los metadatos estándar de OpenAI, como el tiempo de procesamiento:
AudioResultVerbose result = await api . Transcriptions . GetWithDetailsAsync ( " path/to/file.m4a " ) ;
Console . WriteLine ( result . ProcessingTime . TotalMilliseconds ) ; // 496ms
Console . WriteLine ( result . text ) ; // "Hello, this is a test of the transcription function."
Console . WriteLine ( result . language ) ; // "english"
Console . WriteLine ( result . segments [ 0 ] . no_speech_prob ) ; // 0.03712
// etcTambién puede solicitar resultados en formato SRT o VTT, que es útil para generar subtítulos para videos:
string result = await api . Transcriptions . GetAsFormatAsync ( " path/to/file.m4a " , AudioRequest . ResponseFormats . SRT ) ;Se pueden especificar parámetros adicionales como temperatura, indicador, lenguaje, etc.
// inline
result = await api . Transcriptions . GetTextAsync ( " conversation.mp3 " , " en " , " This is a transcript of a conversation between a medical doctor and her patient: " , 0.3 ) ;
// set defaults
api . Transcriptions . DefaultTranscriptionRequestArgs . Language = " en " ;En lugar de proporcionar un archivo local en el disco, puede proporcionar una transmisión de bytes de audio. Esto puede ser útil para transmitir audio desde el micrófono u otra fuente sin tener que escribir primero en el disco. No debe especificar un nombre de archivo, que no tiene que existir, pero que debe tener una extensión precisa para el tipo de audio que está enviando. OpenAI utiliza la extensión del nombre de archivo para determinar en qué formato se encuentra su transmisión de audio.
using ( var audioStream = File . OpenRead ( " path-here.mp3 " ) )
{
return await api . Transcriptions . GetTextAsync ( audioStream , " file.mp3 " ) ;
} Las traducciones le permiten transcribir el texto de cualquiera de los idiomas compatibles al inglés. Operai no admite traducir a ningún otro idioma, solo inglés. Se accede a través de OpenAIAPI.Translations . Admite toda la misma funcionalidad que las transcripciones.
string result = await api . Translations . GetTextAsync ( " chinese-example.m4a " ) ; Se accede a la API de incrustación a través de OpenAIAPI.Embeddings :
async Task < EmbeddingResult > CreateEmbeddingAsync ( EmbeddingRequest request ) ;
// for example
var result = await api . Embeddings . CreateEmbeddingAsync ( new EmbeddingRequest ( " A test text for embedding " , model : Model . AdaTextEmbedding ) ) ;
// or
var result = await api . Embeddings . CreateEmbeddingAsync ( " A test text for embedding " ) ;El resultado de incrustación contiene muchos metadatos, el vector real de los flotadores es en el resultado. Data []. Incrustación.
Para simplificar, puede solicitar directamente el vector de flotadores y desechar los metadatos adicionales con api.Embeddings.GetEmbeddingsAsync("test text here")
Se accede a la API de moderación a través de OpenAIAPI.Moderation :
async Task < ModerationResult > CreateEmbeddingAsync ( ModerationRequest request ) ;
// for example
var result = await api . Moderation . CallModerationAsync ( new ModerationRequest ( " A test text for moderating " , Model . TextModerationLatest ) ) ;
// or
var result = await api . Moderation . CallModerationAsync ( " A test text for moderating " ) ;
Console . WriteLine ( result . results [ 0 ] . MainContentFlag ) ; Los resultados están en .results[0] y tienen buenos métodos a ayuda de ayuda como FlaggedCategories y MainContentFlag .
Se accede al punto final de la API de archivos a través de OpenAIAPI.Files :
// uploading
async Task < File > UploadFileAsync ( string filePath , string purpose = " fine-tune " ) ;
// for example
var response = await api . Files . UploadFileAsync ( " fine-tuning-data.jsonl " ) ;
Console . Write ( response . Id ) ; //the id of the uploaded file
// listing
async Task < List < File > > GetFilesAsync ( ) ;
// for example
var response = await api . Files . GetFilesAsync ( ) ;
foreach ( var file in response )
{
Console . WriteLine ( file . Name ) ;
}También hay métodos para obtener contenido de archivo, eliminar un archivo, etc.
El punto final en sí aún no se ha implementado, pero se agregará pronto.
Se accede a la API de generación de imágenes Dall-E a través de OpenAIAPI.ImageGenerations :
async Task < ImageResult > CreateImageAsync ( ImageGenerationRequest request ) ;
// for example
var result = await api . ImageGenerations . CreateImageAsync ( new ImageGenerationRequest ( " A drawing of a computer writing a test " , 1 , ImageSize . _512 ) ) ;
// or
var result = await api . ImageGenerations . CreateImageAsync ( " A drawing of a computer writing a test " ) ;
Console . WriteLine ( result . Data [ 0 ] . Url ) ;El resultado de la imagen contiene una URL para una imagen en línea o una imagen codificada por Base64, dependiendo de la imagen de Generación de imágenes.
Use Dall-E 3 como este:
async Task < ImageResult > CreateImageAsync ( ImageGenerationRequest request ) ;
// for example
var result = await api . ImageGenerations . CreateImageAsync ( new ImageGenerationRequest ( " A drawing of a computer writing a test " , OpenAI_API . Models . Model . DALLE3 , ImageSize . _1024x1792 , " hd " ) ) ;
// or
var result = await api . ImageGenerations . CreateImageAsync ( " A drawing of a computer writing a test " , OpenAI_API . Models . Model . DALLE3 ) ;
Console . WriteLine ( result . Data [ 0 ] . Url ) ; Para usar el servicio Azure OpenAI, debe especificar el nombre de su recurso Azure OpenAI, así como su ID de implementación de modelos.
No tengo acceso al servicio Microsoft Azure OpenAI, por lo que no puedo probar esta funcionalidad. Si tiene acceso y puede probar, envíe un problema que describe sus resultados. Un PR con pruebas de integración también sería muy apreciado. Específicamente, no está claro para mí que especificar modelos funcione de la misma manera con Azure.
Consulte la documentación de Azure OpenAI y las capturas de pantalla detalladas en el #64 para obtener más información.
La configuración debe verse algo así para el servicio de Azure:
OpenAIAPI api = OpenAIAPI . ForAzure ( " YourResourceName " , " deploymentId " , " api-key " ) ;
api . ApiVersion = " 2023-03-15-preview " ; // needed to access chat endpoint on Azure Luego puede usar el objeto api como lo normal. También puede especificar que la APIAuthentication es cualquiera de las otras formas enumeradas en la sección de autenticación anterior. Actualmente, esta biblioteca solo admite el flujo API-Key, no el flujo AD.
A partir del 2 de abril de 2023, debe seleccionar manualmente la versión API 2023-03-15-preview como se muestra arriba para acceder al punto final de chat en Azure. Una vez que esto esté fuera de vista previa, actualizaré el valor predeterminado.
Puede especificar una IHttpClientFactory que se utilizará para las solicitudes HTTP, que permite ajustar las propiedades de solicitud HTTP, la agrupación de conexión y la burla. Detalles en #103.
OpenAIAPI api = new OpenAIAPI ( ) ;
api . HttpClientFactory = myIHttpClientFactoryObject ; Cada clase, método y propiedad tiene una documentación XML extensa, por lo que debería aparecer automáticamente en IntelliSense. Eso combinado con la documentación oficial de Operai debería ser suficiente para comenzar. No dude en abrir un problema aquí si tiene alguna pregunta. Una mejor documentación puede venir más tarde.
Dominio público CC-0
Esta biblioteca tiene licencia CC-0, en el dominio público. Puede usarlo para lo que quiera, pública o privada, sin preocuparse por el permiso o la licencia o lo que sea. Es solo un envoltorio alrededor de la API de Operai, por lo que aún debe obtener acceso a OpenAi desde ellos directamente. No estoy afiliado a OpenAi y esta biblioteca no está respaldada por ellos, solo tengo acceso beta y quería hacer una biblioteca C# para acceder a ella más fácilmente. Ojalá otros también encuentren esto útil. Siéntase libre de abrir un PR si hay algo que desee contribuir.