-
Notifications
You must be signed in to change notification settings - Fork 0
/
OpenAiChatBookService.cs
112 lines (93 loc) · 3.7 KB
/
OpenAiChatBookService.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
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;
public class OpenAiChatBookService
{
const string openAiUrl = "https://api.openai.com/v1/chat/completions";
const string model = "gpt-4";
readonly string apiKey;
readonly HttpClient client;
// You can define a summary language like "German", though it mostly
// also works without setting it, based on the original's language.
public string? summaryLanguage = null;
public string? translationLanguage = null;
// Optionally, e.g. "Write in the style of Douglas Adams."
public string? additionalSummaryInstructions = null;
public bool addSummaryHeadlines = false;
public bool addSummaryImages = false;
public OpenAiChatBookService(string keyPath)
{
apiKey = File.ReadAllText(keyPath).Trim();
client = new HttpClient();
client.Timeout = TimeSpan.FromMinutes(3);
client.DefaultRequestHeaders.Add("Authorization", $"Bearer {apiKey}");
}
public async Task<string> GetSummary(string bookChunk)
{
string role = "You are a helpful assistant.";
role += " Please shorten the provided book excerpt while keeping the narrative perspective and style. " +
"Include speech of characters, also shortened.";
if (addSummaryImages)
{
role += " Above every paragraph, add in square brackets a visual description of it for an image generator, using only commonly known words.";
}
if (addSummaryHeadlines)
{
role += " If there is a scene switch or similar, add an all-caps headline.";
}
if (!string.IsNullOrEmpty(summaryLanguage))
{
role += " Write in " + summaryLanguage + ".";
}
if (!string.IsNullOrEmpty(additionalSummaryInstructions))
{
role += " " + additionalSummaryInstructions;
}
return await PostAsync(role, bookChunk);
}
public async Task<string> GetTranslation(string bookChunk)
{
translationLanguage = translationLanguage ?? "German";
string role = "You are a helpful assistant. " +
"Please translate the provided book excerpt to " + translationLanguage + ".";
return await PostAsync(role, bookChunk);
}
public async Task<string> PostAsync(string role, string bookChunk)
{
var prompt = new
{
model,
messages = new object[]
{
new { role = "system", content = role },
new { role = "user", content = bookChunk },
},
max_tokens = 4096
};
var content = new StringContent(JsonConvert.SerializeObject(prompt), Encoding.UTF8, "application/json");
var response = await client.PostAsync(openAiUrl, content);
if (response.IsSuccessStatusCode)
{
var responseString = await response.Content.ReadAsStringAsync();
var responseObject = JsonConvert.DeserializeObject<dynamic>(responseString);
Console.WriteLine(responseString);
if (responseObject?["choices"]?[0]?["message"]?["content"] != null)
{
return responseObject["choices"][0]["message"]["content"].ToString();
}
else
{
throw new Exception("Unexpected response structure from OpenAI API");
}
}
else
{
var errorContent = await response.Content.ReadAsStringAsync();
throw new Exception($"Failed to communicate with OpenAI API. " +
"Status code: {response.StatusCode}. Response content: {errorContent}"
);
}
}
}