This repository studies whether Classical Chinese / Wenyanwen can serve as a useful prompt language for LLMs under a quality–cost tradeoff framing rather than a purely stylistic one. 宣传友链: https://linux.do/
It currently contains two closely related experiment families:
- the original matrix comparison over prompt-language settings (
base / zh_compact / wy), and - the newer LangMatch 3-run comparison over interaction settings (
explicit_process / hidden / compact_visible) while keeping the language settings fixed asbase / zh / wy.
The current codebase supports a fixed evaluation matrix over:
- Models:
gpt-4o,gpt-5.4,qwen3-1.7b,qwen3-4b - Prompt modes:
base,zh_compact,wy - Benchmarks:
IFEval,MATH-500(text-only subset),MMLU-Pro
For the LangMatch 3-run workflow, the current public release includes:
- Models:
gpt-4o,gpt-5.4,qwen3-4b - Interaction settings:
explicit_process: explicitly request visible reasoninghidden: request careful thinking but no visible reasoningcompact_visible: allow only brief visible reasoning
- Language settings:
base,zh,wy - Currently exported benchmarks:
MATH-500,MMLU-Pro
The current LangMatch 3-run report keeps the IFEval panel in the figure layout for comparability, but the exported 3-run artifact set does not currently include IFEval rows. Treat those panels as explicit missing-data placeholders, not negative results.
The repository has already gone through one important methodological correction:
- the original small-cap runs are kept only as a truncated pilot,
- the current main comparison is the 2048-token rerun, which removes the largest output-budget artifact for the closed-source models and
qwen3-4b.
If you extend this repo, treat the 2048 rerun reports as the main baseline.
The project asks whether changing only the system prompt language can alter the tradeoff between:
- task performance (
Score / SR), and - inference cost (
Prompt Tok,Completion Tok,Total Tok).
The key comparison is not simply “which language is shorter”, but:
under fixed tasks and fixed model backends, does a more compressed prompt language produce a better quality–cost frontier?
The current experiment uses three system-prompt modes.
English compact baseline:
You are a helpful assistant. Follow the user's instructions carefully. Except for code and direct quotations, keep explanations and narration concise. Avoid colloquial filler. Eliminate redundancy and aim for compact, clear expression.
Modern Chinese compact prompt:
你是一个有帮助的助手。请严格遵循用户要求。除代码和直接指令外,所有解释与叙述都尽量写得简洁。禁止口语化赘述,删繁就简,要求表达精炼、意思清楚。
Wenyan / Classical Chinese compact prompt:
汝为善应人问之助手,当谨循其命。凡码与引文外,释理叙事宜从简。禁绝白话冗词,务求辞约义明。
These are intentionally close in function, but not identical in linguistic form. The design goal is to compare realistic prompt-language regimes rather than perfectly translation-aligned paraphrases.
scripts/run_pilot.py: main experiment runneraggregate_matrix_results.py: aggregates per-run summaries into report tablesgenerate_matrix_plots.py: generates benchmark comparison figuresprepare_langmatch_manifests.py: builds language-matched manifests forhiddenandcompactmodesrun_langmatch_experiment.py: runs the LangMatch experiment over prepared manifestsaggregate_langmatch_results.py: aggregates LangMatch run directories into Markdown tablesexport_langmatch_outputs.py: exports consolidated LangMatch per-sample outputsexport_langmatch_3runs.py: consolidates the 3-run comparison into publish-safe tables and local-only interaction exportsgenerate_langmatch_3runs_plots.py: generates the 12 LangMatch Pareto plots
docs/- proposal and result reports
- English and Chinese analysis docs
- generated figures used in reports
- LangMatch 3-run Chinese report and publish-safe summary artifacts
data/- fixed manifests for pilot runs and full matrix runs
- these manifests define the exact benchmark subsets and per-task token caps
langmatch_v1/: explicit-process manifestslangmatch_v2/: hidden / compact-visible manifestslangmatch_source_manifest_v1.json: source benchmark subset used for LangMatch
src/wyw_pilot/- minimal package root; currently light, reserved for future shared utilities
tests/- regression tests for LangMatch manifest preparation and hidden-think splitting behavior
log/- local run outputs (
results.jsonl,summary.json,summary.md, etc.) - ignored by git
- local run outputs (
The pipeline is deliberately manifest-driven:
- Manifest selection
- choose a fixed subset from
data/*.json
- choose a fixed subset from
- Model execution
run_pilot.pyruns all(task × prompt mode)combinations
- Raw persistence
- each run writes
results.jsonl,manifest.json,summary.json,summary.md
- each run writes
- Aggregation
aggregate_matrix_results.pymerges multiple run directories into one matrix report
- Visualization
generate_matrix_plots.pydraws Pareto-styleScore vs Total Tokfigures
The LangMatch flow is similar but explicitly separates manifest construction, run execution, export, and 3-run reporting:
prepare_langmatch_manifests.pyconstructslangmatch_v1/orlangmatch_v2/manifestsrun_langmatch_experiment.pyexecutes one model over one manifest directoryaggregate_langmatch_results.pysummarizes a set of model runsexport_langmatch_3runs.pyconsolidates the 3-run comparisongenerate_langmatch_3runs_plots.pyproduces the publish-safe Pareto figures used in the report
The current main matrix is based on:
data/matrix_manifest_2048_v1.json- unified output budget: 2048
This rerun exists because the original pilot used tight caps (IFEval=192, MATH-500=64, MMLU-Pro=8), which introduced severe truncation artifacts.
The most important failure case in the original pilot was:
gpt-5.4 / IFEval
Under the original cap, many rows returned empty visible output while still consuming the full completion budget. That made the model look weaker than it really was. After rerunning at 2048, the same slice recovered to 1.000 SR across all three prompt modes.
After the 2048 rerun:
gpt-4o: no remaining cap-hit artifacts in the main rerungpt-5.4: no remaining cap-hit artifacts in the main rerunqwen3-4b: no remaining cap-hit artifacts in the main rerunqwen3-1.7b: still has a small residual truncation risk (4rows withfinish_reason=length)
So the current 2048 matrix is appropriate as the main comparison for:
- closed-source models
qwen3-4b
but qwen3-1.7b should still be interpreted cautiously.
The runner now records enough metadata to audit output-budget problems directly:
configured_max_tokensfinish_reasonusage_details
For future work, treat a row as suspicious if any of the following holds:
finish_reason == "length"completion_tokens == configured_max_tokensresponse_textis empty but token usage is non-zero
Do not report cross-model conclusions without checking those conditions.
The corrected 2048 rerun currently supports the following working conclusions:
zh_compactis the most robust default across model families.wyis not universally best, but it is a real contender on strong models.- On
gpt-5.4,wyis the strongest overall prompt mode in the corrected matrix. - On
MATH-500, the strongest-model behavior remains especially interesting:gpt-4opreferszh_compactgpt-5.4preferswy
For the LangMatch 3-run comparison, the current working conclusion is slightly sharper:
- visible-reasoning format matters in addition to prompt language;
gpt-5.4 / wyis strongest underexplicit_processandcompact_visible;hiddenis mainly a cost-reduction setting rather than a score-maximizing one;qwen3-4bdoes not show a stable Wenyan advantage across the 3-run setup.
That makes Wenyan a conditional prompt-compression strategy, not a universal one.
For the latest writeups, see:
docs/matrix_eval_results_2048.mddocs/matrix_eval_results_2048_zh.mddocs/langmatch_3runs_results_zh.md
This repo uses Python and uv.
Example setup:
uv venv .venv
uv pip install --python .venv/bin/python -e .Use environment variables. Do not hardcode keys in commands, scripts, docs, or commits.
export OPENAI_BASE_URL="https://your-compatible-endpoint/v1"
export OPENAI_API_KEY="<set-in-your-shell-environment>"
.venv/bin/python scripts/run_pilot.py \
--backend openai \
--model gpt-4o \
--manifest data/matrix_manifest_2048_v1.json \
--output-dir log/matrix-2048-gpt-4o.venv/bin/python scripts/run_pilot.py \
--backend transformers \
--model qwen3-4b \
--local-model-path Qwen/Qwen3-4B \
--manifest data/matrix_manifest_2048_v1.json \
--output-dir log/matrix-2048-qwen3-4b.venv/bin/python scripts/aggregate_matrix_results.py \
--run gpt-4o=log/matrix-2048-gpt-4o \
--run gpt-5.4=log/matrix-2048-gpt-5.4 \
--run qwen3-1.7b=log/matrix-2048-qwen3-1.7b \
--run qwen3-4b=log/matrix-2048-qwen3-4b \
--output docs/matrix_eval_results_2048.md.venv/bin/python scripts/generate_matrix_plots.py \
--run gpt-4o=log/matrix-2048-gpt-4o \
--run gpt-5.4=log/matrix-2048-gpt-5.4 \
--run qwen3-1.7b=log/matrix-2048-qwen3-1.7b \
--run qwen3-4b=log/matrix-2048-qwen3-4b \
--output-dir docs/figures/matrix_eval_results_2048.venv/bin/python scripts/prepare_langmatch_manifests.py \
--source-manifest data/langmatch_source_manifest_v1.json \
--mode hidden \
--output-dir data/langmatch_v2
.venv/bin/python scripts/prepare_langmatch_manifests.py \
--source-manifest data/langmatch_source_manifest_v1.json \
--mode compact \
--output-dir data/langmatch_v2.venv/bin/python scripts/run_langmatch_experiment.py \
--backend openai \
--model gpt-4o \
--manifest data/langmatch_v2/langmatch_hidden_manifest.json \
--output-dir log/langmatch-hidden-gpt4o-v2.venv/bin/python scripts/aggregate_langmatch_results.py \
--run gpt-4o=log/langmatch-hidden-gpt4o-v2 \
--run gpt-5.4=log/langmatch-hidden-gpt54-v2 \
--run qwen3-4b=log/langmatch-hidden-qwen3-4b-v2 \
--output docs/langmatch_hidden_summary.mdThe public release ships the aggregated 3-run outputs (langmatch_3runs_tok_sr_table.*, langmatch_3runs_plot_summary.json, figures, and report), but it does not ship raw interaction dumps. That split is intentional: the raw exports can contain provider-specific traces and large prompt/response payloads.
So there are two distinct cases:
- Maintainer-side local export: use
export_langmatch_3runs.pyafter you have local LangMatch run directories. - Public-release figure regeneration: use
generate_langmatch_3runs_plots.pydirectly from the shippedlangmatch_3runs_plot_summary.json.
Maintainer-side local export:
.venv/bin/python scripts/export_langmatch_3runs.pyPublic-release figure regeneration:
.venv/bin/python scripts/generate_langmatch_3runs_plots.pyIf you want to do secondary development, the cleanest extension points are:
- add a new run with the existing manifest
- keep it as a new model row, not a silent replacement
- if the model has configurable reasoning modes, treat each configuration as a separate model identity
- add a new loader in
run_pilot.py - create a fixed manifest subset in
data/ - add an evaluator that produces a deterministic
score - only then extend aggregation and plotting
- do it at the manifest level or with
--max-tokens-override - never compare runs with different caps as if they were the same matrix
Current plots are intentionally simple and paper-friendly:
- x-axis:
Total Tok - y-axis:
Score / SR - color: model
- marker shape: prompt mode
If you redesign plotting, preserve the ability to compare within-model prompt tradeoffs.
This repository must not leak API keys or private endpoints.
Rules:
- never commit keys, bearer tokens,
.envfiles, or raw credential strings - only use environment-variable placeholders in docs and scripts
- do not copy-paste live credentials into READMEs, notebooks, or manifests
- keep runtime logs out of git unless they have been explicitly sanitized
- keep raw prompt/response dumps and hidden-think traces out of the open-source release unless you have explicitly scrubbed them for publication
The repo now ignores:
.env.env.*.venv/.worktrees/log/- raw JSONL exports such as per-sample dumps and local interaction logs
If you add any new local secret file, update .gitignore first.
For contributors or reviewers, the fastest way to understand the project is:
README.mddocs/开题报告草案.mddocs/matrix_eval_results_2048_zh.mdordocs/matrix_eval_results_2048.mddocs/langmatch_3runs_results_zh.mdscripts/run_pilot.pyscripts/run_langmatch_experiment.pyscripts/aggregate_matrix_results.pyscripts/generate_matrix_plots.pyscripts/generate_langmatch_3runs_plots.py
This codebase is not just a collection of ad hoc scripts. It is now organized around a reproducible matrix-evaluation workflow with:
- fixed manifests
- explicit rerun correction after truncation auditing
- bilingual reporting
- plot generation
- enough metadata for future fairness checks
The main thing to preserve in future development is methodological discipline: do not mix pilot results, corrected reruns, and altered model settings into one undifferentiated table.