132 lines
4.1 KiB
Text
132 lines
4.1 KiB
Text
package terminology
|
||
|
||
import (
|
||
"encoding/json"
|
||
"fmt"
|
||
"os"
|
||
"sort"
|
||
"testing"
|
||
|
||
"textmachine/backend/internal/lang"
|
||
)
|
||
|
||
type pyDump struct {
|
||
Roster []struct {
|
||
Src string `json:"src"`
|
||
Type string `json:"type"`
|
||
Origin string `json:"origin"`
|
||
Freq int `json:"freq"`
|
||
Drafts [][]interface{} `json:"drafts"`
|
||
Ctx []string `json:"ctx"`
|
||
Evidence []string `json:"evidence"`
|
||
} `json:"roster"`
|
||
Blocks map[string]string `json:"blocks"`
|
||
Batches [][]string `json:"batches"`
|
||
Series map[string][]string `json:"series"`
|
||
BatchRunes int `json:"batch_runes"`
|
||
}
|
||
|
||
// TestPremisePythonRigMatchesEngine доказывает ИСПОЛНЕНИЕМ, что питон-риг пробы C
|
||
// (consilium_probe.block_of / batches_of) воспроизводит движковые RenderBatch/Batch.
|
||
func TestPremisePythonRigMatchesEngine(t *testing.T) {
|
||
raw, err := os.ReadFile("/home/ubuntu/projects/textmachine/eval/premise_review/py_batching.json")
|
||
if err != nil {
|
||
t.Fatal(err)
|
||
}
|
||
var d pyDump
|
||
if err := json.Unmarshal(raw, &d); err != nil {
|
||
t.Fatal(err)
|
||
}
|
||
|
||
cands := make([]Candidate, 0, len(d.Roster))
|
||
for _, r := range d.Roster {
|
||
c := Candidate{
|
||
Key: r.Src, Src: r.Src, Type: r.Type, Origin: Origin(r.Origin),
|
||
Freq: r.Freq, SinceCh: 0, Evidence: r.Evidence, KWIC: r.Ctx,
|
||
}
|
||
for _, v := range r.Drafts {
|
||
if len(v) != 2 {
|
||
t.Fatalf("draft shape %v", v)
|
||
}
|
||
c.Variants = append(c.Variants, Variant{
|
||
Dst: v[0].(string), Chunks: int(v[1].(float64)),
|
||
})
|
||
}
|
||
cands = append(cands, c)
|
||
}
|
||
|
||
// (1) поблочный рендер
|
||
blockMismatch := 0
|
||
for _, c := range cands {
|
||
got := RenderBatch([]Candidate{c})
|
||
want, ok := d.Blocks[c.Src]
|
||
if !ok {
|
||
t.Fatalf("нет питон-блока для %s", c.Src)
|
||
}
|
||
if got != want {
|
||
blockMismatch++
|
||
if blockMismatch <= 3 {
|
||
t.Errorf("БЛОК РАСХОДИТСЯ %s:\n--- go ---\n%s\n--- py ---\n%s", c.Src, got, want)
|
||
}
|
||
}
|
||
}
|
||
t.Logf("блоков сверено: %d, расхождений: %d", len(cands), blockMismatch)
|
||
|
||
// (2) движок ключ-сортирует кандидатов ДО Batch (terminology.go:212 Merge) — риг делает то же.
|
||
sort.Slice(cands, func(i, j int) bool { return cands[i].Key < cands[j].Key })
|
||
|
||
// (2а) серии движок выводит DetectSeries из язык-слоя, а риг задаёт руками. Сверяем группировки.
|
||
sEnabled, headFinal := lang.SeriesMorphology("zh")
|
||
auto := DetectSeries(cands, SeriesParams{Enabled: sEnabled, HeadFinal: headFinal})
|
||
hand := map[string]int{}
|
||
i := 0
|
||
for _, name := range []string{"zhuan", "deng", "dengzizhi", "jie"} {
|
||
i++
|
||
for _, m := range d.Series[name] {
|
||
hand[m] = i
|
||
}
|
||
}
|
||
groups := func(m map[string]int) map[int][]string {
|
||
g := map[int][]string{}
|
||
for _, c := range cands {
|
||
if id := m[c.Key]; id != 0 {
|
||
g[id] = append(g[id], c.Key)
|
||
}
|
||
}
|
||
return g
|
||
}
|
||
ga, gh := groups(auto), groups(hand)
|
||
t.Logf("DetectSeries(zh, enabled=%v headFinal=%v): %d серий", sEnabled, headFinal, len(ga))
|
||
for id, mem := range ga {
|
||
t.Logf(" движок серия %d: %v", id, mem)
|
||
}
|
||
for id, mem := range gh {
|
||
t.Logf(" риг серия %d: %v", id, mem)
|
||
}
|
||
|
||
got := Batch(cands, d.BatchRunes, auto)
|
||
gotComp := make([][]string, 0, len(got))
|
||
for _, b := range got {
|
||
row := make([]string, 0, len(b))
|
||
for _, c := range b {
|
||
row = append(row, c.Src)
|
||
}
|
||
gotComp = append(gotComp, row)
|
||
}
|
||
gj, _ := json.Marshal(gotComp)
|
||
pj, _ := json.Marshal(d.Batches)
|
||
if string(gj) != string(pj) {
|
||
t.Errorf("СОСТАВ БАТЧЕЙ РАСХОДИТСЯ:\n go=%s\n py=%s", gj, pj)
|
||
} else {
|
||
sizes := ""
|
||
for _, b := range gotComp {
|
||
sizes += fmt.Sprintf(" %d", len(b))
|
||
}
|
||
t.Logf("состав батчей совпал: %d батчей, размеры%s", len(gotComp), sizes)
|
||
}
|
||
|
||
// (3) рунный размер каждого батча против потолка
|
||
for k, b := range got {
|
||
t.Logf("батч %d: %d кандидатов, %d рун (потолок %d)", k, len(b), BatchRunes(b), d.BatchRunes)
|
||
}
|
||
}
|