fixes
This commit is contained in:
@@ -107,7 +107,7 @@ services:
|
||||
- -fa
|
||||
- "on"
|
||||
- -c
|
||||
- "40960"
|
||||
- "65536"
|
||||
- --parallel
|
||||
- "1"
|
||||
# KV-Cache quantisieren — 32GB VRAM, 35B-A3B + mmproj + Bildkontext:
|
||||
|
||||
@@ -184,8 +184,10 @@ function isoDate(y: number, mo: number, d: number): string | null {
|
||||
|
||||
/** US-Formate: 6/25/26, 06-25-2026, "June 25, 2026" → YYYY-MM-DD. */
|
||||
function normDate(raw: string | null): string | null {
|
||||
const c = cleanStr(raw);
|
||||
let c = cleanStr(raw);
|
||||
if (!c) return null;
|
||||
// Leerzeichen um Trenner entfernen: "09 / 13 / 2021" -> "09/13/2021"
|
||||
c = c.replace(/\s*([\/\-.])\s*/g, "$1").trim();
|
||||
let m = c.match(/^(\d{1,2})[\/\-.](\d{1,2})[\/\-.](\d{2}|\d{4})$/);
|
||||
if (m) return isoDate(parseInt(m[3], 10), parseInt(m[1], 10), parseInt(m[2], 10));
|
||||
m = c.match(/^([A-Za-z]{3,9})\.?\s+(\d{1,2})(?:st|nd|rd|th)?,?\s+(\d{2}|\d{4})$/);
|
||||
@@ -344,7 +346,7 @@ STEP 3 — Transcribe VERBATIM (exactly as written, do not normalize or expand a
|
||||
- total_purchase_price: "Total Purchase Price" as written
|
||||
- down_payment_raw: "Down Payment" as written (e.g. "$350,000", "1.5M", "TBD")
|
||||
6. If doc_type is "ca_only": transcribe from the CA page — the prospective buyer's printed/signed name into prospective_buyer, plus address/phone/email if present. Everything else null.
|
||||
7. date_of_introduction_raw: the date next to the buyer's signature on the CA page, verbatim (e.g. "6/25/26"), else null.
|
||||
7. date_of_introduction_raw: the "Date of Introduction" on the CA page (usually near the buyer's signature), transcribed EXACTLY as written including any spaces or separators (e.g. "09 / 13 / 2021", "6/25/26", "Sept 13 2021"). If a date is visible anywhere labeled "Date of Introduction", always return it verbatim — never leave it null just because the format looks unusual. Only null if truly no such date is present.
|
||||
8. From the NOTES page (only if notes_page is set):
|
||||
- notes_business_raw: the business name(s) written in the "Business Interested In" TABLE of the notes page, verbatim (join multiple with a comma). Take ONLY the table entries — do NOT include the free-text "Notes" area at the bottom of the page. If the table is empty, null.
|
||||
The notes page and the info sheet are INDEPENDENT sources; never copy content from one into the other's field.
|
||||
@@ -426,12 +428,41 @@ async function callVision(api: string, images: string[], timeoutMs: number): Pro
|
||||
// Merge: deterministischer Datensatz + Vision-Rohwerte → Zielstruktur
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Zieht den Namen deterministisch aus dem Dateinamen (verlaessliche Quelle,
|
||||
* unabhaengig von der Vision-Transkription). Schema: "Nachname, Vorname <datum> [Zusatz].pdf".
|
||||
* Gibt "Nachname, Vorname" zurueck, oder null wenn nicht erkennbar.
|
||||
* Beeinflusst die Bilderkennung NICHT — reine String-Operation.
|
||||
*/
|
||||
function nameFromFilename(fileName: string): string | null {
|
||||
let s = fileName.replace(/\.pdf$/i, "");
|
||||
// Klammer-Zusaetze wie "(Gordon Greve)" / "(JF Lehman)" entfernen
|
||||
s = s.replace(/\([^)]*\)/g, " ").replace(/\s+/g, " ").trim();
|
||||
// Schema ist "Nachname, Vorname ...". Nimm den Nachnamen (vor dem Komma)
|
||||
// und aus dem Rest nur das erste Wort als Vorname - alles Weitere
|
||||
// (Zweitnamen, Datum, Notes/Oilfield-Zusaetze) faellt weg.
|
||||
const comma = s.indexOf(",");
|
||||
if (comma < 0) {
|
||||
// kein Komma: erstes Wort als Ganzes nehmen, ohne Datum/Zusatz
|
||||
const first = s.replace(/\b\d{4,8}\b.*$/, "").trim();
|
||||
return first.length >= 2 ? first : null;
|
||||
}
|
||||
const last = s.slice(0, comma).trim();
|
||||
const rest = s.slice(comma + 1).trim();
|
||||
// erstes Token des Rests = Vorname (stoppt vor Datum/Zusatzwort)
|
||||
const firstName = (rest.match(/^[A-Za-zÀ-ÿ.'-]+/) || [""])[0];
|
||||
if (!last || !firstName) return null;
|
||||
return `${last}, ${firstName}`;
|
||||
}
|
||||
|
||||
|
||||
function mergeRecord(det: BuyerRecord, vis: VisionRaw, model: string): BuyerRecord {
|
||||
const base: BuyerRecord = {
|
||||
...det,
|
||||
_parser: "vision",
|
||||
_vision_model: model,
|
||||
_vision_ts: new Date().toISOString(),
|
||||
name_from_filename: nameFromFilename(det.file_name),
|
||||
_vision_error: undefined,
|
||||
};
|
||||
delete (base as Record<string, unknown>)["_vision_error"];
|
||||
@@ -464,7 +495,10 @@ function mergeRecord(det: BuyerRecord, vis: VisionRaw, model: string): BuyerReco
|
||||
down_payment: dp.value,
|
||||
down_payment_raw: dp.raw,
|
||||
// Vision-Datum bevorzugt; Fallback: deterministischer Wert (z.B. aus Dateinamen)
|
||||
date_of_introduction: normDate(vis.date_of_introduction_raw) ?? (det.date_of_introduction as string | null) ?? null,
|
||||
// Datum: ISO wenn parsebar, sonst ROHWERT behalten (Mitarbeiter korrigiert
|
||||
// spaeter). Nie verwerfen, nur weil das Format ungewohnt ist.
|
||||
date_of_introduction: normDate(vis.date_of_introduction_raw) ?? cleanStr(vis.date_of_introduction_raw) ?? (det.date_of_introduction as string | null) ?? null,
|
||||
date_of_introduction_raw: cleanStr(vis.date_of_introduction_raw),
|
||||
_info_page: vis.info_page,
|
||||
_ca_page: vis.ca_page,
|
||||
_notes_page: vis.notes_page,
|
||||
|
||||
Reference in New Issue
Block a user