Šķîþ ţö ḿàîñ çöñţéñţ

Îḿþļéḿéñţîñĝ à Ñéŵ Ţööļ

Ţööļš þŕöçéšš Þàŕţš àš ţĥéý ƒļöŵ ţĥŕöüĝĥ à þîþéļîñé. Ḿöšţ ţööļš öñļý çàŕé àƃöüţ öñé öŕ ţŵö Þàŕţ ţýþéš (üšüàļļý Ƃļöçķš).

Üšîñĝ ƂàšéŢööļ

Ƃüîļđ à tool.BaseTool àñđ šéţ ĥàñđļéŕ ƒüñçţîöñ ƒîéļđš ƒöŕ ţĥé Þàŕţ ţýþéš ýöü ŵàñţ ţö þŕöçéšš. Þàŕţš ýöü đöñ'ţ ĥàñđļé þàšš ţĥŕöüĝĥ üñçĥàñĝéđ. Ţĥéŕé àŕé ţŵö ƒàḿîļîéš öƒ ĥàñđļéŕ.

Ƒöŕ Ƃļöçķ þàŕţš, šéţ éẋàçţļý ÖÑÉ çàþàƃîļîţý-ţýþéđ ĥàñđļéŕ: ţĥé þàŕàḿéţéŕ ţýþé ƃöüñđš ŵĥàţ ţĥé ţööļ ḿàý ŵŕîţé (îḿḿüţàƃîļîţý ḿöđéļ, É-03):

  • Annotate(tool.BlockView) error: ŕéàđ-öñļý; ŵŕîţéš öñļý öṽéŕļàýš, àññöţàţîöñš, àñđ þŕöþéŕţîéš.
  • Produce(tool.VariantView) error: ŕéàđš šöüŕçé, ŵŕîţéš ţàŕĝéţ.
  • Transform(tool.BlockView) (tool.EditPlan, error): à ŕéàđ-öñļý éđîţ þŕöđüçéŕ: ŕéţüŕñš àñ éđîţ þļàñ, àñđ ţĥé ƒŕàḿéŵöŕķ àþþļîéŕ ŕéŵŕîţéš ţĥé šöüŕçé, ŕéƃàšîñĝ šüŕṽîṽîñĝ öṽéŕļàýš, ṽàüļţîñĝ šéçŕéţš, àñđ ƃöüñđš-çĥéçķîñĝ, àţöḿîçàļļý. Ţĥé ƒļöŵ'š þļàçéḿéñţ þàšš ṽàļîđàţéš ŵĥéŕé à ţŕàñšƒöŕḿéŕ ḿàý šîţ.

Ƒöŕ ţĥé ñöñ-Ƃļöçķ þàŕţš (Đàţà, Ḿéđîà, Ļàýéŕ/Ĝŕöüþ šţàŕţ/éñđ), šéţ ţĥé üñţýþéđ Handle*Fn ƒîéļđš, ŵĥîçĥ üšé tool.PartHandler = func(part *model.Part) (*model.Part, error): ţĥéšé ŕéçéîṽé ţĥé šţŕéàḿîñĝ Þàŕţ àñđ ţýþé-àššéŕţ ţĥé ŕéšöüŕçé ţĥéý çàŕé àƃöüţ.

package mytool

import (
"strings"

"github.com/neokapi/neokapi/core/model"
"github.com/neokapi/neokapi/core/tool"
)

func NewUppercaseTool() *tool.BaseTool {
t := &tool.BaseTool{
ToolName: "uppercase",
ToolDescription: "Converts source text to uppercase",
}
// Writes a target, so it sets Produce (the view bounds it to target writes).
t.Produce = func(v tool.VariantView) error {
if !v.Translatable() {
return nil
}
v.SetTargetText(model.LocaleEnglish, strings.ToUpper(v.SourceText()))
return nil
}
return t
}

Ţööļ Çàţéĝöŕîéš

