Microsoft m'a contacté à propos de la transition de cette bibliothèque vers une nouvelle bibliothèque officielle C # Openai et maintenant il est prêt à partir! À partir de la v2.0.0-bêta.3, la bibliothèque officielle a maintenant une couverture complète et restera à jour. Plus de détails dans le billet de blog ici: https://devblogs.microsoft.com/dotnet/openai-dotnet-library
Ce dépôt GitHub restera ici pour documenter ma version originale de la bibliothèque via la version 1.11, qui est également disponible sur Nuget également. ?
Une simple bibliothèque C # .NET Wrapper à utiliser avec l'API d'Openai. Plus de contexte sur mon blog. Ceci est ma bibliothèque d'emballage non officielle originale autour de l'API Openai.
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?" À partir de v2.0.0-bêta, cette bibliothèque a été adoptée par Microsoft. La nouvelle version officielle de la bibliothèque aura une couverture complète et restera entièrement à jour. Plus de détails dans le billet de blog ici: https://devblogs.microsoft.com/dotnet/openai-dotnet-library/ Ce repo github restera ici pour documenter ma version originale de la bibliothèque via la version 1.11, qui est toujours disponible sur NuGet également.
Cette bibliothèque est basée sur .NET Standard 2.0, il devrait donc fonctionner sur toutes les versions de .NET, du Framework .NET traditionnel> = 4.7.2 à .NET (Core)> = 3.0. Il devrait fonctionner sur les applications Console, WinForms, WPF, ASP.NET, Unity, Xamarin, etc. Il devrait fonctionner à travers Windows, Linux et Mac, et peut-être même mobile. Il y a des dépendances minimales et il est autorisé dans le domaine public.
Installez le package OpenAI v1.11 depuis Nuget. Voici comment via la ligne de commande:
Install-Package OpenAI - Version 1.11 . 0Il existe 3 façons de fournir vos clés API, par ordre de priorité:
APIAuthentication(string key).openai et contenant la ligne: OPENAI_API_KEY=sk-aaaabbbbbccccddddd Vous utilisez l' APIAuthentication lorsque vous initialisez l'API comme indiqué:
// 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 fileVous pouvez éventuellement inclure une Openaiorganization (OpenAI_ORANIISATION dans le fichier Env ou Config) spécifiant l'organisation utilisée pour une demande d'API. L'utilisation de ces demandes d'API comptera contre le quota d'abonnement de l'organisation spécifiée. Les ID d'organisation peuvent être trouvés sur la page des paramètres de votre organisation.
// for example
OpenAIAPI api = new OpenAIAPI ( new APIAuthentication ( " YOUR_API_KEY " , " org-yourOrgHere " ) ) ; L'API de chat est accessible via OpenAIAPI.Chat . Il existe deux façons d'utiliser le point de terminaison du chat, soit via des conversations simplifiées, soit avec les méthodes complètes de demande / réponse.
La classe de conversation vous permet d'interagir facilement avec Chatgpt en ajoutant des messages à un chat et en demandant à Chatgpt de répondre.
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 } " ) ;
} Le streaming vous permet d'obtenir des résultats qu'ils sont générés, ce qui peut aider votre application à vous sentir plus réactif.
Utilisation des nouveaux itérateurs asynchronisés 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 ) ;
}Ou si vous utilisez un framework .net classique ou C # <8.0:
var chat = api . Chat . CreateConversation ( ) ;
chat . AppendUserInput ( " How to make a hamburger? " ) ;
await chat . StreamResponseFromChatbotAsync ( res =>
{
Console . Write ( res ) ;
} ) ; Vous pouvez envoyer des images au chat pour utiliser le nouveau modèle de vision GPT-4. Cela ne fonctionne qu'avec le modèle Model.GPT4_Vision . Veuillez consulter https://platform.openai.com/docs/guides/vision pour plus d'informations et de limitations.
// 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 l'historique de la conversation de chat devient trop longtemps, il peut ne pas s'adapter à la longueur du contexte du modèle. Par défaut, le (s) message (s) non-système le plus ancien sera supprimé de l'historique de chat et l'appel API sera réévalué. Vous pouvez désactiver cela en définissant chat.AutoTruncateOnContextLengthExceeded = false , ou vous pouvez remplacer l'algorithme de troncature comme ceci:
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 ;
}
}
} ; Vous pouvez également utiliser un nouveau modèle avec une longueur de contexte plus grande. Vous pouvez le faire en définissant chat.Model = Model.GPT4_Turbo ou chat.Model = Model.ChatGPTTurbo_16k , etc.
Vous pouvez voir l'utilisation de jetons via chat.MostRecentApiResult.Usage.PromptTokens et les propriétés connexes.
Vous pouvez accéder à un contrôle complet de l'API de chat en utilisant l' OpenAIAPI.Chat.CreateChatCompletionAsync() et des méthodes connexes.
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 ) ; Il renvoie un ChatResult qui est principalement des métadonnées, alors utilisez sa méthode .ToString() pour obtenir le texte si tout ce que vous voulez est le texte de réponse de l'assistant.
Il existe également une API de streaming asynchrone qui fonctionne de manière similaire aux résultats de streaming de point de terminaison complétés.
Avec les nouveaux modèles Model.GPT4_Turbo ou gpt-3.5-turbo-1106 , vous pouvez définir le ChatRequest.ResponseFormat sur ChatRequest.ResponseFormats.JsonObject pour activer le mode JSON. Lorsque le mode JSON est activé, le modèle est contraint de générer uniquement des chaînes qui analysent l'objet JSON valide. Voir https://platform.openai.com/docs/guides/text-generation/json-mode pour plus de détails.
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"
}
}
*/ Les compléments sont considérés comme hérités par OpenAI. L'API d'achèvement est accessible via 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 Vous pouvez créer votre point de vue CompletionRequest ou utiliser l'une des surcharges d'assistance pour plus de commodité. Il renvoie une CompletionResult qui est principalement des métadonnées, alors utilisez sa méthode .ToString() pour obtenir le texte si tout ce que vous voulez est l'achèvement.
Le streaming vous permet d'obtenir des résultats qu'ils sont générés, ce qui peut aider votre application à vous sentir plus réactif, en particulier sur des modèles lents comme Davinci.
Utilisation des nouveaux itérateurs asynchronisés 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 ) ;
}Ou si vous utilisez un framework .net classique ou 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 ( ) ) ;Les API audio sont du texte à la parole, de la transcription (discours au texte) et de la traduction (discours non anglophone en texte anglais).
L'API TTS est accessible via 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 ) ; Vous pouvez également spécifier tous les paramètres de demande avec un objet 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 " ) ; Au lieu d'enregistrer dans un fichier, vous pouvez obtenir un flux de byte audio avec 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
} L'API de transcription audio vous permet de générer du texte à partir de l'audio, dans l'une des langues prises en charge. Il est accessible via OpenAIAPI.Transcriptions :
string resultText = await api . Transcriptions . GetTextAsync ( " path/to/file.mp3 " ) ;Vous pouvez demander des résultats verbeux, qui vous donneront des informations au niveau du segment et du jeton, ainsi que les métadonnées OpenAI standard telles que le temps de traitement:
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
// etcVous pouvez également demander des résultats au format SRT ou VTT, qui est utile pour générer des sous-titres pour les vidéos:
string result = await api . Transcriptions . GetAsFormatAsync ( " path/to/file.m4a " , AudioRequest . ResponseFormats . SRT ) ;Des paramètres supplémentaires tels que la température, l'invite, le langage, etc. peuvent être spécifiés par la demande ou par défaut:
// 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 " ;Au lieu de fournir un fichier local sur le disque, vous pouvez fournir un flux d'octets audio. Cela peut être utile pour diffuser l'audio à partir du microphone ou d'une autre source sans avoir à écrire d'abord sur le disque. Veuillez ne pas spécifier un nom de fichier, qui n'a pas à exister, mais qui doit avoir une extension précise pour le type d'audio que vous envoyez. OpenAI utilise l'extension de nom de fichier pour déterminer le format dans lequel se trouve votre flux audio.
using ( var audioStream = File . OpenRead ( " path-here.mp3 " ) )
{
return await api . Transcriptions . GetTextAsync ( audioStream , " file.mp3 " ) ;
} Les traductions vous permettent de transcrire du texte de l'une des langues prises en charge vers l'anglais. OpenAI ne prend pas en charge la traduction dans une autre langue, seulement l'anglais. Il est accessible via OpenAIAPI.Translations . Il prend en charge toutes les mêmes fonctionnalités que les transcriptions.
string result = await api . Translations . GetTextAsync ( " chinese-example.m4a " ) ; L'API d'incorporation est accessible via 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 " ) ;Le résultat d'intégration contient beaucoup de métadonnées, le vecteur réel des flotteurs est dans le résultat.data [].
Pour plus de simplicité, vous pouvez directement demander le vecteur de flotteurs et dégager les métadonnées supplémentaires avec api.Embeddings.GetEmbeddingsAsync("test text here")
L'API de modération est accessible via 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 ) ; Les résultats sont dans .results[0] et ont de belles méthodes d'assistance comme FlaggedCategories et MainContentFlag .
Le point de terminaison de l'API des fichiers est accessible via 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 ) ;
}Il existe également des méthodes pour obtenir le contenu des fichiers, supprimer un fichier, etc.
Le point de terminaison du réglage fin n'a pas encore été mis en œuvre, mais sera ajouté bientôt.
L'API de génération d'images de Dall-E est accessible via 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 ) ;Le résultat de l'image contient une URL pour une image en ligne ou une image codée Base64, selon ImageGenerationRequest.ResponseFormat (URL est la valeur par défaut).
Utilisez Dall-E 3 comme ceci:
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 ) ; Pour utiliser le service Azure OpenAI, vous devez spécifier le nom de votre ressource Azure OpenAI ainsi que votre ID de déploiement de modèle.
Je n'ai pas accès au service Microsoft Azure OpenAI, donc je ne peux pas tester cette fonctionnalité. Si vous avez accès et que vous pouvez tester, veuillez soumettre un problème décrivant vos résultats. Un RP avec des tests d'intégration serait également grandement apprécié. Plus précisément, il n'est pas clair pour moi que la spécification des modèles fonctionne de la même manière avec Azure.
Reportez-vous à la documentation Azure OpenAI et à des captures d'écran détaillées dans # 64 pour plus d'informations.
La configuration doit ressembler à ceci pour le service Azure:
OpenAIAPI api = OpenAIAPI . ForAzure ( " YourResourceName " , " deploymentId " , " api-key " ) ;
api . ApiVersion = " 2023-03-15-preview " ; // needed to access chat endpoint on Azure Vous pouvez ensuite utiliser l'objet api comme normal. Vous pouvez également spécifier que l' APIAuthentication est l'une des autres façons énumérées dans la section d'authentification ci-dessus. Actuellement, cette bibliothèque ne prend en charge que le flux de touche API, pas le flux d'annonces.
À partir du 2 avril 2023, vous devez sélectionner manuellement la version API 2023-03-15-preview comme indiqué ci-dessus pour accéder au point de terminaison du chat sur Azure. Une fois que cela est hors de prévisualisation, je mettrai à jour la valeur par défaut.
Vous pouvez spécifier un IHttpClientFactory à utiliser pour les demandes HTTP, ce qui permet de modifier les propriétés de la demande HTTP, la mise en commun de connexions et la moquerie. Détails dans # 103.
OpenAIAPI api = new OpenAIAPI ( ) ;
api . HttpClientFactory = myIHttpClientFactoryObject ; Chaque classe, méthode et propriété a une documentation XML importante, elle devrait donc apparaître automatiquement dans Intellisense. Cela combiné avec la documentation officielle de l'OpenAI devrait être suffisant pour commencer. N'hésitez pas à ouvrir un problème ici si vous avez des questions. Une meilleure documentation peut arriver plus tard.
Domaine public CC-0
Cette bibliothèque est sous licence CC-0, dans le domaine public. Vous pouvez l'utiliser pour ce que vous voulez, publiquement ou en privé, sans vous soucier de l'autorisation ou de l'octroi de licences ou autre chose. C'est juste un wrapper autour de l'API OpenAI, vous devez donc avoir accès à Openai directement à partir d'eux directement. Je ne suis pas affilié à Openai et cette bibliothèque n'est pas approuvée par eux, j'ai juste un accès bêta et je voulais faire une bibliothèque C # pour y accéder plus facilement. J'espère que d'autres trouvent également cela utile. N'hésitez pas à ouvrir un RP s'il y a quelque chose que vous voulez contribuer.