Compare commits

..

No commits in common. "nya" and "disgust" have entirely different histories.
nya ... disgust

16 changed files with 58 additions and 163 deletions

View file

@ -1,28 +0,0 @@
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
WORKDIR /src
COPY *.sln .
COPY src/Nyanlabs.Umogen.Core/*.csproj src/Nyanlabs.Umogen.Core/
COPY src/Nyanlabs.Umogen.Server/*.csproj src/Nyanlabs.Umogen.Server/
COPY test/Nyanlabs.Umogen.WebTests/*.csproj test/Nyanlabs.Umogen.WebTests/
COPY test/Nyanlabs.Umogen.CoreTests/*.csproj test/Nyanlabs.Umogen.CoreTests/
RUN dotnet restore
COPY . .
RUN dotnet publish -c Release -o /build
FROM mcr.microsoft.com/dotnet/aspnet:8.0
RUN apt update -y
RUN apt install -y libreoffice-writer-nogui
COPY --from=build /build /app
WORKDIR /app
EXPOSE 8080
ENTRYPOINT [ "dotnet", "Nyanlabs.Umogen.Server.dll" ]

BIN
out.pdf Normal file

Binary file not shown.

View file

@ -2,7 +2,7 @@ namespace Nyanlabs.Umogen.Core.Models;
public record ApiRequest public record ApiRequest
{ {
public string Model { get; set; } = "gpt-4"; public string Model { get; set; } = "gpt-3.5-turbo";
public float Temperature { get; set; } = 0.7f; public float Temperature { get; set; } = 0.7f;
public ICollection<GptMessage> Messages { get; set; } = new List<GptMessage>(); public ICollection<GptMessage> Messages { get; set; } = new List<GptMessage>();
public bool Stream { get; set; } public bool Stream { get; set; }

View file

@ -16,7 +16,7 @@ public record Person(string Name, string Surname, string IdC, string Pesel, Date
public DateTime? DoB { get; set; } = DoB; public DateTime? DoB { get; set; } = DoB;
[JsonIgnore] [JsonIgnore]
public virtual ICollection<LegalEntity> Companies { get; set; } = default!; public virtual ICollection<LegalEntity> Companies { get; set; }
public string GetName() public string GetName()
{ {

View file

@ -5,13 +5,13 @@ namespace Nyanlabs.Umogen.Core.Models;
public class UmoAnalModel public class UmoAnalModel
{ {
[JsonPropertyName("c_type")] [JsonPropertyName("c_type")]
public string ContractType { get; set; } = default!; public string ContractType { get; set; }
[JsonPropertyName("j_pos")] [JsonPropertyName("j_pos")]
public string JobPosition { get; set; } = default!; public string JobPosition { get; set; }
[JsonPropertyName("k_lit")] [JsonPropertyName("k_lit")]
public string ValueLiteral { get; set; } = default!; public string ValueLiteral { get; set; }
[JsonPropertyName("conds")] [JsonPropertyName("conds")]
public ICollection<string> Conditions { get; set; } = default!; public ICollection<string> Conditions { get; set; }
public UmoDoctype Doctype => UmoDoctypeBindings.GetFromName(ContractType)!.Value; public UmoDoctype Doctype => UmoDoctypeBindings.GetFromName(ContractType).Value;
} }

View file

@ -32,9 +32,9 @@ public class UmoDocumentResult(UmoDoctype? type, Person employee, IEntity employ
.Replace(ENACT_DATE, DateTime.Now.ToString("dd.MM.yyyy")) .Replace(ENACT_DATE, DateTime.Now.ToString("dd.MM.yyyy"))
.Replace(ISSUE_DATE, DateTime.Now.ToString("dd.MM.yyyy")) .Replace(ISSUE_DATE, DateTime.Now.ToString("dd.MM.yyyy"))
.Replace(PAYMENT_LIT, Anal.ValueLiteral) .Replace(PAYMENT_LIT, Anal.ValueLiteral)
.Replace(PAYMENT, Payment!.Value.ToString()) .Replace(PAYMENT, Payment.Value.ToString())
.Replace(WORK_TYPE, Anal.JobPosition) .Replace(WORK_TYPE, Anal.JobPosition)
.Replace(DYNAMIC_DATA, string.Join(", ", Anal.Conditions.Select(x => x.Trim('-').Trim(' ')))); .Replace(DYNAMIC_DATA, string.Join('\n', Anal.Conditions.Select(a => $"- {a}")));
string tmp = Path.GetTempFileName(); string tmp = Path.GetTempFileName();
await File.WriteAllTextAsync(tmp, xml); await File.WriteAllTextAsync(tmp, xml);

View file

@ -8,7 +8,7 @@ public class UmoEngine : IDisposable
{ {
if (isFilePath) if (isFilePath)
{ {
apiKey ??= Environment.GetEnvironmentVariable("UMO_KEY_FILE") ?? Umogen.DEFAULT_API_KEY_FILE; apiKey ??= Umogen.DEFAULT_API_KEY_FILE;
if (!File.Exists(apiKey)) if (!File.Exists(apiKey))
{ {
throw new ArgumentException($"No such file: {apiKey}"); throw new ArgumentException($"No such file: {apiKey}");

View file

@ -5,7 +5,7 @@ namespace Nyanlabs.Umogen.Core;
public class Umogen public class Umogen
{ {
public const string DEFAULT_API_KEY_FILE = "umogenkey.secret"; public const string DEFAULT_API_KEY_FILE = "umogenkey.secret";
public const string PROMPT = "You analyze employment prompt requests and return document type (one of these 'Umowa o Pracę', 'Umowa Zlecenie', 'Umowa o Dzieło') and elaborate description of job details as a list separated by hyphens and newlines. Also give a very generalized job position. You write them in format: '{ \"c_type\": \"<contract type>\", \"j_pos\": \"<rodzaj zawodu>\", \"k_lit\": \"<kwota słownie>\", \"conds\": [ <warunki zatrudnienia> ]'. Nie opisuj wynagrodzenia w '<warunki zatrudnienia>'. Add any clauses (anti-competitive, NDA, etc) to the bottom if requested."; public const string PROMPT = "You analyze employment prompt requests and return document type (one of these 'Umowa o Pracę', 'Umowa Zlecenie', 'Umowa o Dzieło') and elaborate description of job details as a list separated by hyphens and newlines. Also give a very generalized job position. You write them in format: '{ \"c_type\": \"<contract type>\", \"j_pos\": \"<rodzaj zawodu>\", \"k_lit\": \"<kwota słownie>\", \"conds\": [ <warunki zatrudnienia> ]'";
public static readonly JsonSerializerOptions JSON_OPTS = new(JsonSerializerDefaults.Web) public static readonly JsonSerializerOptions JSON_OPTS = new(JsonSerializerDefaults.Web)
{ {
PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseLower PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseLower

View file

@ -11,8 +11,7 @@ public class DataContext : DbContext
protected override void OnConfiguring(DbContextOptionsBuilder o) protected override void OnConfiguring(DbContextOptionsBuilder o)
{ {
o.UseSqlite("Data Source=data.db;");
o.UseSqlite($"Data Source={Environment.GetEnvironmentVariable("UMO_DATA") ?? "data.db"};");
} }
protected override void OnModelCreating(ModelBuilder m) protected override void OnModelCreating(ModelBuilder m)

View file

@ -14,12 +14,12 @@
<div class="row justify-content-center align-items-center g-2"> <div class="row justify-content-center align-items-center g-2">
<div class="col mb-3"> <div class="col mb-3">
<label for="employer" class="form-label">Pracodawca (PESEL lub NIP)</label> <label for="employer" class="form-label">Pracodawca (PESEL lub NIP)</label>
<Autocomplete Value="@_employerId" AcceptedValues="GetEmployers()" Change="ChgEmployer" /> <input type="text" class="form-control" id="employer" @onchange="ChgEmployer" value="@_employerId">
<span class="validation-message">@(employer == null ? "" : $"{employer.GetName()}")</span> <span class="validation-message">@(employer == null ? "" : $"{employer.GetName()}")</span>
</div> </div>
<div class="col mb-3"> <div class="col mb-3">
<label for="employee" class="form-label">Pracownik (PESEL)</label> <label for="employee" class="form-label">Pracownik (PESEL)</label>
<Autocomplete Value="@_employeeId" AcceptedValues="GetEmployees()" Change="ChgEmployee" /> <input type="text" class="form-control" id="employee" @onchange="ChgEmployee" value="@_employeeId">
<span class="validation-message">@(employee == null ? "" : $"{employee.Name} {employee.Surname}")</span> <span class="validation-message">@(employee == null ? "" : $"{employee.Name} {employee.Surname}")</span>
</div> </div>
</div> </div>
@ -59,8 +59,7 @@
{ {
_employerId = (string)e.Value!; _employerId = (string)e.Value!;
employer = await db.Persons.AsNoTracking().SingleOrDefaultAsync(s => s.Pesel == _employerId) as IEntity ?? await employer = await db.Persons.AsNoTracking().SingleOrDefaultAsync(s => s.Pesel == _employerId) as IEntity ?? await
db.Companies.AsNoTracking().Include(i => i.Representative).SingleOrDefaultAsync(s => s.Nip == _employerId); db.Companies.AsNoTracking().SingleOrDefaultAsync(s => s.Nip == _employerId);
StateHasChanged();
} }
private async Task ChgEmployee(ChangeEventArgs e) private async Task ChgEmployee(ChangeEventArgs e)
@ -71,7 +70,7 @@
private string _validityText = ""; private string _validityText = "";
private void ChgValidity(ChangeEventArgs e) private async Task ChgValidity(ChangeEventArgs e)
{ {
string val = (string)e.Value!; string val = (string)e.Value!;
_validityText = val; _validityText = val;
@ -97,19 +96,6 @@
_validity = new ValidTime(now, span); _validity = new ValidTime(now, span);
} }
private IEnumerable<(string, string)> GetEmployers()
{
var pers = db.Persons.AsNoTracking().AsEnumerable().Select(p => ($"{p.Name} {p.Surname}", p.Pesel));
var comp = db.Companies.AsNoTracking().AsEnumerable().Select(c => (c.Name, c.Nip!));
return pers.Union(comp);
}
private IEnumerable<(string, string)> GetEmployees()
{
return db.Persons.AsNoTracking().AsEnumerable().Select(p => ($"{p.Name} {p.Surname}", p.Pesel));
}
private async Task Process() private async Task Process()
{ {
disB = true; disB = true;
@ -117,7 +103,7 @@
await Task.Yield(); await Task.Yield();
output = string.Empty; output = string.Empty;
using UmoEngine eng = new(); using UmoEngine eng = new("/home/nya/Dev/csharp/umogen/umogenkey.secret");
UmoProcess proc = new(eng); UmoProcess proc = new(eng);
Thread.Yield(); Thread.Yield();
@ -129,11 +115,11 @@
} }
var anal = System.Text.Json.JsonSerializer.Deserialize<UmoAnalModel>(output, Umogen.JSON_OPTS); var anal = System.Text.Json.JsonSerializer.Deserialize<UmoAnalModel>(output, Umogen.JSON_OPTS);
UmoDocumentResult res = new(null, employee!, employer!, _validity, _payment, UmoDocumentResult res = new(null, employee, employer, _validity, _payment,
anal!); anal);
var bytes = await res.ProcessPdf(Path.Combine(Environment.GetEnvironmentVariable("UMO_TEMPLATES")!, var bytes = await res.ProcessPdf(Path.Combine("/home/nya/Dev/csharp/umogen/",
anal!.Doctype.TemplateDoc())); $"templates/{anal.Doctype.TemplateDoc()}"));
await js.InvokeVoidAsync("blobby", bytes); await js.InvokeVoidAsync("blobby", bytes);
disB = false; disB = false;

View file

@ -16,13 +16,22 @@
"environmentVariables": { "environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development" "ASPNETCORE_ENVIRONMENT": "Development"
} }
} },
}, "https": {
"IIS Express": { "commandName": "Project",
"commandName": "IISExpress", "dotnetRunMessages": true,
"launchBrowser": true, "launchBrowser": true,
"environmentVariables": { "applicationUrl": "https://localhost:7029;http://localhost:5214",
"ASPNETCORE_ENVIRONMENT": "Development" "environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
} }
} }
} }

View file

@ -1,51 +0,0 @@
<div class="relat" @onfocusin="(() => focus = true)">
<input type="text" class="form-control" @oninput="Prechange" value="@Value">
@if (focus)
{
<div class="autocomplete-items">
@foreach (var tup in Filter())
{
<div @onclick="async (e) => await Select(tup.Item2)">
@tup.Item1 (@tup.Item2)
</div>
}
</div>
}
</div>
@code {
private bool focus = false;
[Parameter]
public IEnumerable<(string, string)> AcceptedValues { get; set; } = [];
[Parameter]
public string Value { get; set; } = "";
private async Task Prechange(ChangeEventArgs e)
{
Value = (string)e.Value!;
StateHasChanged();
await Change.InvokeAsync(e);
}
[Parameter]
public EventCallback<ChangeEventArgs> Change { get; set; }
private async Task Select(string s)
{
focus = false;
Value = s;
await Prechange(new()
{
Value = s
});
StateHasChanged();
}
private IEnumerable<(string, string)> Filter()
{
return AcceptedValues.Where(v => v.Item1.StartsWith(Value, StringComparison.OrdinalIgnoreCase) ||
v.Item2.StartsWith(Value, StringComparison.OrdinalIgnoreCase));
}
}

View file

@ -1,32 +0,0 @@
.relat {
position: relative;
}
.autocomplete {
position: relative;
display: inline-block;
}
.autocomplete-items {
position: absolute;
border: 1px solid #d4d4d4;
border-bottom: none;
border-top: none;
z-index: 99;
/*position the autocomplete items to be the same width as the container:*/
top: 3rem;
left: 0;
right: 0;
width: fit-content;
}
.autocomplete-items div {
padding: 10px;
cursor: pointer;
background-color: #fff;
border-bottom: 1px solid #d4d4d4;
}
.autocomplete-items div:hover {
background-color: rgb(156, 237, 248);
}

