A Microsoft me procurou sobre a transição desta biblioteca para uma nova biblioteca oficial do C# Openai e agora está pronto para ir! Começando com v2.0.0-beta.3, a biblioteca oficial agora tem cobertura total e permanecerá atualizada. Mais detalhes na postagem do blog aqui: https://devblogs.microsoft.com/dotnet/openai-dotnet-library
Este repositório do GitHub permanecerá aqui para documentar minha versão original da biblioteca através da versão 1.11, que ainda está disponível no NUGET. ?
Uma biblioteca de wrapper C# .NET simples para usar com a API do OpenAI. Mais contexto no meu blog. Esta é a minha biblioteca de invólucro não oficial original em torno da 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?" Começando com v2.0.0-beta, esta biblioteca foi adotada pela Microsoft. A nova versão oficial da biblioteca terá cobertura completa e permanecerá totalmente atualizado. Mais detalhes na postagem do blog aqui: https://devblogs.microsoft.com/dotnet/openai-dotnet-library/ Este repo Github permanecerá aqui para documentar minha versão original da biblioteca através da versão 1.11, que ainda está disponível no NUGET também.
Esta biblioteca é baseada no padrão .NET 2.0, portanto, deve funcionar em todas as versões do .NET, a partir da estrutura .NET tradicional> = 4.7.2 a .NET (CORE)> = 3.0. Ele deve funcionar em aplicativos de console, WinForms, WPF, ASP.NET, Unity, Xamarin, etc. Deve funcionar no Windows, Linux e Mac e possivelmente até móveis. Existem dependências mínimas e licenciadas no domínio público.
Instale o pacote OpenAI v1.11 da NUGET. Veja como via CommandLine:
Install-Package OpenAI - Version 1.11 . 0Existem três maneiras de fornecer suas chaves da API, em ordem de precedência:
APIAuthentication(string key).openai e contendo a linha: OPENAI_API_KEY=sk-aaaabbbbbccccddddd Você usa a APIAuthentication ao inicializar a API como mostrado:
// 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, você pode incluir uma organização aberta (OpenAI_organization no arquivo Env ou Config), especificando qual organização é usada para uma solicitação de API. O uso dessas solicitações de API será contado com a cota de assinatura da organização especificada. Os IDs da organização podem ser encontrados na página de configurações da sua organização.
// for example
OpenAIAPI api = new OpenAIAPI ( new APIAuthentication ( " YOUR_API_KEY " , " org-yourOrgHere " ) ) ; A API de bate -papo é acessada via OpenAIAPI.Chat . Existem duas maneiras de usar o terminal de bate -papo, por meio de conversas simplificadas ou com os métodos completos de solicitação/resposta.
A aula de conversa permite que você interaja facilmente com o ChatGPT adicionando mensagens a um bate -papo e pedindo ao 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 } " ) ;
} O streaming permite que você obtenha resultados é que eles são gerados, o que pode ajudar seu aplicativo a se sentir mais responsivo.
Usando os novos iteradores C# 8.0 Async:
var chat = api . Chat . CreateConversation ( ) ;
chat . AppendUserInput ( " How to make a hamburger? " ) ;
await foreach ( var res in chat . StreamResponseEnumerableFromChatbotAsync ( ) )
{
Console . Write ( res ) ;
}Ou se estiver usando a estrutura .NET clássica ou C# <8.0:
var chat = api . Chat . CreateConversation ( ) ;
chat . AppendUserInput ( " How to make a hamburger? " ) ;
await chat . StreamResponseFromChatbotAsync ( res =>
{
Console . Write ( res ) ;
} ) ; Você pode enviar imagens para o bate-papo para usar o novo modelo GPT-4 Vision. Isso funciona apenas com o modelo Model.GPT4_Vision . Consulte https://platform.openai.com/docs/guides/vision para obter mais informações e limitações.
// 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 " ) ) ; Se o histórico de conversas de bate -papo demorar muito, pode não se encaixar na duração do contexto do modelo. Por padrão, a (s) mensagem (s) mais antiga (s) não-sistema será removida do histórico de bate-papo e a chamada da API será julgada. Você pode desativar isso definindo chat.AutoTruncateOnContextLengthExceeded = false , ou você pode substituir o algoritmo de truncamento 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 ;
}
}
} ; Você também pode usar um novo modelo com uma duração de contexto maior. Você pode fazer isso definindo chat.Model = Model.GPT4_Turbo ou chat.Model = Model.ChatGPTTurbo_16k , etc.
Você pode ver o uso do token via chat.MostRecentApiResult.Usage.PromptTokens e propriedades relacionadas.
Você pode acessar o controle total da API de bate -papo usando o OpenAIAPI.Chat.CreateChatCompletionAsync() e 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 ) ; Ele retorna um ChatResult que é principalmente metadados, então use seu método .ToString() para obter o texto se tudo o que você deseja é o texto de resposta do assistente.
Há também uma API de streaming assíncrona que funciona de maneira semelhante aos resultados do streaming de terminal de conclusão.
Com os novos modelos Model.GPT4_Turbo ou gpt-3.5-turbo-1106 , você pode definir o ChatRequest.ResponseFormat como ChatRequest.ResponseFormats.JsonObject para ativar o modo JSON. Quando o modo JSON está ativado, o modelo é restrito a gerar apenas seqüências de caracteres que analisam o objeto JSON válido. Consulte https://platform.openai.com/docs/guides/text-generação/json-mode para obter mais detalhes.
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"
}
}
*/ As conclusões são consideradas legado pelo OpenAI. A API de conclusão é acessada 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 Você pode criar sua CompletionRequest o tempo antes do tempo ou usar uma das sobrecargas do ajudante por conveniência. Ele retorna um CompletionResult que é principalmente metadados; portanto, use seu método .ToString() para obter o texto se tudo o que você deseja é a conclusão.
O streaming permite que você obtenha resultados é que eles são gerados, o que pode ajudar seu aplicativo a se sentir mais responsivo, especialmente em modelos lentos como o DaVinci.
Usando os novos iteradores C# 8.0 Async:
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 se estiver usando a estrutura .NET clássica 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 ( ) ) ;As APIs de áudio são texto para fala, transcrição (fala para texto) e tradução (discurso não inglês para texto em inglês).
A API TTS é acessada 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 ) ; Você também pode especificar todos os parâmetros de solicitação com um 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 " ) ; Em vez de salvar em um arquivo, você pode obter um fluxo de bytes de áudio com 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
} A API de transcrição de áudio permite gerar texto a partir de áudio, em qualquer um dos idiomas suportados. É acessado via OpenAIAPI.Transcriptions :
string resultText = await api . Transcriptions . GetTextAsync ( " path/to/file.mp3 " ) ;Você pode solicitar resultados detalhados, o que fornecerá informações de segmento e nível de token, bem como os metadados do OpenAI padrão, como o tempo de processamento:
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
// etcVocê também pode solicitar resultados no formato SRT ou VTT, que é útil para gerar legendas para vídeos:
string result = await api . Transcriptions . GetAsFormatAsync ( " path/to/file.m4a " , AudioRequest . ResponseFormats . SRT ) ;Parâmetros adicionais, como temperatura, prompt, idioma, etc, podem ser especificados por solicitação ou como padrão:
// 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 " ;Em vez de fornecer um arquivo local no disco, você pode fornecer um fluxo de bytes de áudio. Isso pode ser útil para transmitir áudio do microfone ou de outra fonte sem precisar gravar primeiro no disco. Por favor, não você deve especificar um nome de arquivo, que não precisa existir, mas que deve ter uma extensão precisa para o tipo de áudio que você está enviando. O OpenAI usa a extensão do nome do arquivo para determinar em que formato seu fluxo de áudio está.
using ( var audioStream = File . OpenRead ( " path-here.mp3 " ) )
{
return await api . Transcriptions . GetTextAsync ( audioStream , " file.mp3 " ) ;
} As traduções permitem transcrever o texto de qualquer um dos idiomas suportados para o inglês. O OpenAI não apóia a tradução para nenhum outro idioma, apenas o inglês. É acessado via OpenAIAPI.Translations . Ele suporta todas as mesmas funcionalidades que as transcrições.
string result = await api . Translations . GetTextAsync ( " chinese-example.m4a " ) ; A API de incorporação é acessada 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 " ) ;O resultado da incorporação contém muitos metadados, o vetor real de carros alegóricos está em resultado.datos []. Incorporação.
Por simplicidade, você pode solicitar diretamente o vetor de carros alegóricos e desmontar os metadados extras com api.Embeddings.GetEmbeddingsAsync("test text here")
A API de moderação é acessada 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 ) ; Os resultados são em .results[0] e têm belos métodos de auxiliar, como FlaggedCategories e MainContentFlag .
O endpoint da API de arquivos é acessado 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 ) ;
}Também existem métodos para obter conteúdo de arquivo, excluir um arquivo, etc.
O ponto final de ajuste fino ainda não foi implementado, mas será adicionado em breve.
A API de geração de imagem Dall-E é acessada 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 ) ;O resultado da imagem contém um URL para uma imagem on-line ou uma imagem codificada pela base64, dependendo do ImageGenationRequest.ResponseFormat (URL é o padrão).
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 o serviço Azure Openai, você precisa especificar o nome do seu recurso do Azure OpenAI, bem como o seu ID de implantação de modelo.
Não tenho acesso ao serviço Microsoft Azure OpenAi, por isso não consigo testar essa funcionalidade. Se você tiver acesso e pode testar, envie um problema descrevendo seus resultados. Um PR com testes de integração também seria muito apreciado. Especificamente, não está claro para mim que a especificação de modelos funciona da mesma maneira com o Azure.
Consulte a documentação do Azure OpenAi e as capturas de tela detalhadas em #64 para obter mais informações.
A configuração deve parecer algo assim para o serviço do Azure:
OpenAIAPI api = OpenAIAPI . ForAzure ( " YourResourceName " , " deploymentId " , " api-key " ) ;
api . ApiVersion = " 2023-03-15-preview " ; // needed to access chat endpoint on Azure Você pode usar o objeto api como o normal. Você também pode especificar a APIAuthentication é qualquer uma das outras maneiras listadas na seção de autenticação acima. Atualmente, esta biblioteca suporta apenas o fluxo da tecla API, não o fluxo de anúncios.
Em 2 de abril de 2023, você precisa selecionar manualmente a versão 2023-03-15-preview como mostrado acima, para acessar o terminal de bate-papo no Azure. Quando isso estiver fora de visualização, atualizarei o padrão.
Você pode especificar um IHttpClientFactory a ser usado para solicitações HTTP, o que permite aprimorando propriedades de solicitação HTTP, pool de conexões e zombaria. Detalhes em #103.
OpenAIAPI api = new OpenAIAPI ( ) ;
api . HttpClientFactory = myIHttpClientFactoryObject ; Cada classe, método e propriedade possui extensa documentação XML, portanto, deve aparecer automaticamente no IntelliSense. Isso combinado com a documentação oficial do Openai deve ser suficiente para começar. Sinta -se à vontade para abrir um problema aqui se tiver alguma dúvida. Melhor documentação pode vir mais tarde.
CC-0 Domínio Público
Esta biblioteca é licenciada CC-0, no domínio público. Você pode usá -lo para o que quiser, publicamente ou privado, sem se preocupar com permissão ou licenciamento ou qualquer outra coisa. É apenas uma embalagem em torno da API Openai, então você ainda precisa ter acesso ao OpenAI diretamente deles. Não sou afiliado ao OpenAI e esta biblioteca não é endossada por eles, apenas tenho acesso beta e queria fazer uma biblioteca C# para acessá -la com mais facilidade. Espero que outros achem isso útil também. Sinta -se à vontade para abrir um PR se houver algo que você queira contribuir.