onw 1.2.2: API default sampling setting (for apps that send none), chat starts from custom values
Browse files- CHANGELOG.md +6 -0
- CHANGELOG_en.md +6 -0
- MANUAL.md +1 -0
- MANUAL_en.md +1 -0
- onw/__init__.py +1 -1
- onw/app.py +10 -1
- onw/i18n.json +14 -0
- onw/manager.py +11 -1
- onw/server.py +22 -4
- onw/web/index.html +4 -1
- onw/web/manage.html +15 -1
- pyproject.toml +1 -1
CHANGELOG.md
CHANGED
|
@@ -5,6 +5,12 @@
|
|
| 5 |
日付は日本時間です。各版は Hugging Face の `ryugyosoft/onw` にタグ(`v0.4.2` 以降)付きで残っています。
|
| 6 |
onw ウィンドウは、新しい版があるとこのファイルから変更点を表示します(`## v…` の見出しで区切っています)。
|
| 7 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 8 |
## v1.2.1 (2026-10-04)
|
| 9 |
- Gemma:設定の「64 トークン処理」を切り替えるたびに、NPU 向けのコンパイル(数分)をやり直していた問題を修正。スライディング
|
| 10 |
ウィンドウ層のリングの長さが「読み込んだ中で最大のブロック」で決まっていたため、64 トークン処理のオン/オフで 1 トークン用・
|
|
|
|
| 5 |
日付は日本時間です。各版は Hugging Face の `ryugyosoft/onw` にタグ(`v0.4.2` 以降)付きで残っています。
|
| 6 |
onw ウィンドウは、新しい版があるとこのファイルから変更点を表示します(`## v…` の見出しで区切っています)。
|
| 7 |
|
| 8 |
+
## v1.2.2 (2026-10-04)
|
| 9 |
+
- 設定の「サーバーと API」に「API の既定の生成設定」を追加。温度・Top P などを送らないアプリ(OpenCode など)のリクエストに、
|
| 10 |
+
「貪欲(温度 0。これまでどおり、既定)」「モデルの推奨値(チャット画面と同じ。Qwen 系は思考時に思考用の値)」「自分で指定」の
|
| 11 |
+
どれを使うかを選べます。アプリが送った値はそのまま使います。「自分で指定」にすると、チャット画面の初期値もその値になります
|
| 12 |
+
(「(設定の値)」と表示)。
|
| 13 |
+
|
| 14 |
## v1.2.1 (2026-10-04)
|
| 15 |
- Gemma:設定の「64 トークン処理」を切り替えるたびに、NPU 向けのコンパイル(数分)をやり直していた問題を修正。スライディング
|
| 16 |
ウィンドウ層のリングの長さが「読み込んだ中で最大のブロック」で決まっていたため、64 トークン処理のオン/オフで 1 トークン用・
|
CHANGELOG_en.md
CHANGED
|
@@ -4,6 +4,12 @@
|
|
| 4 |
|
| 5 |
Dates are JST. Every version is on Hugging Face `ryugyosoft/onw`, tagged from `v0.4.2` on.
|
| 6 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 7 |
## v1.2.1 (2026-10-04)
|
| 8 |
- Gemma: switching "64-token blocks" in the settings compiled the model for the NPU again (minutes) every time. The
|
| 9 |
sliding-window layers' ring length followed the largest block loaded, so turning the 64-token blocks on or off changed
|
|
|
|
| 4 |
|
| 5 |
Dates are JST. Every version is on Hugging Face `ryugyosoft/onw`, tagged from `v0.4.2` on.
|
| 6 |
|
| 7 |
+
## v1.2.2 (2026-10-04)
|
| 8 |
+
- Settings, Server and API: "API default sampling" for requests that send no temperature, Top P etc. (OpenCode, ...):
|
| 9 |
+
greedy (temperature 0, as before, the default), the model's recommended values (as in the chat; the Qwen family
|
| 10 |
+
switches to its thinking values when thinking) or custom values. Values an app sends are always used. With custom
|
| 11 |
+
values the chat page starts from them too ("(the values from the settings)").
|
| 12 |
+
|
| 13 |
## v1.2.1 (2026-10-04)
|
| 14 |
- Gemma: switching "64-token blocks" in the settings compiled the model for the NPU again (minutes) every time. The
|
| 15 |
sliding-window layers' ring length followed the largest block loaded, so turning the 64-token blocks on or off changed
|
MANUAL.md
CHANGED
|
@@ -143,6 +143,7 @@
|
|
| 143 |
| コンテキスト長 | 会話で使える最大の長さ。KV キャッシュは実際に使った分だけメモリを使うので、大きくしても短い会話は遅くなりません。変えても再コンパイルはありません |
|
| 144 |
| LAN からの接続を許可する | 他の PC から API を使えるようにします(API キーの設定をおすすめします) |
|
| 145 |
| API で思考の指定がないリクエストも考えてから答える | `enable_thinking` を送らないエージェントのアプリ向け。回答は遅くなります |
|
|
|
|
| 146 |
|
| 147 |
### 速さとメモリ
|
| 148 |
|
|
|
|
| 143 |
| コンテキスト長 | 会話で使える最大の長さ。KV キャッシュは実際に使った分だけメモリを使うので、大きくしても短い会話は遅くなりません。変えても再コンパイルはありません |
|
| 144 |
| LAN からの接続を許可する | 他の PC から API を使えるようにします(API キーの設定をおすすめします) |
|
| 145 |
| API で思考の指定がないリクエストも考えてから答える | `enable_thinking` を送らないエージェントのアプリ向け。回答は遅くなります |
|
| 146 |
+
| API の既定の生成設定 | 温度・Top P などを送らないアプリ(OpenCode など)のリクエストに使う値。「貪欲(温度 0)」(既定)、「モデルの推奨値」(チャット画面と同じ。Qwen 系は思考時に思考用の値)、「自分で指定」。アプリが送った値はそのまま使います。「自分で指定」にすると、チャット画面の初期値もその値になります |
|
| 147 |
|
| 148 |
### 速さとメモリ
|
| 149 |
|
MANUAL_en.md
CHANGED
|
@@ -152,6 +152,7 @@ applies them ("Discard" throws them away). For settings that need a server resta
|
|
| 152 |
| Context length | The longest a conversation can get. The KV cache only uses memory for what is used, so a larger value does not slow short conversations; changing it needs no recompile |
|
| 153 |
| Allow connections from the LAN | Lets other PCs use the API (setting an API key is recommended) |
|
| 154 |
| Think before answering API requests that do not say | For agent apps that never send `enable_thinking`. Answers take longer |
|
|
|
|
| 155 |
|
| 156 |
### Speed and memory
|
| 157 |
|
|
|
|
| 152 |
| Context length | The longest a conversation can get. The KV cache only uses memory for what is used, so a larger value does not slow short conversations; changing it needs no recompile |
|
| 153 |
| Allow connections from the LAN | Lets other PCs use the API (setting an API key is recommended) |
|
| 154 |
| Think before answering API requests that do not say | For agent apps that never send `enable_thinking`. Answers take longer |
|
| 155 |
+
| API default sampling | The values for requests that send no temperature, Top P etc. (OpenCode, ...): greedy (temperature 0, the default), the model's recommended values (as in the chat; the Qwen family switches to its thinking values when thinking) or custom. Values an app sends are always used. With custom values the chat page starts from them too |
|
| 156 |
|
| 157 |
### Speed and memory
|
| 158 |
|
onw/__init__.py
CHANGED
|
@@ -2,4 +2,4 @@
|
|
| 2 |
|
| 3 |
A small engine that runs LLMs entirely on the Intel NPU: static segment graphs + host-managed state.
|
| 4 |
"""
|
| 5 |
-
__version__ = "1.2.
|
|
|
|
| 2 |
|
| 3 |
A small engine that runs LLMs entirely on the Intel NPU: static segment graphs + host-managed state.
|
| 4 |
"""
|
| 5 |
+
__version__ = "1.2.2"
|
onw/app.py
CHANGED
|
@@ -84,7 +84,8 @@ STREAMABLE = {
|
|
| 84 |
}
|
| 85 |
DEFAULTS = {"model": "", "port": 8000, "lan": False, "api_key": "", "context": 32768, "device": "NPU",
|
| 86 |
"autostart_server": True, "login_start": False, "models_dir": "", "model_folders": [], "pld": True, "big_blocks": "auto", "npuw": "auto", "expert_gb": "auto", "update_check": True, "mem_saver": False, "mem_saver_strict": False, "think_default": False,
|
| 87 |
-
"lang": "auto", "npuw_moe": False, "npuw_async": False, "cache_size": False
|
|
|
|
| 88 |
CONTEXTS = ["1024", "2048", "4096", "8192", "16384", "32768", "65536", "131072", "262144"]
|
| 89 |
|
| 90 |
|
|
@@ -651,6 +652,14 @@ def _start_server(cfg):
|
|
| 651 |
env["ONW_EXPERT_GB"] = str(budget)
|
| 652 |
if cfg.get("think_default"): # API requests that say nothing about thinking: think
|
| 653 |
env["ONW_THINK_DEFAULT"] = "1"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 654 |
if cfg.get("mem_saver") and saver_applies(model, cfg): # memory-saving mode: one block size at a time
|
| 655 |
env["ONW_LAZY16"] = "1"
|
| 656 |
if cfg.get("mem_saver_strict"): # strict: never both block sizes at once (answers wait)
|
|
|
|
| 84 |
}
|
| 85 |
DEFAULTS = {"model": "", "port": 8000, "lan": False, "api_key": "", "context": 32768, "device": "NPU",
|
| 86 |
"autostart_server": True, "login_start": False, "models_dir": "", "model_folders": [], "pld": True, "big_blocks": "auto", "npuw": "auto", "expert_gb": "auto", "update_check": True, "mem_saver": False, "mem_saver_strict": False, "think_default": False,
|
| 87 |
+
"lang": "auto", "npuw_moe": False, "npuw_async": False, "cache_size": False,
|
| 88 |
+
"api_sampling": "greedy", "api_temperature": 0.7, "api_top_p": 0.95, "api_top_k": 20, "api_presence": 0.0}
|
| 89 |
CONTEXTS = ["1024", "2048", "4096", "8192", "16384", "32768", "65536", "131072", "262144"]
|
| 90 |
|
| 91 |
|
|
|
|
| 652 |
env["ONW_EXPERT_GB"] = str(budget)
|
| 653 |
if cfg.get("think_default"): # API requests that say nothing about thinking: think
|
| 654 |
env["ONW_THINK_DEFAULT"] = "1"
|
| 655 |
+
# API requests that send no sampling values (agent apps like OpenCode): greedy, the model's recommendation or set
|
| 656 |
+
if cfg.get("api_sampling") == "recommended":
|
| 657 |
+
env["ONW_API_SAMPLING"] = "recommended"
|
| 658 |
+
elif cfg.get("api_sampling") == "custom":
|
| 659 |
+
env["ONW_API_SAMPLING"] = json.dumps({"temperature": float(cfg.get("api_temperature", 0.7)),
|
| 660 |
+
"top_p": float(cfg.get("api_top_p", 0.95)),
|
| 661 |
+
"top_k": int(cfg.get("api_top_k", 0)),
|
| 662 |
+
"presence_penalty": float(cfg.get("api_presence", 0.0))})
|
| 663 |
if cfg.get("mem_saver") and saver_applies(model, cfg): # memory-saving mode: one block size at a time
|
| 664 |
env["ONW_LAZY16"] = "1"
|
| 665 |
if cfg.get("mem_saver_strict"): # strict: never both block sizes at once (answers wait)
|
onw/i18n.json
CHANGED
|
@@ -10,6 +10,7 @@
|
|
| 10 |
"35B MoE を半分に刈り込み": "The 35B MoE pruned by half",
|
| 11 |
"64 トークン処理": "64-token blocks",
|
| 12 |
"API で思考の指定がないリクエストも考えてから答える": "Think before answering API requests that do not say",
|
|
|
|
| 13 |
"API キー(任意)": "API key (optional)",
|
| 14 |
"Hugging Face に接続できません: {0}": "Cannot reach Hugging Face: {0}",
|
| 15 |
"IBM の 8B。思考とツール呼び出し・コーディング向け": "IBM's 8B, for thinking, tool calls and coding",
|
|
@@ -132,6 +133,7 @@
|
|
| 132 |
"メモリ目安": "Memory (est.)",
|
| 133 |
"メモリ節約モード": "Memory-saving mode",
|
| 134 |
"モデル": "Models",
|
|
|
|
| 135 |
"モデルは読み込まれていません": "No model loaded",
|
| 136 |
"モデルをロード": "Load model",
|
| 137 |
"モデルを削除": "Delete model",
|
|
@@ -253,9 +255,11 @@
|
|
| 253 |
"次の文章を、元の表現をなるべく使って2文に要約してください。": "Summarize the following text in two sentences, reusing its wording as much as possible.",
|
| 254 |
"止まった理由: {0}": "Why it stopped: {0}",
|
| 255 |
"温度": "Temperature",
|
|
|
|
| 256 |
"準備中…": "Preparing…",
|
| 257 |
"無効": "Off",
|
| 258 |
"状態": "Status",
|
|
|
|
| 259 |
"生成速度": "Decode speed",
|
| 260 |
"画像": "Image",
|
| 261 |
"画像も読めます": "Reads images too",
|
|
@@ -267,6 +271,7 @@
|
|
| 267 |
"終了(サーバーも停止)": "Quit (stops the server too)",
|
| 268 |
"結果": "Result",
|
| 269 |
"繰り返し抑制": "Repetition penalty",
|
|
|
|
| 270 |
"自分で置いたモデル・{0}": "Your own model · {0}",
|
| 271 |
"要約や書き直しなど、元の文章をなぞる回答が速くなります。": "Speeds up answers that reuse the prompt's text, such as summaries and rewrites.",
|
| 272 |
"言語": "Language",
|
|
@@ -274,6 +279,7 @@
|
|
| 274 |
"設定は保存しました。サーバーを新しい設定で今すぐ再起動しますか?(キャンセルしても、次にモデルを読み込むときから反映されます)": "Settings saved. Restart the server with the new settings now? (Cancel keeps them for the next model load.)",
|
| 275 |
"詳細": "Advanced",
|
| 276 |
"読み込み中…": "Loading…",
|
|
|
|
| 277 |
"起動時と 1 日ごとに更新を確認する": "Check for updates at startup and daily",
|
| 278 |
"起動時に前回ロードしたモデルを自動でロードする": "Load the last model automatically at startup",
|
| 279 |
"追加…": "Add…",
|
|
@@ -298,6 +304,7 @@
|
|
| 298 |
"(再利用 {0})": " (reused {0})",
|
| 299 |
"(無題)": "(untitled)",
|
| 300 |
"(画像)": "(image)",
|
|
|
|
| 301 |
"+ 新しい会話": "+ New conversation"
|
| 302 |
},
|
| 303 |
"zh": {
|
|
@@ -311,6 +318,7 @@
|
|
| 311 |
"35B MoE を半分に刈り込み": "35B MoE 裁剪一半",
|
| 312 |
"64 トークン処理": "64 token 分块",
|
| 313 |
"API で思考の指定がないリクエストも考えてから答える": "API 请求未指定思考时也先思考再回答",
|
|
|
|
| 314 |
"API キー(任意)": "API 密钥(可选)",
|
| 315 |
"Hugging Face に接続できません: {0}": "无法连接 Hugging Face:{0}",
|
| 316 |
"IBM の 8B。思考とツール呼び出し・コーディング向け": "IBM 的 8B,适合思考、工具调用和编程",
|
|
@@ -433,6 +441,7 @@
|
|
| 433 |
"メモリ目安": "内存估计",
|
| 434 |
"メモリ節約モード": "省内存模式",
|
| 435 |
"モデル": "模型",
|
|
|
|
| 436 |
"モデルは読み込まれていません": "未加载模型",
|
| 437 |
"モデルをロード": "加载模型",
|
| 438 |
"モデルを削除": "删除模型",
|
|
@@ -554,9 +563,11 @@
|
|
| 554 |
"次の文章を、元の表現をなるべく使って2文に要約してください。": "请尽量使用原文的表达,把下面的文字概括成两句话。",
|
| 555 |
"止まった理由: {0}": "停止原因:{0}",
|
| 556 |
"温度": "温度",
|
|
|
|
| 557 |
"準備中…": "准备中…",
|
| 558 |
"無効": "关闭",
|
| 559 |
"状態": "状态",
|
|
|
|
| 560 |
"生成速度": "生成速度",
|
| 561 |
"画像": "图像",
|
| 562 |
"画像も読めます": "也能读图",
|
|
@@ -568,6 +579,7 @@
|
|
| 568 |
"終了(サーバーも停止)": "退出(同时停止服务器)",
|
| 569 |
"結果": "结果",
|
| 570 |
"繰り返し抑制": "重复惩罚",
|
|
|
|
| 571 |
"自分で置いたモデル・{0}": "自行放置的模型・{0}",
|
| 572 |
"要約や書き直しなど、元の文章をなぞる回答が速くなります。": "让摘要、改写等沿用原文的回答更快。",
|
| 573 |
"言語": "语言",
|
|
@@ -575,6 +587,7 @@
|
|
| 575 |
"設定は保存しました。サーバーを新しい設定で今すぐ再起動しますか?(キャンセルしても、次にモデルを読み込むときから反映されます)": "设置已保存。现在用新设置重启服务器?(取消后,下次加载模型时生效)",
|
| 576 |
"詳細": "高级",
|
| 577 |
"読み込み中…": "加载中…",
|
|
|
|
| 578 |
"起動時と 1 日ごとに更新を確認する": "启动时及每天检查更新",
|
| 579 |
"起動時に前回ロードしたモデルを自動でロードする": "启动时自动加载上次的模型",
|
| 580 |
"追加…": "添加…",
|
|
@@ -599,6 +612,7 @@
|
|
| 599 |
"(再利用 {0})": "(复用 {0})",
|
| 600 |
"(無題)": "(无标题)",
|
| 601 |
"(画像)": "(图片)",
|
|
|
|
| 602 |
"+ 新しい会話": "+ 新对话"
|
| 603 |
}
|
| 604 |
}
|
|
|
|
| 10 |
"35B MoE を半分に刈り込み": "The 35B MoE pruned by half",
|
| 11 |
"64 トークン処理": "64-token blocks",
|
| 12 |
"API で思考の指定がないリクエストも考えてから答える": "Think before answering API requests that do not say",
|
| 13 |
+
"API の既定の生成設定": "API default sampling",
|
| 14 |
"API キー(任意)": "API key (optional)",
|
| 15 |
"Hugging Face に接続できません: {0}": "Cannot reach Hugging Face: {0}",
|
| 16 |
"IBM の 8B。思考とツール呼び出し・コーディング向け": "IBM's 8B, for thinking, tool calls and coding",
|
|
|
|
| 133 |
"メモリ目安": "Memory (est.)",
|
| 134 |
"メモリ節約モード": "Memory-saving mode",
|
| 135 |
"モデル": "Models",
|
| 136 |
+
"モデルの推奨値(チャット画面と同じ)": "The model's recommended values (as in the chat)",
|
| 137 |
"モデルは読み込まれていません": "No model loaded",
|
| 138 |
"モデルをロード": "Load model",
|
| 139 |
"モデルを削除": "Delete model",
|
|
|
|
| 255 |
"次の文章を、元の表現をなるべく使って2文に要約してください。": "Summarize the following text in two sentences, reusing its wording as much as possible.",
|
| 256 |
"止まった理由: {0}": "Why it stopped: {0}",
|
| 257 |
"温度": "Temperature",
|
| 258 |
+
"温度などを送らないアプリ(OpenCode など)のリクエストに使います。アプリが送った値はそのまま使います。": "For requests from apps that send no temperature etc. (OpenCode, ...). Values an app sends are always used.",
|
| 259 |
"準備中…": "Preparing…",
|
| 260 |
"無効": "Off",
|
| 261 |
"状態": "Status",
|
| 262 |
+
"生成設定の値が不正です": "Invalid sampling values",
|
| 263 |
"生成速度": "Decode speed",
|
| 264 |
"画像": "Image",
|
| 265 |
"画像も読めます": "Reads images too",
|
|
|
|
| 271 |
"終了(サーバーも停止)": "Quit (stops the server too)",
|
| 272 |
"結果": "Result",
|
| 273 |
"繰り返し抑制": "Repetition penalty",
|
| 274 |
+
"自分で指定": "Custom",
|
| 275 |
"自分で置いたモデル・{0}": "Your own model · {0}",
|
| 276 |
"要約や書き直しなど、元の文章をなぞる回答が速くなります。": "Speeds up answers that reuse the prompt's text, such as summaries and rewrites.",
|
| 277 |
"言語": "Language",
|
|
|
|
| 279 |
"設定は保存しました。サーバーを新しい設定で今すぐ再起動しますか?(キャンセルしても、次にモデルを読み込むときから反映されます)": "Settings saved. Restart the server with the new settings now? (Cancel keeps them for the next model load.)",
|
| 280 |
"詳細": "Advanced",
|
| 281 |
"読み込み中…": "Loading…",
|
| 282 |
+
"貪欲(温度 0。毎回同じ答え)": "Greedy (temperature 0, the same answer every time)",
|
| 283 |
"起動時と 1 日ごとに更新を確認する": "Check for updates at startup and daily",
|
| 284 |
"起動時に前回ロードしたモデルを自動でロードする": "Load the last model automatically at startup",
|
| 285 |
"追加…": "Add…",
|
|
|
|
| 304 |
"(再利用 {0})": " (reused {0})",
|
| 305 |
"(無題)": "(untitled)",
|
| 306 |
"(画像)": "(image)",
|
| 307 |
+
"(設定の値)": "(the values from the settings)",
|
| 308 |
"+ 新しい会話": "+ New conversation"
|
| 309 |
},
|
| 310 |
"zh": {
|
|
|
|
| 318 |
"35B MoE を半分に刈り込み": "35B MoE 裁剪一半",
|
| 319 |
"64 トークン処理": "64 token 分块",
|
| 320 |
"API で思考の指定がないリクエストも考えてから答える": "API 请求未指定思考时也先思考再回答",
|
| 321 |
+
"API の既定の生成設定": "API 默认生成设置",
|
| 322 |
"API キー(任意)": "API 密钥(可选)",
|
| 323 |
"Hugging Face に接続できません: {0}": "无法连接 Hugging Face:{0}",
|
| 324 |
"IBM の 8B。思考とツール呼び出し・コーディング向け": "IBM 的 8B,适合思考、工具调用和编程",
|
|
|
|
| 441 |
"メモリ目安": "内存估计",
|
| 442 |
"メモリ節約モード": "省内存模式",
|
| 443 |
"モデル": "模型",
|
| 444 |
+
"モデルの推奨値(チャット画面と同じ)": "模型的推荐值(与聊天页面相同)",
|
| 445 |
"モデルは読み込まれていません": "未加载模型",
|
| 446 |
"モデルをロード": "加载模型",
|
| 447 |
"モデルを削除": "删除模型",
|
|
|
|
| 563 |
"次の文章を、元の表現をなるべく使って2文に要約してください。": "请尽量使用原文的表达,把下面的文字概括成两句话。",
|
| 564 |
"止まった理由: {0}": "停止原因:{0}",
|
| 565 |
"温度": "温度",
|
| 566 |
+
"温度などを送らないアプリ(OpenCode など)のリクエストに使います。アプリが送った値はそのまま使います。": "用于不发送温度等参数的应用(如 OpenCode)的请求。应用发送的值始终优先。",
|
| 567 |
"準備中…": "准备中…",
|
| 568 |
"無効": "关闭",
|
| 569 |
"状態": "状态",
|
| 570 |
+
"生成設定の値が不正です": "生成设置的值无效",
|
| 571 |
"生成速度": "生成速度",
|
| 572 |
"画像": "图像",
|
| 573 |
"画像も読めます": "也能读图",
|
|
|
|
| 579 |
"終了(サーバーも停止)": "退出(同时停止服务器)",
|
| 580 |
"結果": "结果",
|
| 581 |
"繰り返し抑制": "重复惩罚",
|
| 582 |
+
"自分で指定": "自定义",
|
| 583 |
"自分で置いたモデル・{0}": "自行放置的模型・{0}",
|
| 584 |
"要約や書き直しなど、元の文章をなぞる回答が速くなります。": "让摘要、改写等沿用原文的回答更快。",
|
| 585 |
"言語": "语言",
|
|
|
|
| 587 |
"設定は保存しました。サーバーを新しい設定で今すぐ再起動しますか?(キャンセルしても、次にモデルを読み込むときから反映されます)": "设置已保存。现在用新设置重启服务器?(取消后,下次加载模型时生效)",
|
| 588 |
"詳細": "高级",
|
| 589 |
"読み込み中…": "加载中…",
|
| 590 |
+
"貪欲(温度 0。毎回同じ答え)": "贪婪(温度 0,每次答案相同)",
|
| 591 |
"起動時と 1 日ごとに更新を確認する": "启动时及每天检查更新",
|
| 592 |
"起動時に前回ロードしたモデルを自動でロードする": "启动时自动加载上次的模型",
|
| 593 |
"追加…": "添加…",
|
|
|
|
| 612 |
"(再利用 {0})": "(复用 {0})",
|
| 613 |
"(無題)": "(无标题)",
|
| 614 |
"(画像)": "(图片)",
|
| 615 |
+
"(設定の値)": "(设置中的值)",
|
| 616 |
"+ 新しい会話": "+ 新对话"
|
| 617 |
}
|
| 618 |
}
|
onw/manager.py
CHANGED
|
@@ -373,11 +373,21 @@ class Manager:
|
|
| 373 |
"update_check", "lang", "npuw_moe", "npuw_async", "cache_size", "mem_saver", "mem_saver_strict", "think_default"):
|
| 374 |
if k in new:
|
| 375 |
cfg[k] = new[k]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 376 |
if ctx != cfg["context"]:
|
| 377 |
cfg["context_chosen"] = True # (the old 1024 default moves up; a choice stays)
|
| 378 |
cfg["port"], cfg["context"] = port, ctx
|
| 379 |
server_keys = ("lan", "api_key", "device", "pld", "big_blocks", "npuw", "expert_gb", "port", "context",
|
| 380 |
-
"npuw_moe", "npuw_async", "cache_size", "mem_saver", "mem_saver_strict", "think_default"
|
|
|
|
| 381 |
app.save_config(cfg)
|
| 382 |
i18n.current(cfg) # messages switch language right away
|
| 383 |
try:
|
|
|
|
| 373 |
"update_check", "lang", "npuw_moe", "npuw_async", "cache_size", "mem_saver", "mem_saver_strict", "think_default"):
|
| 374 |
if k in new:
|
| 375 |
cfg[k] = new[k]
|
| 376 |
+
if new.get("api_sampling") in ("greedy", "recommended", "custom"):
|
| 377 |
+
cfg["api_sampling"] = new["api_sampling"]
|
| 378 |
+
try:
|
| 379 |
+
for k, cast, lo, hi in (("api_temperature", float, 0, 2), ("api_top_p", float, 0.01, 1), ("api_top_k", int, 0, 1000),
|
| 380 |
+
("api_presence", float, 0, 2)):
|
| 381 |
+
if k in new:
|
| 382 |
+
cfg[k] = min(max(cast(float(new[k])), lo), hi)
|
| 383 |
+
except (TypeError, ValueError):
|
| 384 |
+
return {"error": T("生成設定の値が不正です")}
|
| 385 |
if ctx != cfg["context"]:
|
| 386 |
cfg["context_chosen"] = True # (the old 1024 default moves up; a choice stays)
|
| 387 |
cfg["port"], cfg["context"] = port, ctx
|
| 388 |
server_keys = ("lan", "api_key", "device", "pld", "big_blocks", "npuw", "expert_gb", "port", "context",
|
| 389 |
+
"npuw_moe", "npuw_async", "cache_size", "mem_saver", "mem_saver_strict", "think_default",
|
| 390 |
+
"api_sampling", "api_temperature", "api_top_p", "api_top_k", "api_presence")
|
| 391 |
app.save_config(cfg)
|
| 392 |
i18n.current(cfg) # messages switch language right away
|
| 393 |
try:
|
onw/server.py
CHANGED
|
@@ -40,6 +40,7 @@ info = {}
|
|
| 40 |
lock = threading.Lock() # one generation at a time on the NPU
|
| 41 |
WEB = os.path.join(os.path.dirname(os.path.abspath(__file__)), "web")
|
| 42 |
API_KEY = None # --api-key: required as a Bearer token on /v1
|
|
|
|
| 43 |
|
| 44 |
|
| 45 |
def oai_error(status, message, type_="invalid_request_error", code=None):
|
|
@@ -293,10 +294,15 @@ def gen_args(body):
|
|
| 293 |
elif isinstance(choice, dict) and tools: # a named function: offer just that one
|
| 294 |
name = (choice.get("function") or {}).get("name")
|
| 295 |
tools = [t for t in tools if (t.get("function") or {}).get("name") == name] or tools
|
| 296 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 297 |
stop=[stop] if isinstance(stop, str) else list(stop), seed=body.get("seed"), think=think,
|
| 298 |
-
top_k=_num(body, "top_k", 0, int), repetition_penalty=_num(body, "repetition_penalty", 1.0),
|
| 299 |
-
presence_penalty=_num(body, "presence_penalty", 0.0),
|
| 300 |
frequency_penalty=_num(body, "frequency_penalty", 0.0), tools=tools)
|
| 301 |
|
| 302 |
|
|
@@ -515,7 +521,7 @@ def recommended_sampling(arch, engine_dir=None):
|
|
| 515 |
|
| 516 |
|
| 517 |
def main(argv=None):
|
| 518 |
-
global pipe, MODEL_ID, API_KEY
|
| 519 |
ap = argparse.ArgumentParser(prog="onw serve", description="chat UI + OpenAI-compatible API on the Intel NPU")
|
| 520 |
ap.add_argument("model", help="onw model folder, or a Hugging Face repo id (downloaded into ./models)")
|
| 521 |
ap.add_argument("--host", default="127.0.0.1")
|
|
@@ -554,6 +560,18 @@ def main(argv=None):
|
|
| 554 |
# greedy Gemma on the NPU can fall into repeating one word (fp16 on the NPU tips a near tie; the same happens with
|
| 555 |
# any onw version): the pages suggest a repetition penalty, the API default stays 1.0 (OpenAI behaviour)
|
| 556 |
info.update(arch=arch, rep_hint=1.2 if arch.startswith("gemma") else None, sampling=recommended_sampling(arch, a.engine))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 557 |
if a.open:
|
| 558 |
import webbrowser
|
| 559 |
threading.Timer(1.5, webbrowser.open, [f"http://{'localhost' if a.host in ('0.0.0.0', '127.0.0.1') else a.host}:{a.port}/chat"]).start()
|
|
|
|
| 40 |
lock = threading.Lock() # one generation at a time on the NPU
|
| 41 |
WEB = os.path.join(os.path.dirname(os.path.abspath(__file__)), "web")
|
| 42 |
API_KEY = None # --api-key: required as a Bearer token on /v1
|
| 43 |
+
API_SAMPLING = None # sampling for requests that send none (ONW_API_SAMPLING: "recommended" or a JSON of values)
|
| 44 |
|
| 45 |
|
| 46 |
def oai_error(status, message, type_="invalid_request_error", code=None):
|
|
|
|
| 294 |
elif isinstance(choice, dict) and tools: # a named function: offer just that one
|
| 295 |
name = (choice.get("function") or {}).get("name")
|
| 296 |
tools = [t for t in tools if (t.get("function") or {}).get("name") == name] or tools
|
| 297 |
+
# what the request leaves out: greedy, or the settings' API defaults (API_SAMPLING; thinking has its own set)
|
| 298 |
+
dflt = dict(API_SAMPLING or {})
|
| 299 |
+
if think and isinstance(dflt.get("think"), dict):
|
| 300 |
+
dflt.update(dflt["think"])
|
| 301 |
+
return dict(max_new_tokens=mx, temperature=_num(body, "temperature", dflt.get("temperature", 0.0)),
|
| 302 |
+
top_p=_num(body, "top_p", dflt.get("top_p", 1.0)),
|
| 303 |
stop=[stop] if isinstance(stop, str) else list(stop), seed=body.get("seed"), think=think,
|
| 304 |
+
top_k=_num(body, "top_k", dflt.get("top_k", 0), int), repetition_penalty=_num(body, "repetition_penalty", 1.0),
|
| 305 |
+
presence_penalty=_num(body, "presence_penalty", dflt.get("presence_penalty", 0.0)),
|
| 306 |
frequency_penalty=_num(body, "frequency_penalty", 0.0), tools=tools)
|
| 307 |
|
| 308 |
|
|
|
|
| 521 |
|
| 522 |
|
| 523 |
def main(argv=None):
|
| 524 |
+
global pipe, MODEL_ID, API_KEY, API_SAMPLING
|
| 525 |
ap = argparse.ArgumentParser(prog="onw serve", description="chat UI + OpenAI-compatible API on the Intel NPU")
|
| 526 |
ap.add_argument("model", help="onw model folder, or a Hugging Face repo id (downloaded into ./models)")
|
| 527 |
ap.add_argument("--host", default="127.0.0.1")
|
|
|
|
| 560 |
# greedy Gemma on the NPU can fall into repeating one word (fp16 on the NPU tips a near tie; the same happens with
|
| 561 |
# any onw version): the pages suggest a repetition penalty, the API default stays 1.0 (OpenAI behaviour)
|
| 562 |
info.update(arch=arch, rep_hint=1.2 if arch.startswith("gemma") else None, sampling=recommended_sampling(arch, a.engine))
|
| 563 |
+
want = os.environ.get("ONW_API_SAMPLING")
|
| 564 |
+
if want == "recommended":
|
| 565 |
+
API_SAMPLING = {k: v for k, v in (info["sampling"] or {}).items() if k != "source"} or None
|
| 566 |
+
elif want:
|
| 567 |
+
try:
|
| 568 |
+
API_SAMPLING = json.loads(want)
|
| 569 |
+
except ValueError:
|
| 570 |
+
API_SAMPLING = None
|
| 571 |
+
info.update(api_sampling=API_SAMPLING, api_sampling_mode="recommended" if want == "recommended" else
|
| 572 |
+
"custom" if API_SAMPLING else "greedy")
|
| 573 |
+
if API_SAMPLING:
|
| 574 |
+
print(f"[api] requests without sampling values use {API_SAMPLING}", flush=True)
|
| 575 |
if a.open:
|
| 576 |
import webbrowser
|
| 577 |
threading.Timer(1.5, webbrowser.open, [f"http://{'localhost' if a.host in ('0.0.0.0', '127.0.0.1') else a.host}:{a.port}/chat"]).start()
|
onw/web/index.html
CHANGED
|
@@ -195,7 +195,10 @@ fetch("/api/info").then(r => r.json()).then(i => {
|
|
| 195 |
if (i.always_thinks && $("maxtok").value === "512") $("maxtok").value = "2048";
|
| 196 |
|
| 197 |
if (i.context) $("note").textContent = T("文脈は約{0}トークン", i.context);
|
| 198 |
-
if (i.
|
|
|
|
|
|
|
|
|
|
| 199 |
SAMPLING = i.sampling; setSampling(SAMPLING);
|
| 200 |
$("samphint").textContent = i.sampling.source === "onw" ? T("(onw の推奨値)") : T("(モデルの推奨値)");
|
| 201 |
$("samphint").style.display = "";
|
|
|
|
| 195 |
if (i.always_thinks && $("maxtok").value === "512") $("maxtok").value = "2048";
|
| 196 |
|
| 197 |
if (i.context) $("note").textContent = T("文脈は約{0}トークン", i.context);
|
| 198 |
+
if (i.api_sampling_mode === "custom" && i.api_sampling) { // the settings' own API values: the chat starts there too
|
| 199 |
+
SAMPLING = i.api_sampling; setSampling(SAMPLING);
|
| 200 |
+
$("samphint").textContent = T("(設定の値)"); $("samphint").style.display = "";
|
| 201 |
+
} else if (i.sampling) { // the model's recommended sampling as the starting values
|
| 202 |
SAMPLING = i.sampling; setSampling(SAMPLING);
|
| 203 |
$("samphint").textContent = i.sampling.source === "onw" ? T("(onw の推奨値)") : T("(モデルの推奨値)");
|
| 204 |
$("samphint").style.display = "";
|
onw/web/manage.html
CHANGED
|
@@ -217,6 +217,13 @@
|
|
| 217 |
<span class="desc">会話で使える最大の長さ。KV キャッシュは実際に使った分だけメモリを使います(1K トークンあたり 8〜80 MB)。変えても再コンパイルはありません。</span></div>
|
| 218 |
<label class="swrow"><span class="switch"><input type="checkbox" id="f-lan"><i></i></span><span>LAN からの接続を許可する<span class="desc">他の PC から API を使えるようにします。API キーの設定をおすすめします。</span></span></label>
|
| 219 |
<label class="swrow"><span class="switch"><input type="checkbox" id="f-think_default"><i></i></span><span>API で思考の指定がないリクエストも考えてから答える<span class="desc">enable_thinking を送らないエージェントのアプリ向け。回答は遅くなります。</span></span></label>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 220 |
</div>
|
| 221 |
|
| 222 |
<div class="card set sub" data-sub="speed">
|
|
@@ -391,6 +398,9 @@
|
|
| 391 |
$("f-device").value = c.device; $("f-big_blocks").value = c.big_blocks || "auto"; $("f-npuw").value = c.npuw || "auto"; $("f-expert_gb").value = String(c.expert_gb || "auto"); $("f-lang").value = c.lang || "auto";
|
| 392 |
for (const k of ["pld", "autostart_server", "login_start", "lan", "update_check"]) $("f-" + k).checked = c[k] !== false && !!(c[k] ?? true);
|
| 393 |
for (const k of ["npuw_moe", "npuw_async", "cache_size", "mem_saver", "mem_saver_strict", "think_default"]) $("f-" + k).checked = !!c[k];
|
|
|
|
|
|
|
|
|
|
| 394 |
strictState();
|
| 395 |
const sm = s.saver_models || [];
|
| 396 |
$("row-mem_saver").style.display = sm.length || c.mem_saver ? "" : "none";
|
|
@@ -398,6 +408,8 @@
|
|
| 398 |
$("saver-models").textContent = sm.length ? T("この PC で効くモデル:{0}", sm.join(T("、"))) : T("この PC には効くモデルがありません");
|
| 399 |
}
|
| 400 |
}
|
|
|
|
|
|
|
| 401 |
function strictState() { // the strict option only under the memory-saving mode
|
| 402 |
const on = $("f-mem_saver").checked;
|
| 403 |
$("f-mem_saver_strict").disabled = !on;
|
|
@@ -448,7 +460,9 @@
|
|
| 448 |
}
|
| 449 |
async function saveSettings() {
|
| 450 |
const body = {port: $("f-port").value, context: $("f-context").value, api_key: $("f-api_key").value.trim(), device: $("f-device").value,
|
| 451 |
-
big_blocks: $("f-big_blocks").value, npuw: $("f-npuw").value, expert_gb: $("f-expert_gb").value, lang: $("f-lang").value
|
|
|
|
|
|
|
| 452 |
for (const k of ["pld", "autostart_server", "login_start", "lan", "update_check", "npuw_moe", "npuw_async", "cache_size", "mem_saver", "mem_saver_strict", "think_default"]) body[k] = $("f-" + k).checked;
|
| 453 |
if (!body.mem_saver) body.mem_saver_strict = false;
|
| 454 |
const oldLang = S.config.lang || "auto";
|
|
|
|
| 217 |
<span class="desc">会話で使える最大の長さ。KV キャッシュは実際に使った分だけメモリを使います(1K トークンあたり 8〜80 MB)。変えても再コンパイルはありません。</span></div>
|
| 218 |
<label class="swrow"><span class="switch"><input type="checkbox" id="f-lan"><i></i></span><span>LAN からの接続を許可する<span class="desc">他の PC から API を使えるようにします。API キーの設定をおすすめします。</span></span></label>
|
| 219 |
<label class="swrow"><span class="switch"><input type="checkbox" id="f-think_default"><i></i></span><span>API で思考の指定がないリクエストも考えてから答える<span class="desc">enable_thinking を送らないエージェントのアプリ向け。回答は遅くなります。</span></span></label>
|
| 220 |
+
<div class="opt"><span class="k">API の既定の生成設定</span><select id="f-api_sampling" style="width:260px"><option value="greedy">貪欲(温度 0。毎回同じ答え)</option><option value="recommended">モデルの推奨値(チャット画面と同じ)</option><option value="custom">自分で指定</option></select>
|
| 221 |
+
<span class="desc">温度などを送らないアプリ(OpenCode など)のリクエストに使います。アプリが送った値はそのまま使います。</span></div>
|
| 222 |
+
<div class="opt" id="row-api_custom"><span class="k"></span>
|
| 223 |
+
<label class="small">温度 <input type="number" id="f-api_temperature" min="0" max="2" step="0.1" style="width:64px"></label>
|
| 224 |
+
<label class="small">Top P <input type="number" id="f-api_top_p" min="0.05" max="1" step="0.05" style="width:64px"></label>
|
| 225 |
+
<label class="small">Top K <input type="number" id="f-api_top_k" min="0" max="1000" step="1" style="width:64px"></label>
|
| 226 |
+
<label class="small">出現ペナルティ <input type="number" id="f-api_presence" min="0" max="2" step="0.1" style="width:64px"></label></div>
|
| 227 |
</div>
|
| 228 |
|
| 229 |
<div class="card set sub" data-sub="speed">
|
|
|
|
| 398 |
$("f-device").value = c.device; $("f-big_blocks").value = c.big_blocks || "auto"; $("f-npuw").value = c.npuw || "auto"; $("f-expert_gb").value = String(c.expert_gb || "auto"); $("f-lang").value = c.lang || "auto";
|
| 399 |
for (const k of ["pld", "autostart_server", "login_start", "lan", "update_check"]) $("f-" + k).checked = c[k] !== false && !!(c[k] ?? true);
|
| 400 |
for (const k of ["npuw_moe", "npuw_async", "cache_size", "mem_saver", "mem_saver_strict", "think_default"]) $("f-" + k).checked = !!c[k];
|
| 401 |
+
$("f-api_sampling").value = c.api_sampling || "greedy";
|
| 402 |
+
for (const k of ["api_temperature", "api_top_p", "api_top_k", "api_presence"]) $("f-" + k).value = c[k] ?? "";
|
| 403 |
+
apiCustomState();
|
| 404 |
strictState();
|
| 405 |
const sm = s.saver_models || [];
|
| 406 |
$("row-mem_saver").style.display = sm.length || c.mem_saver ? "" : "none";
|
|
|
|
| 408 |
$("saver-models").textContent = sm.length ? T("この PC で効くモデル:{0}", sm.join(T("、"))) : T("この PC には効くモデルがありません");
|
| 409 |
}
|
| 410 |
}
|
| 411 |
+
function apiCustomState() { $("row-api_custom").style.display = $("f-api_sampling").value === "custom" ? "" : "none"; }
|
| 412 |
+
document.addEventListener("change", e => { if (e.target && e.target.id === "f-api_sampling") apiCustomState(); });
|
| 413 |
function strictState() { // the strict option only under the memory-saving mode
|
| 414 |
const on = $("f-mem_saver").checked;
|
| 415 |
$("f-mem_saver_strict").disabled = !on;
|
|
|
|
| 460 |
}
|
| 461 |
async function saveSettings() {
|
| 462 |
const body = {port: $("f-port").value, context: $("f-context").value, api_key: $("f-api_key").value.trim(), device: $("f-device").value,
|
| 463 |
+
big_blocks: $("f-big_blocks").value, npuw: $("f-npuw").value, expert_gb: $("f-expert_gb").value, lang: $("f-lang").value,
|
| 464 |
+
api_sampling: $("f-api_sampling").value, api_temperature: $("f-api_temperature").value, api_top_p: $("f-api_top_p").value,
|
| 465 |
+
api_top_k: $("f-api_top_k").value, api_presence: $("f-api_presence").value};
|
| 466 |
for (const k of ["pld", "autostart_server", "login_start", "lan", "update_check", "npuw_moe", "npuw_async", "cache_size", "mem_saver", "mem_saver_strict", "think_default"]) body[k] = $("f-" + k).checked;
|
| 467 |
if (!body.mem_saver) body.mem_saver_strict = false;
|
| 468 |
const oldLang = S.config.lang || "auto";
|
pyproject.toml
CHANGED
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
| 4 |
|
| 5 |
[project]
|
| 6 |
name = "onw"
|
| 7 |
-
version = "1.2.
|
| 8 |
description = "Ore no NPU ga konna ni ugoku wake nai - LLMs entirely on the Intel NPU"
|
| 9 |
readme = "README.md"
|
| 10 |
license = {text = "Apache-2.0"}
|
|
|
|
| 4 |
|
| 5 |
[project]
|
| 6 |
name = "onw"
|
| 7 |
+
version = "1.2.2"
|
| 8 |
description = "Ore no NPU ga konna ni ugoku wake nai - LLMs entirely on the Intel NPU"
|
| 9 |
readme = "README.md"
|
| 10 |
license = {text = "Apache-2.0"}
|