the absolute state of S T U F F

This commit is contained in:
femsci 2023-11-18 11:01:11 +01:00
parent 17ed4cdb6f
commit c22d5c6d82
Signed by: femsci
GPG key ID: 08F7911F0E650C67
28 changed files with 12110 additions and 95 deletions

2
.gitignore vendored
View file

@ -3,3 +3,5 @@
**/target/ **/target/
/build /build
/umogenkey.secret /umogenkey.secret
**.db
**.db-*

BIN
out.pdf Normal file

Binary file not shown.

View file

@ -1,11 +1,18 @@
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace Nyanlabs.Umogen.Core.Models; namespace Nyanlabs.Umogen.Core.Models;
public class LegalEntity(string Name, string? Nip = null, string? Headquarters = null, Person? Representative = null) : IEntity, INLSerializable public class LegalEntity : IEntity, INLSerializable
{ {
public string Name { get; set; } = Name; [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public string? Nip { get; set; } = Nip; [Key]
public string? Headquarters { get; set; } = Headquarters; public long Id { get; set; }
public Person? Representative { get; set; } = Representative; public string Name { get; set; } = default!;
public string? Nip { get; set; } = default!;
public string? Headquarters { get; set; }
public Person? Representative { get; set; }
public long? PersonId { get; set; }
public string GetName() public string GetName()
{ {
@ -24,6 +31,6 @@ public class LegalEntity(string Name, string? Nip = null, string? Headquarters =
public string SerializeToDocument() public string SerializeToDocument()
{ {
return $"{Name}, reprezentowaną przez {Representative.GetName()}"; return $"{Name}{(Representative != null ? $", reprezentowaną przez {Representative.GetName()}" : "")}";
} }
} }

View file

@ -1,13 +1,23 @@
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Text.Json.Serialization;
namespace Nyanlabs.Umogen.Core.Models; namespace Nyanlabs.Umogen.Core.Models;
public record Person(string Name, string Surname, string? Id = null, string? Pesel = null, DateTime? DoB = null) : IEntity, INLSerializable public record Person(string Name, string Surname, string IdC, string Pesel, DateTime? DoB = null) : IEntity, INLSerializable
{ {
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
[Key]
public long Id { get; set; }
public string Name { get; set; } = Name; public string Name { get; set; } = Name;
public string Surname { get; set; } = Surname; public string Surname { get; set; } = Surname;
public string? IDCode { get; set; } = Id; public string IDCode { get; set; } = IdC;
public string? Pesel { get; set; } = Pesel; public string Pesel { get; set; } = Pesel;
public DateTime? DoB { get; set; } = DoB; public DateTime? DoB { get; set; } = DoB;
[JsonIgnore]
public virtual ICollection<LegalEntity> Companies { get; set; }
public string GetName() public string GetName()
{ {
return $"{Name} {Surname}"; return $"{Name} {Surname}";

View file

@ -1,8 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
using System.Threading.Tasks;
namespace Nyanlabs.Umogen.Core.Models; namespace Nyanlabs.Umogen.Core.Models;

View file

@ -27,6 +27,6 @@ public readonly struct ValidTime : INLSerializable, IDocSerializable
public string SerializeToDocument() public string SerializeToDocument()
{ {
return this.Start != DateTime.MaxValue ? $"na czas od {Start:dd MMM yyyy} do {End:dd MMM yyyy}" : "na czas nieokreślony"; return this.Start != DateTime.MaxValue ? $"na czas od {Start:dd.MM.yyyy} do {End:dd.MM.yyyy}" : "na czas nieokreślony";
} }
} }

View file

@ -27,6 +27,7 @@ public class SseConsumer<TEvent> : IDisposable, IAsyncDisposable
yield return JsonSerializer.Deserialize<TEvent>(line, Umogen.JSON_OPTS) ?? throw new DataException("Invalid data..."); yield return JsonSerializer.Deserialize<TEvent>(line, Umogen.JSON_OPTS) ?? throw new DataException("Invalid data...");
} }
reader.Close();
} }
public void Dispose() public void Dispose()

View file

@ -0,0 +1,21 @@
using Microsoft.EntityFrameworkCore;
using Nyanlabs.Umogen.Core.Models;
namespace Nyanlabs.Umogen.Server;
public class DataContext : DbContext
{
public DbSet<Person> Persons => Set<Person>();
public DbSet<LegalEntity> Companies => Set<LegalEntity>();
protected override void OnConfiguring(DbContextOptionsBuilder o)
{
o.UseSqlite("Data Source=data.db;");
}
protected override void OnModelCreating(ModelBuilder m)
{
m.Entity<LegalEntity>().HasOne(e => e.Representative).WithMany(e => e.Companies);
}
}

View file

@ -6,6 +6,8 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="Femsci.AspapajNet" Version="1.0.2" /> <PackageReference Include="Femsci.AspapajNet" Version="1.0.2" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="8.0.0" />
</ItemGroup> </ItemGroup>
<PropertyGroup> <PropertyGroup>

View file

@ -2,19 +2,43 @@
@using Umogen.Core; @using Umogen.Core;
@using Umogen.Core.Models; @using Umogen.Core.Models;
@inject IJSRuntime js @inject IJSRuntime js
@inject DataContext db
@using Microsoft.EntityFrameworkCore;
<PageTitle>Umowy</PageTitle> <PageTitle>Umowy</PageTitle>
<h2 class="text-center">Umowy</h2> <h2 class="text-center">Umowy</h2>
<div class="form-control"> <div class="container">
<input type="text" placeholder="Osoba" @bind-value="_person" /> <form>
</div> <div class="row justify-content-center align-items-center g-2">
<div class="form-control"> <div class="col mb-3">
<input type="text" placeholder="Wynagrodzenie" @bind-value="_value" /> <label for="employer" class="form-label">Pracodawca (PESEL lub NIP)</label>
</div> <input type="text" class="form-control" id="employer" @onchange="ChgEmployer" value="@_employerId">
<div class="form-control"> <span class="validation-message">@(employer == null ? "" : $"{employer.GetName()}")</span>
<input type="text" placeholder="Wpisz dane" @bind-value="_prompt" /> </div>
<div class="col mb-3">
<label for="employee" class="form-label">Pracownik (PESEL)</label>
<input type="text" class="form-control" id="employee" @onchange="ChgEmployee" value="@_employeeId">
<span class="validation-message">@(employee == null ? "" : $"{employee.Name} {employee.Surname}")</span>
</div>
</div>
<div class="row justify-content-center align-items-center g-2">
<div class="col mb-3">
<label for="validity" class="form-label">Okres trwania [dni]</label>
<input type="text" class="form-control" id="validity" @onchange="ChgValidity" value="@_validityText">
</div>
<div class="col mb-3">
<label for="value" class="form-label">Wynagrodzenie [PLN]</label>
<input type="number" class="form-control" id="value" @bind-value="_payment">
</div>
</div>
<div class="col mb-3">
<label for="query" class="form-label">Dane (NLP)</label>
<input type="text" class="form-control" id="query" @bind-value="_query">
</div>
<button disabled="@disB" type="button" @onclick="Process" class="btn btn-primary">Generuj</button>
</form>
</div> </div>
@ -22,19 +46,69 @@
<div class="text-center"><b>OUT:</b> @output</div> <div class="text-center"><b>OUT:</b> @output</div>
</div> </div>
<button class="btn btn-primary" @onclick="Process">Wyszukaj</button>
@code { @code {
private string _prompt, _person, _value; private string _employerId = "", _employeeId = "";
private Person? employee;
private IEntity? employer;
private string _query = "";
private ValidTime _validity;
private decimal _payment;
private string output = ""; private string output = "";
private bool disB = false;
private async Task ChgEmployer(ChangeEventArgs e)
{
_employerId = (string)e.Value!;
employer = await db.Persons.AsNoTracking().SingleOrDefaultAsync(s => s.Pesel == _employerId) as IEntity ?? await
db.Companies.AsNoTracking().SingleOrDefaultAsync(s => s.Nip == _employerId);
}
private async Task ChgEmployee(ChangeEventArgs e)
{
_employeeId = (string)e.Value!;
employee = await db.Persons.AsNoTracking().SingleOrDefaultAsync(s => s.Pesel == _employeeId);
}
private string _validityText = "";
private async Task ChgValidity(ChangeEventArgs e)
{
string val = (string)e.Value!;
_validityText = val;
StateHasChanged();
var now = DateTime.Now;
if (!TimeSpan.TryParse(val, out TimeSpan span))
{
_validityText = "nieokreślony";
_validity = ValidTime.Invalid;
}
if (span.TotalDays < 1)
{
_validityText = "nieokreślony";
_validity = ValidTime.Invalid;
StateHasChanged();
return;
}
_validityText = $"{span.TotalDays} d";
_validity = new ValidTime(now, span);
}
private async Task Process() private async Task Process()
{ {
disB = true;
this.StateHasChanged();
await Task.Yield();
output = string.Empty; output = string.Empty;
using UmoEngine eng = new("/home/nya/Dev/csharp/umogen/umogenkey.secret"); using UmoEngine eng = new("/home/nya/Dev/csharp/umogen/umogenkey.secret");
UmoProcess proc = new(eng); UmoProcess proc = new(eng);
Thread.Yield(); Thread.Yield();
await foreach (var str in proc.Ask(_prompt))
await foreach (var str in proc.Ask(_query + $" wynagrodzenie {_payment} zł"))
{ {
output += str; output += str;
Console.Write(str); Console.Write(str);
@ -42,13 +116,14 @@
} }
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, new Person("Kotek", "Miauczyński", "CBS4327563", "04281308999", new DateTime(2004, 08, UmoDocumentResult res = new(null, employee, employer, _validity, _payment,
13)),
new Person("Kotek", "Miauczyński", "CBS4327563", "04281308999", new DateTime(2004, 08, 13)), ValidTime.Invalid, 2137,
anal); anal);
var bytes = await res.ProcessPdf(Path.Combine("/home/nya/Dev/csharp/umogen/", var bytes = await res.ProcessPdf(Path.Combine("/home/nya/Dev/csharp/umogen/",
$"templates/{anal.Doctype.TemplateDoc()}")); $"templates/{anal.Doctype.TemplateDoc()}"));
await js.InvokeVoidAsync("blobby", bytes); await js.InvokeVoidAsync("blobby", bytes);
disB = false;
this.StateHasChanged();
} }
} }

View file

@ -0,0 +1,97 @@
@page "/entities"
@inject DataContext db
@using Microsoft.EntityFrameworkCore
<PageTitle>Podmioty</PageTitle>
<h2 class="text-center">Podmioty</h2>
<div class="col-md-4">
<a href="/entities#" @onclick="ShowPersonDialog">Dodaj nową osobę</a>
</div>
@if (_mode == 1)
{
<div class="mt-4 mb-4">
<PersonAddForm OnSubmit="HideAll" />
</div>
}
<div class="table-responsive-xl">
<table class="table table-primary">
<thead>
<tr>
<th scope="col">Id</th>
<th scope="col">Imię</th>
<th scope="col">PESEL</th>
<th scope="col">Seria dowodu</th>
</tr>
</thead>
<tbody>
@foreach (var person in db.Persons.AsNoTracking().ToList())
{
<tr class="">
<td scope="row">@person.Id</td>
<td>@person.Name @person.Surname</td>
<td>@person.Pesel</td>
<td>@person.IdC</td>
</tr>
}
</tbody>
</table>
</div>
<div class="col-md-4">
<a href="/entities#" @onclick="ShowCompanyDialog">Dodaj nową firmę</a>
</div>
@if (_mode == 2)
{
<div class="mt-4 mb-4">
<CompanyAddForm OnSubmit="HideAll" />
</div>
}
<div class="table-responsive-xl">
<table class="table table-primary">
<thead>
<tr>
<th scope="col">Id</th>
<th scope="col">Nazwa</th>
<th scope="col">NIP</th>
<th scope="col">Siedziba</th>
<th scope="col">Reprezentant</th>
</tr>
</thead>
<tbody>
@foreach (var company in db.Companies.AsNoTracking().Include(c => c.Representative).ToList())
{
<tr class="">
<td scope="row">@company.Id</td>
<td>@company.Name</td>
<td>@company.Nip</td>
<td>@company.Headquarters</td>
<td>@(company.Representative!.Name) @(company.Representative.Surname) [ID @company.Representative.Id]
</td>
</tr>
}
</tbody>
</table>
</div>
@code {
int _mode = 0;
private void HideAll()
{
_mode = 0;
}
private void ShowCompanyDialog()
{
_mode = (_mode != 2 ? 2 : 0);
}
private void ShowPersonDialog()
{
_mode = (_mode != 1 ? 1 : 0);
}
}

View file

@ -2,4 +2,14 @@
<PageTitle>Index</PageTitle> <PageTitle>Index</PageTitle>
<h1>Hello, meowmeow~</h1> <div class="container text-center">
<h1>umogen</h1>
<h3 class="mb-5">Silly Integrated Unified System for Accounting and Contract Handling</h3>
<p>umogen is an experiment that aims to leverage large language models in order to decrease the effort of
handwriting various Polish legal contracts. This iteration will focus on employment and service contracts,
namely: contract of employment
and civic-law contracts which are the primary contracts used to employ workers. Moreover, civic-law contracts
can be utilized to exchange services.</p>
<p>Check <a href="/entities">podmioty</a> for entity data manipulation and <a href="/contracts">umowy</a> to get
started with contract generation.</p>
</div>

View file

@ -1,20 +0,0 @@
@page "/people"
<PageTitle>Osoby</PageTitle>
<h2 class="text-center">Osoby</h2>
<button @onclick="Toggle">Dodaj nowe osoby</button>
@if (addVis)
{
<PersonAddForm OnSubmit="Toggle" />
}
@code {
private bool addVis = false;
private void Toggle()
{
addVis = !addVis;
}
}

View file

@ -10,8 +10,7 @@
<meta charset="utf-8" /> <meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<base href="~/" /> <base href="~/" />
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet" <link href="css/bs.css" rel="stylesheet">
integrity="sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN" crossorigin="anonymous">
<link href="css/site.css" rel="stylesheet" /> <link href="css/site.css" rel="stylesheet" />
<link href="Nyanlabs.Umogen.Server.styles.css" rel="stylesheet" /> <link href="Nyanlabs.Umogen.Server.styles.css" rel="stylesheet" />
<link rel="icon" href="favicon.ico" /> <link rel="icon" href="favicon.ico" />

View file

@ -1,14 +1,24 @@
using Femsci.AspapajNet; using Femsci.AspapajNet;
using Nyanlabs.Umogen.Server;
var builder = WebApplication.CreateBuilder(args); var builder = WebApplication.CreateBuilder(args);
// Add services to the container. // Add services to the container.
builder.Services.AddRazorPages(); builder.Services.AddRazorPages();
builder.Services.AddServerSideBlazor(); builder.Services.AddServerSideBlazor();
builder.Services.AddPapiez(); builder.Services.AddPapiez();
builder.Services.AddDbContextFactory<DataContext>();
var app = builder.Build(); var app = builder.Build();
using (var db = new DataContext())
{
await db.Database.EnsureCreatedAsync();
}
if (!app.Environment.IsDevelopment()) if (!app.Environment.IsDevelopment())
{ {
app.UseExceptionHandler("/Error"); app.UseExceptionHandler("/Error");

View file

@ -0,0 +1,56 @@
@inject DataContext db
<h2 class="text-center">Dodaj firmę</h2>
<div class="container">
<form>
<div class="mb-3">
<label for="repr" class="form-label">Id reprezentanta</label>
<input type="text" class="form-control" id="repr" @bind-value="_reprId">
</div>
<div class="row justify-content-center align-items-center g-2">
<div class="col mb-3">
<label for="name" class="form-label">Nazwa firmy</label>
<input type="text" class="form-control" id="name" @bind-value="_name">
</div>
<div class="col mb-3">
<label for="nip" class="form-label">NIP</label>
<input type="text" class="form-control" id="nip" @bind-value="_nip">
</div>
</div>
<div class="mb-3">
<label for="loc" class="form-label">Siedziba</label>
<input type="text" class="form-control" id="loc" @bind-value="_loc">
</div>
<button @onclick="Submit" class="btn btn-primary">Dodaj</button>
</form>
</div>
@code {
[Parameter]
public required Action OnSubmit { get; set; }
private long _reprId;
private string _name = string.Empty,
_loc = string.Empty,
_nip = string.Empty;
private async Task Submit()
{
Core.Models.LegalEntity p = new()
{
Name = _name,
Nip = _nip,
Headquarters = _loc,
PersonId = _reprId,
};
await db.AddAsync(p);
await db.SaveChangesAsync();
_name = string.Empty;
_loc = string.Empty;
_nip = string.Empty;
_reprId = 0;
OnSubmit.Invoke();
}
}

View file

@ -11,7 +11,7 @@
<a class="nav-link active" aria-current="page" href="/">Home</a> <a class="nav-link active" aria-current="page" href="/">Home</a>
</li> </li>
<li class="nav-item"> <li class="nav-item">
<a class="nav-link" href="/people">Osoby</a> <a class="nav-link" href="/entities">Osoby</a>
</li> </li>
<li class="nav-item"> <li class="nav-item">
<a class="nav-link" href="/contracts">Umowy</a> <a class="nav-link" href="/contracts">Umowy</a>

View file

@ -1,22 +1,28 @@
@inject DataContext db
<h2 class="text-center">Dodaj osobę</h2> <h2 class="text-center">Dodaj osobę</h2>
<div class="container"> <div class="container align-items-center">
<form> <form>
<div class="mb-3"> <div class="row justify-content-center align-items-center g-2">
<div class="col mb-3">
<label for="name" class="form-label">Imię</label> <label for="name" class="form-label">Imię</label>
<input type="text" class="form-control" id="name" @bind-value="_name"> <input type="text" class="form-control" id="name" @bind-value="_name">
</div> </div>
<div class="mb-3"> <div class="col mb-3">
<label for="surname" class="form-label">Nazwisko</label> <label for="surname" class="form-label">Nazwisko</label>
<input type="text" class="form-control" id="surname" @bind-value="_surname"> <input type="text" class="form-control" id="surname" @bind-value="_surname">
</div> </div>
<div class="mb-3"> </div>
<div class="row justify-content-center align-items-center g-2">
<div class="col mb-3">
<label for="pesel" class="form-label">PESEL</label> <label for="pesel" class="form-label">PESEL</label>
<input type="text" class="form-control" id="pesel" @bind-value="_pesel"> <input type="text" class="form-control" id="pesel" @bind-value="_pesel">
</div> </div>
<div class="mb-3"> <div class="col mb-3">
<label for="cbs" class="form-label">Seria dowodu</label> <label for="cbs" class="form-label">Seria dowodu</label>
<input type="text" class="form-control" id="cbs" @bind-value="_id"> <input type="text" class="form-control" id="cbs" @bind-value="_id">
</div> </div>
</div>
<button @onclick="Submit" class="btn btn-primary">Dodaj</button> <button @onclick="Submit" class="btn btn-primary">Dodaj</button>
</form> </form>
</div> </div>
@ -30,9 +36,17 @@
_pesel = string.Empty, _pesel = string.Empty,
_id = string.Empty; _id = string.Empty;
private void Submit() private async Task Submit()
{ {
Core.Models.Person p = new(_name, _surname, _id, _pesel); Core.Models.Person p = new(_name, _surname, _id, _pesel);
await db.AddAsync(p);
await db.SaveChangesAsync();
_name = string.Empty;
_surname = string.Empty;
_pesel = string.Empty;
_id = string.Empty;
OnSubmit.Invoke(); OnSubmit.Invoke();
} }
} }

File diff suppressed because it is too large Load diff

View file

@ -53,6 +53,10 @@ a,
outline: 1px solid #26b050; outline: 1px solid #26b050;
} }
.validation-message {
display: inline-flex;
}
.invalid { .invalid {
outline: 1px solid red; outline: 1px solid red;
} }

