Skip to content

Commit

Permalink
Added support for GPT 3.5, 4.0, and audio translations and transcript… (
Browse files Browse the repository at this point in the history
#43)

* Added support for GPT 3.5, 4.0, and audio translations and transcriptions.

* Added tags to nuget package for gpt-3.5, gpt-4, and whisper.

* Addressed null reference issues.
  • Loading branch information
johniwasz committed Mar 18, 2023
1 parent 82f611b commit c6dba7e
Show file tree
Hide file tree
Showing 28 changed files with 1,421 additions and 129 deletions.
162 changes: 125 additions & 37 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ A simple light-weight library that wraps the GPT-3 API with support for dependen

Supported features include:

- GPT 3.5 Turbo and Chat Completions
- Audio Transcription and Translation (Whisper API)
- Completions
- Edits
- Files
Expand Down Expand Up @@ -49,9 +51,71 @@ Configure `IChatGPTClient` service:
services.AddScoped<IChatGPTClient, ChatGPTClient>();
```

## Chat Completions

Chat completions are a special type of completion that are optimized for chat. They are designed to be used in a conversational context.

### Chat Completion Quickstart

This shows a usage of the GPT-3.5 Turbo model.

``` C#
using Whetstone.ChatGPT;
using Whetstone.ChatGPT.Models;

. . .

IChatGPTClient client = new ChatGPTClient("YOURAPIKEY");

var gptRequest = new ChatGPTCompletionRequest
{
Model = ChatGPT35Models.Davinci003,
Prompt = "How is the weather?"
};

var gptRequest = new ChatGPTChatCompletionRequest
{
Model = ChatGPT35Models.Turbo,
Messages = new List<ChatGPTChatCompletionMessage>()
{
new ChatGPTChatCompletionMessage()
{
Role = MessageRole.System,
Content = "You are a helpful assistant."
},
new ChatGPTChatCompletionMessage()
{
Role = MessageRole.User,
Content = "Who won the world series in 2020?"
},
new ChatGPTChatCompletionMessage()
{
Role = MessageRole.Assistant,
Content = "The Los Angeles Dodgers won the World Series in 2020."
},
new ChatGPTChatCompletionMessage()
{
Role = MessageRole.User,
Content = "Where was it played?"
}
},
Temperature = 0.9f,
MaxTokens = 100
};

using IChatGPTClient client = new ChatGPTClient("YOURAPIKEY");

var response = await client.CreateChatCompletionAsync(gptRequest);

Console.WriteLine(response.GetCompletionText());

```

GPT-4 models can also be used provided your account has been granted access to the [limited beta](https://openai.com/waitlist/gpt-4).

## Completion

GPT-3 Completions use [models](https://beta.openai.com/docs/models) to answer a wide variety of tasks, including but not limited to classification, sentiment analysis, answering questions, etc.
Completions use [models](https://beta.openai.com/docs/models) to answer a wide variety of tasks, including but not limited to classification, sentiment analysis, answering questions, etc.

### Completion Quickstart

Expand All @@ -63,20 +127,20 @@ using Whetstone.ChatGPT.Models;

. . .

IChatGPTClient client = new ChatGPTClient("YOURAPIKEY");

var gptRequest = new ChatGPTCompletionRequest
{
Model = ChatGPTCompletionModels.Davinci,
Model = ChatGPT35Models.Davinci003,
Prompt = "How is the weather?"
};

using IChatGPTClient client = new ChatGPTClient("YOURAPIKEY");

var response = await client.CreateCompletionAsync(gptRequest);

Console.WriteLine(response.GetCompletionText());
```

GPT-3 is not deterministic. One of the test runs of the sample above returned:
GPT-3.5 is not deterministic. One of the test runs of the sample above returned:

> The weather can vary greatly depending on location. In general, you can expect temperatures to be moderate and climate to be comfortable, but it is always best to check the forecast for your specific area.
Expand All @@ -102,7 +166,7 @@ using Whetstone.ChatGPT.Models;

. . .

IChatGPTClient client = new ChatGPTClient("YOURAPIKEY");
using IChatGPTClient client = new ChatGPTClient("YOURAPIKEY");

var gptEditRequest = new ChatGPTCreateEditRequest
{
Expand Down Expand Up @@ -146,54 +210,52 @@ ChatGPTUploadFileRequest? uploadRequest = new ChatGPTUploadFileRequest
};

ChatGPTFileInfo? uploadedFileInfo;
using (IChatGPTClient client = new ChatGPTClient("YOURAPIKEY"))
{
uploadedFileInfo = await client.UploadFileAsync(uploadRequest);
}

IChatGPTClient client = new ChatGPTClient("YOURAPIKEY");

uploadedFileInfo = await client.UploadFileAsync(uploadRequest);

```

## Fine Tuning Quickstart

Once the file has been created, get the fileId, and reference it when creating a new fine tuning.

```C#
using (IChatGPTClient client = new ChatGPTClient("YOURAPIKEY"))
{
var fileList = await client.ListFilesAsync();
var foundFile = fileList.Data.First(x => x.Filename.Equals("finetuningsample.jsonl"));
IChatGPTClient client = new ChatGPTClient("YOURAPIKEY");

ChatGPTCreateFineTuneRequest tuningRequest = new ChatGPTCreateFineTuneRequest
{
TrainingFileId = foundFile.Id
};
var fileList = await client.ListFilesAsync();
var foundFile = fileList.Data.First(x => x.Filename.Equals("finetuningsample.jsonl"));

ChatGPTFineTuneJob? tuneResponse = await client.CreateFineTuneAsync(tuningRequest);
ChatGPTCreateFineTuneRequest tuningRequest = new ChatGPTCreateFineTuneRequest
{
TrainingFileId = foundFile.Id
};

string fineTuneId = tuneResponse.Id;
ChatGPTFineTuneJob? tuneResponse = await client.CreateFineTuneAsync(tuningRequest);

}
string fineTuneId = tuneResponse.Id;

```

Processing the fine tuning request will take some time. Once it finishes, the __Status__ will report "succeeded" and it's ready to be used in a completion request.

```C#
using (IChatGPTClient client = new ChatGPTClient("YOURAPIKEY"))
{
ChatGPTFineTuneJob? tuneResponse = await client.RetrieveFineTuneAsync("FINETUNEID");
using IChatGPTClient client = new ChatGPTClient("YOURAPIKEY");

ChatGPTFineTuneJob? tuneResponse = await client.RetrieveFineTuneAsync("FINETUNEID");

if(tuneResponse.Status.Equals("succeeded"))
{
if(tuneResponse.Status.Equals("succeeded"))
{
var gptRequest = new ChatGPTCompletionRequest
{
Model = ChatGPTCompletionModels.Davinci,
Prompt = "How is the weather?"
Model = ChatGPTCompletionModels.Davinci,
Prompt = "How is the weather?"
};

var response = await client.CreateCompletionAsync(gptRequest);

Console.WriteLine(response.GetCompletionText());
}
}

```
Expand All @@ -210,15 +272,41 @@ ChatGPTCreateImageRequest imageRequest = new()
ResponseFormat = CreatedImageFormat.Base64
};

using (IChatGPTClient client = new ChatGPTClient("YOURAPIKEY"))
{
ChatGPTImageResponse? imageResponse = await client.CreateImageAsync(imageRequest);
using IChatGPTClient client = new ChatGPTClient("YOURAPIKEY");

var imageData = imageResponse?.Data[0];
ChatGPTImageResponse? imageResponse = await client.CreateImageAsync(imageRequest);

if (imageData != null)
{
byte[] imageBytes = await client.DownloadImageAsync(imageData);
}
var imageData = imageResponse?.Data[0];

if (imageData != null)
{
byte[] imageBytes = await client.DownloadImageAsync(imageData);
}
```

## Audio Transcription Quickstart

Her's an example that transcribes an audio file using the Whisper.

```C#

string audioFile = @"audiofiles\transcriptiontest.mp3";

byte[] fileContents = File.ReadAllBytes(audioFile);
ChatGPTFileContent gptFile = new ChatGPTFileContent
{
FileName = audioFile,
Content = fileContents
};

ChatGPTAudioTranscriptionRequest? transcriptionRequest = new ChatGPTAudioTranscriptionRequest
{
File = gptFile
};

using IChatGPTClient client = new ChatGPTClient("YOURAPIKEY");

ChatGPTAudioResponse? audioResponse = await client.CreateTranscriptionAsync(transcriptionRequest, true);

Console.WriteLine(response?.Text);
```
88 changes: 88 additions & 0 deletions src/Whetstone.ChatGPT.Test/AudioWhisperTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Whetstone.ChatGPT.Models;
using static System.Net.Mime.MediaTypeNames;

namespace Whetstone.ChatGPT.Test
{
public class AudioWhisperTests
{
[Fact(Skip = "reduce testing costs")]
public async Task TranscribeFileAsync()
{
ChatGPTAudioTranscriptionRequest? uploadRequest = new ChatGPTAudioTranscriptionRequest
{
File = GetAudioFileContent()
};
using IChatGPTClient client = ChatGPTTestUtilties.GetClient();

ChatGPTAudioResponse? audioResponse = await client.CreateTranscriptionAsync(uploadRequest, true);

string? text = audioResponse?.Text;

Assert.NotNull(text);
}

[Fact(Skip = "reduce testing costs")]
public async Task TranscribeFileToTextAsync()
{
ChatGPTAudioTranscriptionRequest? uploadRequest = new ChatGPTAudioTranscriptionRequest
{
File = GetAudioFileContent()
};
using IChatGPTClient client = ChatGPTTestUtilties.GetClient();

string? textReponse = await client.CreateTranscriptionAsync(uploadRequest, AudioResponseFormatText.WebVtt);

Assert.NotNull(textReponse);
}

[Fact(Skip = "reduce testing costs")]
public async Task TranslateFileAsync()
{
ChatGPTAudioTranslationRequest? uploadRequest = new ChatGPTAudioTranslationRequest
{
File = GetAudioFileContent()
};
using IChatGPTClient client = ChatGPTTestUtilties.GetClient();

ChatGPTAudioResponse? audioResponse = await client.CreateTranslationAsync(uploadRequest, true);

string? text = audioResponse?.Text;

Assert.NotNull(text);
}

[Fact(Skip = "reduce testing costs")]
public async Task TranslateFileToTextAsync()
{
ChatGPTAudioTranslationRequest? uploadRequest = new ChatGPTAudioTranslationRequest
{
File = GetAudioFileContent()
};
using IChatGPTClient client = ChatGPTTestUtilties.GetClient();

string? textReponse = await client.CreateTranslationAsync(uploadRequest, AudioResponseFormatText.WebVtt);

Assert.NotNull(textReponse);
}


private ChatGPTFileContent GetAudioFileContent()
{
string audioFile = @"audiofiles\transcriptiontest.mp3";

byte[] fileContents = File.ReadAllBytes(audioFile);
ChatGPTFileContent gptFile = new ChatGPTFileContent
{
FileName = audioFile,
Content = fileContents
};

return gptFile;
}
}
}
Loading

0 comments on commit c6dba7e

Please sign in to comment.