ÇàţéĝöŕýŔéšþöñšîƃîļîţýÉẋàḿþļéš
ŢŕàñšƒöŕḿḾöđîƒý çöñţéñţ îñ-þļàçéçàšé çĥàñĝé, šéàŕçĥ/ŕéþļàçé, ŕéđàçţîöñ
ÉñŕîçĥÀđđ ḿéţàđàţà öŕ öṽéŕļàýššéĝḿéñţàţîöñ, çöñţéñţ-ḿéḿöŕý ļéṽéŕàĝîñĝ, ÀÎ ţŕàñšļàţîöñ, ţéŕḿîñöļöĝý
ṼàļîđàţéÇĥéçķ ǫüàļîţý ŵîţĥöüţ ḿöđîƒýîñĝŕüļé-ƃàšéđ çĥéçķš, ŵöŕđ çöüñţ, šþéļļ çĥéçķ
ÇöñṽéŕţŢŕàñšƒöŕḿ ŕéþŕéšéñţàţîöñšÉñçöđîñĝ çöñṽéŕšîöñ, ļîñé ƃŕéàķ ñöŕḿàļîžàţîöñ

Öṽéŕŕîđîñĝ Þŕöçéšš

΃ ýöü ñééđ ƒüļļ çöñţŕöļ öṽéŕ ţĥé þŕöçéššîñĝ ļööþ (ƒöŕ éẋàḿþļé, ţö àççüḿüļàţé šţàţé àçŕöšš ḿàñý Þàŕţš, öŕ ţö éḿîţ ḿöŕé Þàŕţš ţĥàñ ýöü çöñšüḿé), đéƒîñé à ñàḿéđ ţýþé ţĥàţ éḿƃéđš tool.BaseTool àñđ öṽéŕŕîđé Process đîŕéçţļý:

type MyTool struct {
tool.BaseTool
}

func (t *MyTool) Process(ctx context.Context, in <-chan *model.Part, out chan<- *model.Part) error {
for {
select {
case <-ctx.Done():
return ctx.Err()
case part, ok := <-in:
if !ok {
return nil
}
// Custom processing logic
out <- part
}
}
}

Ŕéĝîšţŕàţîöñ

Ŕéĝîšţéŕ ýöüŕ ţööļ îñ à ToolRegistry, ḿàþþîñĝ à ñàḿé ţö à ƒàçţöŕý:

reg := registry.NewToolRegistry()
reg.Register("uppercase", func() tool.Tool {
return NewUppercaseTool()
})

Üšé RegisterWithSchema îñšţéàđ ţö àţţàçĥ à þàŕàḿéţéŕ šçĥéḿà, àñđ SetConfigFactory šö à ÝÀḾĻ šţéþ'š config: ŕéàçĥéš ţĥé ţööļ; šéé Ţööļ Àüţĥöŕîñĝ.

Ƃüîļţ-îñ Ţööļš

Ţĥé ƒŕàḿéŵöŕķ'š ƃüîļţ-îñ ţööļš àŕé ŕéĝîšţéŕéđ ŵîţĥ ţĥéîŕ þàŕàḿéţéŕ šçĥéḿàš. Ţĥé àüţĥöŕîţàţîṽé, ĝéñéŕàţéđ ļîšţ öƒ ŵĥàţ šĥîþš îñ ţĥé çüŕŕéñţ ƃüîļđ (éṽéŕý ţööļ'š ñàḿé, đéšçŕîþţîöñ, àñđ þàŕàḿéţéŕš) îš ţĥé Ţööļ Ŕéƒéŕéñçé, ŕéñđéŕéđ ƒŕöḿ ţĥöšé šçĥéḿàš šö îţ àļŵàýš ḿàţçĥéš ţĥé ƃüîļđ. Ţĥîš ĝüîđé đéļîƃéŕàţéļý đöéš ñöţ ŕéšţàţé îţ; ƒöŕ ĥöŵ ţĥé ƃüîļţ-îñš ḿàþ ţö ţĥé ķîñđš öƒ ŵöŕķ àƃöṽé, šéé Ţööļš.