View file

@ -5,13 +5,5 @@
"Microsoft.AspNetCore": "Warning" "Microsoft.AspNetCore": "Warning"
} }
}, },
"Kestrel": {
"Endpoints": {
"Http": {
"Url": "http://+:8080"
}
}
},
"AllowedHosts": "*" "AllowedHosts": "*"
} }

View file

@ -8,4 +8,24 @@ public class GenerationTests
private Person ModelEmployer => new("Kotek", "Miauczyński", "CBS4327563", "04281308999", new DateTime(2004, 08, 13)); 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)); 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("I would like to employ Jan Kowalski ID NO CBS3727348 for part time job as a shopkeeper and pay 1400zł.");
// await foreach (var str in enu)
// {
// Console.Write(str);
// }
}
} }

View file

@ -31,7 +31,7 @@ public class PdfTest
} }
var anal = JsonSerializer.Deserialize<UmoAnalModel>(sb.ToString(), Core.Umogen.JSON_OPTS); var anal = JsonSerializer.Deserialize<UmoAnalModel>(sb.ToString(), Core.Umogen.JSON_OPTS);
UmoDocumentResult r = new(null, ModelEmployer, ModelEmployee, ValidTime.Invalid, 2137, anal!); UmoDocumentResult r = new(null, ModelEmployer, ModelEmployee, ValidTime.Invalid, 2137, anal);
// When // When
byte[] b = await r.ProcessPdf(Path.Combine(root, $"templates/{r.DocType.TemplateDoc()}")); byte[] b = await r.ProcessPdf(Path.Combine(root, $"templates/{r.DocType.TemplateDoc()}"));