View file

@ -8,13 +8,9 @@ function blobby(arr) {
var downloadLink = document.createElement("a"); var downloadLink = document.createElement("a");
downloadLink.target = "_blank"; downloadLink.target = "_blank";
downloadLink.download = "umo.pdf"; downloadLink.download = "umo.pdf";
// set object URL as the anchor's href
downloadLink.href = url; downloadLink.href = url;
// append the anchor to document body
document.body.append(downloadLink); document.body.append(downloadLink);
// fire a click event on the anchor
downloadLink.click(); downloadLink.click();
} }

View file

@ -47,26 +47,14 @@ public class NLSerializationTests
Assert.Equal("Kotek Miauczyński; PESEL 04281308999; ID series CBS4327563; born 13 Aug 2004", query); Assert.Equal("Kotek Miauczyński; PESEL 04281308999; ID series CBS4327563; born 13 Aug 2004", query);
} }
[Fact] private LegalEntity ModelCompany => new()
public void PersonNLTestNoData()
{ {
// Given Name = "Nyanbyte P.S.A.",
Person p = ModelEmployer with Nip = "1313131313",
{ Headquarters = "Miaumiaśna 13, Miauczki",
IDCode = null, Representative = ModelEmployer
Pesel = null,
DoB = null,
}; };
// When
var query = p.NLQuerySerialize();
// Then
Assert.Equal("Kotek Miauczyński; unknown PESEL; unknown ID series; unknown date of birth", query);
}
private LegalEntity ModelCompany => new("Nyanbyte P.S.A.", "1313131313", "Miaumiaśna 13, Miauczki", ModelEmployer);
[Fact] [Fact]
public void CompanySerializationTest() public void CompanySerializationTest()
{ {

View file

@ -1,9 +1,5 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text; using System.Text;
using System.Text.Json; using System.Text.Json;
using System.Threading.Tasks;
using Nyanlabs.Umogen.Core; using Nyanlabs.Umogen.Core;
using Nyanlabs.Umogen.Core.Models; using Nyanlabs.Umogen.Core.Models;