Šçĥéḿà-Đŕîṽéñ ÇĻÎ Ƒļàĝš

Àļļ ƃüîļţ-îñ ţööļš üšé šçĥéḿà-đŕîṽéñ ÇĻÎ ƒļàĝš. Ţööļ çöñƒîĝ šţŕüçţš üšé schema:"..." ţàĝš ţö àüţö-ĝéñéŕàţé ƒļàĝš ƒŕöḿ ţĥé šţŕüçţ ƒîéļđš. Üšé schema:"-" ţö éẋçļüđé à ƒîéļđ ƒŕöḿ ƒļàĝ ĝéñéŕàţîöñ. Ţĥé NewToolFromConfig þàţţéŕñ àļļöŵš ţĥé ƒļöŵ éñĝîñé ţö îñšţàñţîàţé ţööļš ƒŕöḿ ÝÀḾĻ çöñƒîĝüŕàţîöñ ƃý ḿàþþîñĝ çöñƒîĝ ķéýš ţö šţŕüçţ ƒîéļđš àüţöḿàţîçàļļý.

Ŕéĝîšţéŕîñĝ Ƃüîļţ-îñ Ţööļš

Àļļ ƃüîļţ-îñ ţööļš çàñ ƃé ŕéĝîšţéŕéđ îñţö à ŕéĝîšţŕý àţ öñçé, éàçĥ ŵîţĥ îţš þàŕàḿéţéŕ šçĥéḿà:

import (
"github.com/neokapi/neokapi/core/registry"
"github.com/neokapi/neokapi/core/tools"
)

toolReg := registry.NewToolRegistry()
tools.RegisterAll(toolReg)

Îñđîṽîđüàļ ţööļš çàñ àļšö ƃé çöñšţŕüçţéđ đîŕéçţļý. Éàçĥ ţàķéš à çöñƒîĝ šţŕüçţ (šéé ţĥé Ţööļ Ŕéƒéŕéñçé ƒöŕ éṽéŕý ƒîéļđ):

// Segmentation with default SRX-like rules
segTool := tools.NewSegmentationTool(&tools.SegmentationConfig{})

// Rule-based check: configured via per-rule flags on RuleCheckConfig
checkTool := tools.NewRuleCheckTool(tools.NewRuleCheckConfig(model.LocaleID("fr")))

// Content-memory leverage with a custom fuzzy threshold and a memory provider
memoryTool := tools.NewMemoryLeverageTool(&tools.MemoryLeverageConfig{
TargetLocale: "fr",
FuzzyThreshold: 80, // 0-100
Memory: memoryProvider,
})

Ţĥé terms þàçķàĝé öƒƒéŕš ţŵö ļîƃŕàŕý ţööļš ƒöŕ éḿƃéđđîñĝ îñ Ĝö, éàçĥ ţàķîñĝ à Terminology àļöñĝšîđé îţš çöñƒîĝ. Ñéîţĥéŕ îš à ŕéĝîšţéŕéđ ƒļöŵ ţööļ: ţĥé ţööļ à ÝÀḾĻ ƒļöŵ öŕ kapi exec ñàḿéš îš term-check, àñđ ŵĥéñ à ţööļ'š šçĥéḿà đéçļàŕéš ţĥàţ îţ ŕéǫüîŕéš à ţéŕḿš šţöŕé, ţĥé ŕüññéŕ àþþéñđš term-lookup àñđ term-enforce àƒţéŕ îţ ŵîţĥ ţĥé ŕüñ'š ļöçàļéš.

import "github.com/neokapi/neokapi/terms"

// Term lookup: scans source text and attaches terminology annotations
termLookupTool := terms.NewTermLookupTool(tb, terms.TermLookupConfig{
SourceLocale: "en",
TargetLocale: "fr",
})

// Term enforce: verifies translations use the preferred terminology
termEnforceTool := terms.NewTermEnforceTool(tb, terms.TermEnforceConfig{
SourceLocale: "en",
TargetLocale: "fr",
})