Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 6 additions & 12 deletions docs/hooks-and-ways/languages.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Multi-Language Support

Ways supports multilingual matching and output across 52 languages. The system uses two embedding models: a precise English model and a broad multilingual model, routed per-way via frontmatter.
Ways supports multilingual matching and output across 52 languages. The system uses two embedding models: a precise English model and a broad multilingual model, routed automatically by the corpus builder.

## Setting output language

Expand Down Expand Up @@ -36,18 +36,12 @@ Two embedding models handle different matching scenarios:

Both are downloaded by `make setup` and stored in `~/.cache/claude-ways/user/`.

Each way declares which model it uses via the `embed_model` frontmatter field:
Model routing is automatic — no frontmatter field needed:

```yaml
---
description: security vulnerability scanning
vocabulary: security vulnerability CVE audit
embed_model: en # default — uses English model
embed_threshold: 0.35
---
```
- **`.md` ways** → English model (all-MiniLM-L6-v2)
- **`.locales.jsonl` entries** → multilingual model (paraphrase-multilingual-MiniLM-L12-v2)

Ways with `embed_model: multilingual` are scored by the multilingual model against a separate corpus.
The corpus builder splits entries into `ways-corpus-en.jsonl` and `ways-corpus-multi.jsonl`, each embedded with the appropriate model.

## Locale stubs — packed format

Expand Down Expand Up @@ -75,7 +69,7 @@ When a Japanese user types a prompt, the scanner:
### Format rules

- **`embed_threshold`** is optional — omit it and the corpus generator defaults to 0.25. Use `ways tune --apply` to compute optimal values automatically.
- **`embed_model`** is implicit — always `multilingual` for locale stubs (not stored in the file).
- **Model routing** is automaticlocale stubs always use the multilingual model (not stored in the file).
- **No body content** — just the JSONL line. If someone writes a full native-language way, they create `security.ja.md` as a regular file, which overrides the packed entry.

### Override mechanism
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
description: intercept raw build, test, lint, publish commands when a Makefile exists
vocabulary: npm run npm test npx pytest cargo build cargo test go build go test pip install docker build docker compose eslint prettier ruff tsc webpack vite jest mocha cargo publish npm publish twine
commands: ^(npm|npx|pytest|cargo|go |pip |docker |eslint|prettier|ruff |tsc|webpack|vite|jest|mocha|twine)
threshold: 2.0
threshold: 1.0
scope: agent, subagent
when:
file_exists: Makefile
Expand Down
2 changes: 1 addition & 1 deletion tools/way-embed/test-multilingual.sh
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ if $MARKDOWN; then
echo "2. **English ways + multilingual model (cross-language)** — user types in any language, matches against English descriptions. Works but scores 30-50% lower."
echo "3. **Native-language stubs + multilingual model (same-language)** — locale entries in \`.locales.jsonl\` with native descriptions. Consistently scores 0.80+ across tested languages."
echo ""
echo "**Recommendation:** Ship both models. English ways use the English model (precise, 21MB). Multilingual stubs use the multilingual model (broad, 127MB). Per-way \`embed_model\` frontmatter field controls routing. This gives per-language threshold tuning without compromising English accuracy."
echo "**Recommendation:** Ship both models. English ways use the English model (precise, 21MB). Multilingual stubs use the multilingual model (broad, 127MB). Routing is automatic — the corpus builder derives the model from file type (.md → EN, .locales.jsonl → multilingual)."
else
echo ""
echo "Results: ${pass}/${total} passed (threshold: ${THRESHOLD})"
Expand Down
2 changes: 1 addition & 1 deletion tools/ways-cli/src/cmd/language.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//! Language coverage report — shows multilingual state of ways.
//!
//! Reports: resolved output language, per-way embed_model,
//! Reports: resolved output language, derived embedding model per way,
//! locale stubs (.locales.jsonl + override .lang.md files), and model availability.

use anyhow::Result;
Expand Down
4 changes: 2 additions & 2 deletions tools/ways-cli/src/cmd/scan/scoring.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@ pub(crate) fn batch_bm25_score(query: &str) -> Vec<(String, f64)> {
/// down" — BM25 fallback is appropriate.
///
/// Queries both EN and multilingual corpora (when available) and merges
/// results. Each way is scored by the model specified in its `embed_model`
/// frontmatter field.
/// results. Each way is scored by its derived model (EN for .md ways,
/// multilingual for .locales.jsonl entries).
pub(crate) fn batch_embed_score(query: &str) -> Option<Vec<(String, f64)>> {
let embed_bin = find_way_embed()?;
let xdg = xdg_cache_dir().join("claude-ways/user");
Expand Down
Loading