-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathPodcastCopilot.cs
155 lines (125 loc) · 6.34 KB
/
PodcastCopilot.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
using System.Web;
using Azure.AI.OpenAI;
using Azure;
using Newtonsoft.Json.Linq;
using OpenAI.Chat;
using OpenAI.Audio;
using OpenAI.Images;
namespace PodcastAppAPI
{
public class PodcastCopilot
{
//Initialize Endpoints and Key
static string endpointSC = Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT_SC");
static string keySC = Environment.GetEnvironmentVariable("AZURE_OPENAI_KEY_SC");
static string bingSearchUrl = "https://api.bing.microsoft.com/v7.0/search";
static string bingSearchKey = Environment.GetEnvironmentVariable("BING_SEARCH_KEY");
//Instantiate OpenAI Client
static AzureOpenAIClient azureOpenAIClient = new AzureOpenAIClient(
new Uri(endpointSC),
new AzureKeyCredential(keySC));
//Get Audio Transcription
public static async Task<string> GetTranscription(string podcastUrl)
{
var decodededUrl = HttpUtility.UrlDecode(podcastUrl);
HttpClient httpClient = new HttpClient();
Stream audioStreamFromBlob = await httpClient.GetStreamAsync(decodededUrl);
AudioClient client = azureOpenAIClient.GetAudioClient("whisper");
AudioTranscription audioTranscription =
await client.TranscribeAudioAsync(audioStreamFromBlob, "file.mp3");
return audioTranscription.Text;
}
//Extract Guest Name from transcription
public static async Task<string> GetGuestName(string transcription)
{
ChatClient client = azureOpenAIClient.GetChatClient("gpt4");
ChatCompletion chatCompletion = await client.CompleteChatAsync(
[
new SystemChatMessage("Extract only the guest name on the Beyond the Tech podcast from the following transcript. Beyond the Tech is hosted by Kevin Scott, so Kevin Scott will never be the guest."),
new UserChatMessage(transcription)
]);
return chatCompletion.ToString();
}
//Get Guest Bio from Bing
public static async Task<string> GetGuestBio(string guestName)
{
var client = new HttpClient();
client.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", bingSearchKey);
HttpResponseMessage response = await client.GetAsync($"{bingSearchUrl}?q={guestName}");
string responseBody = await response.Content.ReadAsStringAsync();
// Parse responseBody as JSON and extract the bio.
JObject searchResults = JObject.Parse(responseBody);
var bio = searchResults["webPages"]["value"][0]["snippet"].ToString();
return bio;
}
//Create Social Media Blurb
public static async Task<string> GetSocialMediaBlurb(string transcription, string bio)
{
ChatClient client = azureOpenAIClient.GetChatClient("gpt4");
ChatCompletion chatCompletion = await client.CompleteChatAsync(
[
new SystemChatMessage(
@"You are a helpful large language model that can create a LinkedIn
promo blurb for episodes of the podcast Behind the Tech, when given
transcripts of the podcasts. The Behind the Tech podcast is hosted
by Kevin Scott."),
new UserChatMessage(
@"Create a short summary of this podcast episode that would be appropriate
to post on LinkedIn to promote the podcast episode. The post should be from
the first-person perspective of Kevin Scott, who hosts the podcast. \n" +
$"Here is the transcript of the podcast episode: {transcription} \n" +
$"Here is the bio of the guest: {bio}")
]);
return chatCompletion.ToString();
}
//Generate a Dall-E prompt
public static async Task<string> GetDallEPrompt(string socialBlurb)
{
ChatClient client = azureOpenAIClient.GetChatClient("gpt4");
ChatCompletion chatCompletion = await client.CompleteChatAsync(
[
new SystemChatMessage(
@"You are a helpful large language model that generates DALL-E prompts,
that when given to the DALL-E model can generate beautiful high-quality
images to use in social media posts about a podcast on technology. Good
DALL-E prompts will contain mention of related objects, and will not contain
people, faces, or words. Good DALL-E prompts should include a reference
to podcasting along with items from the domain of the podcast guest."),
new UserChatMessage(
@$"Create a DALL-E prompt to create an image to post along with this social
media text: {socialBlurb}")
]);
return chatCompletion.ToString();
}
//Create social media image with a Dall-E
public static async Task<string> GetImage(string prompt)
{
ImageClient client = azureOpenAIClient.GetImageClient("dalle3");
ImageGenerationOptions options = new()
{
Quality = GeneratedImageQuality.High,
Size = GeneratedImageSize.W1024xH1024,
Style = GeneratedImageStyle.Vivid,
ResponseFormat = GeneratedImageFormat.Uri,
};
GeneratedImage image =
await client.GenerateImageAsync(prompt + ", high-quality digital art", options);
return image.ImageUri.ToString();
}
public static async Task<SocialMediaPost> GenerateSocialMediaPost(string podcastUrl)
{
var transcription = await GetTranscription(podcastUrl);
var guestName = await GetGuestName(transcription);
var guestBio = await GetGuestBio(guestName);
var generatedBlurb = await GetSocialMediaBlurb(transcription, guestBio);
var dallePrompt = await GetDallEPrompt(generatedBlurb);
var generatedImage = await GetImage(dallePrompt);
var socialMediaPost = new SocialMediaPost()
{
ImageUrl = generatedImage,
Blurb = generatedBlurb
};
return socialMediaPost;
}
}
}