Chat-flow analysis + promise-detection baseline (docs + WIP scaffold)#594
Draft
edwh wants to merge 11 commits into
Draft
Chat-flow analysis + promise-detection baseline (docs + WIP scaffold)#594edwh wants to merge 11 commits into
edwh wants to merge 11 commits into
Conversation
✅ Deploy Preview for golden-caramel-d2c3a7 canceled.
|
be5891d to
5833f71
Compare
…Wanted) State machines of User2User chats derived from ~40k new conversations on the live DB over one month, split into separate Offer and Wanted flows (different roles, events, and outcomes). Includes ai-flower workflow JSONs, Graphviz sources, and rendered diagrams. PII-free aggregate analysis only. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
… session brief PHP/Rubix-ML §5.2 baseline (TF-IDF word+char n-grams → logistic regression) over windowed, speaker-tagged, PII-normalised chat spans, as Laravel artisan commands in iznik-batch. Includes the dataset CSV contract, a synthetic fixture, extraction + training/eval commands, pure unit tests (TDD), and plans/promise-detection-session-brief.md so another explorer can try the embedding / DST alternatives off the same contract. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Replace Rubix Pipeline (proba double-transforms) with fit-once/transform-only transformers so AUC/threshold/timing are meaningful; implement featureImportances- based top n-grams with empirical positive-rate; wrap samples; serialize-persist. Cap char-n-gram vocab to bound Rubix's dense matrix. First dev result (768 rooms): linear F1 0.357 / ROC-AUC 0.751 / PR-AUC 0.458, beating the keyword baseline. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…dataset/model outputs Record the FP=20x-FN cost target: success = precision >= ~95% (minimise 20*FP+1*FN); the linear baseline (~64% precision) is net-negative vs never firing under it, so it stands as a proof-of-signal baseline and the bar the embedding/DST tracks must clear. Add storage/promise/.gitignore so the (PII-normalised) dataset CSV + model are never committed. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ng (data corruption) fputcsv/fgetcsv used PHP's default backslash escaping. Spans are full of backslashes (\u.. artefacts) and quotes, so the write/read round-trip broke: fgetcsv merged rows whose fields ended on a stray escape, gluing several spans into one record with the wrong label. The extractor wrote ~3146 rows but the file read back as 1772 — ~30% of the dataset corrupted, invalidating the metrics trained on it. Fix: escape: '' on both fputcsv and fgetcsv (double-quote quoting). Verified: a 40-room probe now reads back exactly as many records as were written. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
… near-chance Re-ran on de-corrupted data: linear F1 0.206 / ROC-AUC 0.591 / PR-AUC 0.198 — near chance and beaten by the keyword baseline. The earlier F1 0.357/ROC 0.751 were artefacts of the merged-row corruption. Verdict stands and strengthens: not deployable under 20:1; bar for embedding/DST is precision >= ~95%. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…erance, fixture, ROC data) - assertEqual -> assertEquals across DatasetExtractorTest + PiiNormaliserTest (assertEqual is not a PHPUnit 11 method -> 14 errors) - DatasetExtractor: keep j=0 and the final turn (unless it IS the promise turn) within tolerance, and emit rows newest-first so spans include both speakers - KeywordBaseline: treat 'thank you so much' as an acceptance signal - dataset_fixture.csv: trim to the documented 22 data rows - EvaluatorTest: use genuinely-interleaved scores for the ~random ROC case Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…tring Four single-arg calls (the \r/\n/\t collapse test + whitespace-only test) threw ArgumentCountError under PHPUnit 11. Pass $result as the haystack. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ps the address regex normalise() also redacts '<number> <Word>' as <ADDRESS>, so 'Line 1 Line 2 Tabbed' became 'Line <ADDRESS> <ADDRESS>'. Use digit-free words; the test is about \r\n\t collapsing, not PII. Verified against the real normaliser. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ESS>
The street-address pattern was /\b\d{1,4}\s+[A-Z][a-z]+.../i — with /i it matched
times/durations/quantities ('come at 6 pm', 'in 2 days', '3 chairs', '7 tonight'),
emitting fake <ADDRESS> tokens. Since a shared address is one of the strongest
promise signals (the keyword baseline fires on any <ADDRESS>), this injected false
positives into the dataset, the baseline and the reader.
Now require a real street suffix (Street/Road/Lane/...) with a capitalised street
name; bare number+word no longer matches. Verified against the failing examples and
real addresses; regression tests added.
NOTE: the extracted CSVs (dev/full) were built with the buggy normaliser and must be
re-extracted; model results derived from them are contaminated.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…he whole chat_rooms set and times out the live-DB tunnel. Use a cheap PK-ordered scan (id desc) bounded by --since/--max-rooms instead. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
f5b7dd7 to
ed6f31f
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This branch carries two related pieces of work on understanding Freegle member-to-member chats. Docs + a work-in-progress ML scaffold; no production code paths are touched.
Part 1 — Empirical chat-conversation flowcharts (Offer & Wanted)
State machines of
User2Userchats, derived from the live DB (V2 live API tunnel) over ~40k new conversations in one month, read against ~260 full conversations. Offer and Wanted behave differently, so each has its own flow.Key finding:
Completedonly closes the post — it does not prove the replier in this chat got the item. A bareInterested → Completed, or a two-sided chat ending "sorry, gone to someone else", is not a collection. Counting only genuine handover-to-this-replier:Files:
plans/freegle-chat-flow.md,…-offer.{png,dot}+…-offer-workflow.json,…-wanted.{png,dot}+…-wanted-workflow.json(ai-flower workflow definitions, % on every transition).Part 2 — Promise-detection: linear baseline scaffold (WIP) + session brief
Detecting the
promisedstate (the point an exchange is committed to) from natural-language dialogue, per the working-notes spec. This is the pragmatic §5.2 baseline: a linear classifier over TF-IDF word + char n-grams on windowed, speaker-tagged, PII-normalised spans, as Laravel artisan commands iniznik-batch.plans/promise-detection-session-brief.md— full brief: spec interpretation, locked decisions (PHP/Rubix-ML, static CSV, address-as-signal not pure leakage, charset/utf8mb4), live-DB findings (~16.5% positive; role resolution), sample sizing, the dataset CSV contract, and the open alternatives (embedding classifier, DST/generative, zero-shot NLI) so another explorer can build a comparable model off the samespan→labelcontract.iznik-batch/app/Services/Promise,…/Console/Commands/Promise):PiiNormaliser,DatasetExtractor,CharNgramTokenizer,DatasetReader,KeywordBaseline,FeaturePipeline,Evaluator(P/R/F1, ROC/PR-AUC, threshold sweep, promise-timing offsets),promise:extract+promise:traincommands, 6 unit-test files (53 cases), the CSVCONTRACT.md+ synthetic fixture, andrubix/mlin composer.Status — runs end-to-end on real data; WIP, not merge-ready. Defects fixed along the way: real probabilities (the Rubix
Pipeline::proba()double-transformed — replaced with fit-once/transform-only transformers), top n-grams implemented, and a CSV data-corruption bug (fputcsv/fgetcsvdefault\-escaping silently merged ~30% of rows on read — spans are full of\u..artefacts + quotes; fixed with RFC-4180escape: ''). Clean result on a 768-room sample (2,516 train / 640 test, split by conversation, 13% positive): linear F1 0.206 / ROC-AUC 0.591 / PR-AUC 0.198 — near chance, and the keyword baseline beats it on F1 (0.333). (An earlier "F1 0.357 / ROC-AUC 0.751" was an artefact of the corrupted data.)Success criterion is cost-based, and the baseline fails it. A false positive (wrongly claiming a promise) is stated as 20× worse than a false negative. That makes the target precision ≥ ~95% (minimise expected cost
20·FP + 1·FN; fire only atP>~0.95); below ~95% precision a model is net-negative versus never firing. On clean data the linear baseline tops out ~33% precision (and ROC-AUC 0.591, near chance), so under 20:1 it's not deployable — and it isn't even a convincing proof-of-signal. It sets the bar (precision ≥95%) the embedding/DST alternatives must clear. See the brief for the full reasoning and design implications (two-stage triage / human-in-loop).Remaining issues: Rubix's dense vectoriser OOMs on char-n-grams at scale (capped for now); char-grams dominate the feature importances and add noise (a word-grams-only pass is the cheap next experiment). This part is pushed to enable parallel exploration, not to merge as-is.
Branch hygiene + test-suite fixes
This branch had accumulated unrelated commits from several sessions (monitor-fsm, mail-retry, freegle tooling) — all of which had already landed in
master— plus one duplicate mail commit. It has been rebased onto currentmaster, dropping every one of those; it now contains only the chat-flow docs (Part 1) and the promise scaffold (Part 2).The committed unit tests also carried PHPUnit-validity bugs that the rebase surfaced, now fixed so the suite runs cleanly:
assertEqual()(17 uses) — not a method in PHPUnit 11 → replaced withassertEquals().assertStringNotContainsString()called with a single argument (4 uses) → missing$resulthaystack supplied.DatasetExtractorwindow/tolerance logic and a fixture/assertion drift (EvaluatorTest"random" ROC data, fixture row count, aKeywordBaselineacceptance phrase).\r\n\t-collapse test used digit+word input (Line 1 … Line 2) that the normaliser's address regex redacts to<ADDRESS>; switched to digit-free words.Notes
master.🤖 Generated with Claude Code