absolute utter filth yet it's working
This commit is contained in:
parent
c3f3cc6acb
commit
7b322ef7fb
11 changed files with 169 additions and 4 deletions
15
src/Nyanlabs.Umogen.Core/Models/ApiChoice.cs
Normal file
15
src/Nyanlabs.Umogen.Core/Models/ApiChoice.cs
Normal file
|
@ -0,0 +1,15 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Nyanlabs.Umogen.Core.Models;
|
||||
|
||||
public class ApiChoice
|
||||
{
|
||||
public string FinishReason { get; set; } = default!;
|
||||
public int Index { get; set; }
|
||||
public GptMessage? Message { get; set; }
|
||||
public GptMessage? Delta { get; set; }
|
||||
|
||||
}
|
|
@ -4,4 +4,7 @@ public record ApiRequest
|
|||
{
|
||||
public string Model { get; set; } = "gpt-3.5-turbo";
|
||||
public float Temperature { get; set; } = 0.7f;
|
||||
public ICollection<GptMessage> Messages { get; set; } = new List<GptMessage>();
|
||||
public bool Stream { get; set; }
|
||||
//public ApiResponseFormat ResponseFormat { get; set; } = new();
|
||||
}
|
||||
|
|
16
src/Nyanlabs.Umogen.Core/Models/ApiResponse.cs
Normal file
16
src/Nyanlabs.Umogen.Core/Models/ApiResponse.cs
Normal file
|
@ -0,0 +1,16 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Nyanlabs.Umogen.Core.Models;
|
||||
|
||||
public class ApiResponse
|
||||
{
|
||||
public string Id { get; set; } = default!;
|
||||
public string Model { get; set; } = default!;
|
||||
public string Object { get; set; } = default!;
|
||||
public UsageStats Usage { get; set; } = default!;
|
||||
public ICollection<ApiChoice> Choices { get; set; } = new List<ApiChoice>();
|
||||
public long Created { get; set; }
|
||||
}
|
6
src/Nyanlabs.Umogen.Core/Models/ApiResponseFormat.cs
Normal file
6
src/Nyanlabs.Umogen.Core/Models/ApiResponseFormat.cs
Normal file
|
@ -0,0 +1,6 @@
|
|||
namespace Nyanlabs.Umogen.Core.Models;
|
||||
|
||||
public class ApiResponseFormat
|
||||
{
|
||||
public string Type { get; set; } = "json_object";
|
||||
}
|
7
src/Nyanlabs.Umogen.Core/Models/GptMessage.cs
Normal file
7
src/Nyanlabs.Umogen.Core/Models/GptMessage.cs
Normal file
|
@ -0,0 +1,7 @@
|
|||
namespace Nyanlabs.Umogen.Core.Models;
|
||||
|
||||
public record GptMessage(string Role, string Content)
|
||||
{
|
||||
public string Role { get; } = Role;
|
||||
public string Content { get; } = Content;
|
||||
}
|
|
@ -45,6 +45,6 @@ public class UmoDocument : INLSerializable
|
|||
public ValidTime? ValidTime { get; set; }
|
||||
public string NLSerialize()
|
||||
{
|
||||
return $"{Doctype.Name().Item1} for {Employee.NLSerialize()} working for {Employer.NLSerialize()}; valid {ValidTime?.NLSerialize() ?? "for unspecified time"}.";
|
||||
return $"{Doctype.Name().Item2} for {Employee.NLSerialize()} working for {Employer.NLSerialize()}; valid {ValidTime?.NLSerialize() ?? "for unspecified time"}.";
|
||||
}
|
||||
}
|
||||
|
|
17
src/Nyanlabs.Umogen.Core/Models/UsageStats.cs
Normal file
17
src/Nyanlabs.Umogen.Core/Models/UsageStats.cs
Normal file
|
@ -0,0 +1,17 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text.Json.Serialization;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Nyanlabs.Umogen.Core.Models;
|
||||
|
||||
public class UsageStats
|
||||
{
|
||||
[JsonPropertyName("completion_tokens")]
|
||||
public int CompletionTokens { get; set; }
|
||||
[JsonPropertyName("prompt_tokens")]
|
||||
public int PromptTokens { get; set; }
|
||||
[JsonPropertyName("total_tokens")]
|
||||
public int TotalTokens { get; set; }
|
||||
}
|
|
@ -38,7 +38,7 @@ public class UmoEngine : IDisposable
|
|||
_http.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", apiKey);
|
||||
}
|
||||
|
||||
private readonly HttpClient _http;
|
||||
internal readonly HttpClient _http;
|
||||
|
||||
public async Task<bool> ValidateKey()
|
||||
{
|
||||
|
|
|
@ -1,3 +1,10 @@
|
|||
using System.Data;
|
||||
using System.Net.Http.Json;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
|
||||
using Nyanlabs.Umogen.Core.Models;
|
||||
|
||||
namespace Nyanlabs.Umogen.Core;
|
||||
|
||||
public class UmoProcess
|
||||
|
@ -9,8 +16,56 @@ public class UmoProcess
|
|||
|
||||
private readonly UmoEngine _eng;
|
||||
|
||||
public async Task Ask()
|
||||
public async IAsyncEnumerable<string> Ask(string content)
|
||||
{
|
||||
ApiRequest req = new()
|
||||
{
|
||||
Messages = new List<GptMessage>()
|
||||
{
|
||||
new("system", Umogen.PROMPT),
|
||||
new("user", content)
|
||||
},
|
||||
Stream = true
|
||||
};
|
||||
|
||||
HttpRequestMessage msg = new(HttpMethod.Post, "chat/completions");
|
||||
msg.Content = new StringContent(JsonSerializer.Serialize(req, options: Umogen.JSON_OPTS), Encoding.UTF8, "application/json");
|
||||
var resp = await _eng._http.SendAsync(msg, HttpCompletionOption.ResponseHeadersRead);
|
||||
|
||||
if (!resp.IsSuccessStatusCode)
|
||||
{
|
||||
Console.WriteLine(await resp.Content.ReadAsStringAsync());
|
||||
throw new DataException($"Cannot process request: {resp.StatusCode}.");
|
||||
}
|
||||
|
||||
var apiResp = await resp.Content.ReadAsStreamAsync();
|
||||
|
||||
var reader = new StreamReader(apiResp);
|
||||
|
||||
string? line;
|
||||
while ((line = await reader.ReadLineAsync()) != null)
|
||||
{
|
||||
if (line.StartsWith("data:"))
|
||||
{
|
||||
line = line[5..].Trim();
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(line))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
File.AppendAllText("/tmp/raw.md", line + "\n");
|
||||
|
||||
ApiResponse respChunk = JsonSerializer.Deserialize<ApiResponse>(line, options: Umogen.JSON_OPTS)!;
|
||||
ApiChoice choice = respChunk.Choices.First();
|
||||
|
||||
if (choice.FinishReason == "stop")
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
yield return choice.Delta?.Content ?? ":<";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,13 @@
|
|||
using System.Text.Json;
|
||||
|
||||
namespace Nyanlabs.Umogen.Core;
|
||||
|
||||
public class Umogen
|
||||
{
|
||||
public const string DEFAULT_API_KEY_FILE = "umogenkey.secret";
|
||||
public const string PROMPT = "You write Polish legal document in markdown format.";
|
||||
public const string PROMPT = "You write Polish legal contracts in Polish language in markdown format.";
|
||||
public static readonly JsonSerializerOptions JSON_OPTS = new(JsonSerializerDefaults.Web)
|
||||
{
|
||||
PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseLower
|
||||
};
|
||||
}
|
||||
|
|
40
test/Nyanlabs.Umogen.WebTests/GenerationTests.cs
Normal file
40
test/Nyanlabs.Umogen.WebTests/GenerationTests.cs
Normal file
|
@ -0,0 +1,40 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Nyanlabs.Umogen.Core;
|
||||
using Nyanlabs.Umogen.Core.Models;
|
||||
|
||||
namespace Nyanlabs.Umogen.WebTests;
|
||||
|
||||
public class GenerationTests
|
||||
{
|
||||
private Person ModelEmployer => new("Kotek", "Miauczyński", "CBS4327563", "04281308999", new DateTime(2004, 08, 13));
|
||||
|
||||
private Person ModelEmployee => new("Miau", "Kotczyński", "CBS69696969", "76011694336", new DateTime(1976, 1, 16));
|
||||
|
||||
[Fact]
|
||||
public async Task Meow4Me()
|
||||
{
|
||||
// Given
|
||||
var rootDir = Environment.CurrentDirectory.Replace("test/Nyanlabs.Umogen.WebTests/bin/Debug/net8.0", "");
|
||||
|
||||
UmoEngine eng = new(Path.Combine(rootDir, Core.Umogen.DEFAULT_API_KEY_FILE));
|
||||
|
||||
// When
|
||||
UmoDocument doc = new(UmoDoctype.CONTR_EMPLOYMENT, ModelEmployer, ModelEmployee);
|
||||
|
||||
UmoProcess proc = new(eng);
|
||||
var enu = proc.Ask(doc.NLSerialize());
|
||||
|
||||
await foreach (var str in enu)
|
||||
{
|
||||
Console.Write(str);
|
||||
File.AppendAllText("/tmp/doc.md", str);
|
||||
}
|
||||
|
||||
Console.WriteLine("~");
|
||||
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue