@modular-prompt/driver 0.13.5 → 0.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +117 -4
- package/dist/driver-registry/ai-service.d.ts +23 -1
- package/dist/driver-registry/ai-service.d.ts.map +1 -1
- package/dist/driver-registry/ai-service.js +44 -10
- package/dist/driver-registry/ai-service.js.map +1 -1
- package/dist/driver-registry/config-based-factory.d.ts.map +1 -1
- package/dist/driver-registry/config-based-factory.js +16 -0
- package/dist/driver-registry/config-based-factory.js.map +1 -1
- package/dist/driver-registry/factory-helper.d.ts +2 -0
- package/dist/driver-registry/factory-helper.d.ts.map +1 -1
- package/dist/driver-registry/factory-helper.js +21 -3
- package/dist/driver-registry/factory-helper.js.map +1 -1
- package/dist/driver-registry/index.d.ts +2 -2
- package/dist/driver-registry/index.d.ts.map +1 -1
- package/dist/driver-registry/index.js +1 -1
- package/dist/driver-registry/index.js.map +1 -1
- package/dist/driver-registry/registry.d.ts.map +1 -1
- package/dist/driver-registry/registry.js +3 -1
- package/dist/driver-registry/registry.js.map +1 -1
- package/dist/driver-registry/types.d.ts +8 -2
- package/dist/driver-registry/types.d.ts.map +1 -1
- package/dist/index.d.ts +11 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +11 -1
- package/dist/index.js.map +1 -1
- package/dist/local-inference/adapters.d.ts +66 -0
- package/dist/local-inference/adapters.d.ts.map +1 -0
- package/dist/local-inference/adapters.js +2 -0
- package/dist/local-inference/adapters.js.map +1 -0
- package/dist/local-inference/driver.d.ts +51 -0
- package/dist/local-inference/driver.d.ts.map +1 -0
- package/dist/local-inference/driver.js +309 -0
- package/dist/local-inference/driver.js.map +1 -0
- package/dist/local-inference/index.d.ts +22 -0
- package/dist/local-inference/index.d.ts.map +1 -0
- package/dist/local-inference/index.js +17 -0
- package/dist/local-inference/index.js.map +1 -0
- package/dist/local-inference/process-client.d.ts +50 -0
- package/dist/local-inference/process-client.d.ts.map +1 -0
- package/dist/local-inference/process-client.js +92 -0
- package/dist/local-inference/process-client.js.map +1 -0
- package/dist/local-inference/process-communication.d.ts +41 -0
- package/dist/local-inference/process-communication.d.ts.map +1 -0
- package/dist/{mlx-ml/process → local-inference}/process-communication.js +40 -47
- package/dist/local-inference/process-communication.js.map +1 -0
- package/dist/local-inference/process-port.d.ts +12 -0
- package/dist/local-inference/process-port.d.ts.map +1 -0
- package/dist/local-inference/process-port.js +2 -0
- package/dist/local-inference/process-port.js.map +1 -0
- package/dist/local-inference/prompt-utils.d.ts +6 -0
- package/dist/local-inference/prompt-utils.d.ts.map +1 -0
- package/dist/local-inference/prompt-utils.js +17 -0
- package/dist/local-inference/prompt-utils.js.map +1 -0
- package/dist/local-inference/protocol.d.ts +192 -0
- package/dist/local-inference/protocol.d.ts.map +1 -0
- package/dist/local-inference/protocol.js +2 -0
- package/dist/local-inference/protocol.js.map +1 -0
- package/dist/local-inference/queue-types.d.ts +54 -0
- package/dist/local-inference/queue-types.d.ts.map +1 -0
- package/dist/local-inference/queue-types.js +2 -0
- package/dist/local-inference/queue-types.js.map +1 -0
- package/dist/local-inference/request-queue.d.ts +36 -0
- package/dist/local-inference/request-queue.d.ts.map +1 -0
- package/dist/{mlx-ml/process/queue.js → local-inference/request-queue.js} +89 -56
- package/dist/local-inference/request-queue.js.map +1 -0
- package/dist/local-inference/stream-utils.d.ts +19 -0
- package/dist/local-inference/stream-utils.d.ts.map +1 -0
- package/dist/local-inference/stream-utils.js +76 -0
- package/dist/local-inference/stream-utils.js.map +1 -0
- package/dist/mlx-ml/mlx-cache-support.d.ts +23 -0
- package/dist/mlx-ml/mlx-cache-support.d.ts.map +1 -0
- package/dist/mlx-ml/mlx-cache-support.js +45 -0
- package/dist/mlx-ml/mlx-cache-support.js.map +1 -0
- package/dist/mlx-ml/mlx-driver.d.ts +20 -59
- package/dist/mlx-ml/mlx-driver.d.ts.map +1 -1
- package/dist/mlx-ml/mlx-driver.js +86 -415
- package/dist/mlx-ml/mlx-driver.js.map +1 -1
- package/dist/mlx-ml/mlx-local-inference-adapters.d.ts +3 -0
- package/dist/mlx-ml/mlx-local-inference-adapters.d.ts.map +1 -0
- package/dist/mlx-ml/mlx-local-inference-adapters.js +19 -0
- package/dist/mlx-ml/mlx-local-inference-adapters.js.map +1 -0
- package/dist/mlx-ml/mlx-options.d.ts +19 -0
- package/dist/mlx-ml/mlx-options.d.ts.map +1 -0
- package/dist/mlx-ml/mlx-options.js +30 -0
- package/dist/mlx-ml/mlx-options.js.map +1 -0
- package/dist/mlx-ml/process/index.d.ts +11 -8
- package/dist/mlx-ml/process/index.d.ts.map +1 -1
- package/dist/mlx-ml/process/index.js +75 -52
- package/dist/mlx-ml/process/index.js.map +1 -1
- package/dist/mlx-ml/process/model-specific.d.ts +2 -1
- package/dist/mlx-ml/process/model-specific.d.ts.map +1 -1
- package/dist/mlx-ml/process/model-specific.js.map +1 -1
- package/dist/mlx-ml/process/prompt-builder.d.ts +11 -0
- package/dist/mlx-ml/process/prompt-builder.d.ts.map +1 -0
- package/dist/mlx-ml/process/prompt-builder.js +51 -0
- package/dist/mlx-ml/process/prompt-builder.js.map +1 -0
- package/dist/mlx-ml/process/types.d.ts +15 -183
- package/dist/mlx-ml/process/types.d.ts.map +1 -1
- package/dist/mlx-ml/tool-call-parser/tool-formatter.js +2 -2
- package/dist/mlx-ml/tool-call-parser/tool-formatter.js.map +1 -1
- package/dist/mlx-ml/types.d.ts +2 -45
- package/dist/mlx-ml/types.d.ts.map +1 -1
- package/dist/models-config/index.d.ts +8 -0
- package/dist/models-config/index.d.ts.map +1 -0
- package/dist/models-config/index.js +7 -0
- package/dist/models-config/index.js.map +1 -0
- package/dist/models-config/loader.d.ts +20 -0
- package/dist/models-config/loader.d.ts.map +1 -0
- package/dist/models-config/loader.js +85 -0
- package/dist/models-config/loader.js.map +1 -0
- package/dist/models-config/paths.d.ts +7 -0
- package/dist/models-config/paths.d.ts.map +1 -0
- package/dist/models-config/paths.js +11 -0
- package/dist/models-config/paths.js.map +1 -0
- package/dist/models-config/resolve.d.ts +57 -0
- package/dist/models-config/resolve.d.ts.map +1 -0
- package/dist/models-config/resolve.js +187 -0
- package/dist/models-config/resolve.js.map +1 -0
- package/dist/models-config/types.d.ts +60 -0
- package/dist/models-config/types.d.ts.map +1 -0
- package/dist/models-config/types.js +5 -0
- package/dist/models-config/types.js.map +1 -0
- package/dist/pytorch/process/index.d.ts +35 -0
- package/dist/pytorch/process/index.d.ts.map +1 -0
- package/dist/pytorch/process/index.js +69 -0
- package/dist/pytorch/process/index.js.map +1 -0
- package/dist/pytorch/pytorch-driver.d.ts +35 -0
- package/dist/pytorch/pytorch-driver.d.ts.map +1 -0
- package/dist/pytorch/pytorch-driver.js +48 -0
- package/dist/pytorch/pytorch-driver.js.map +1 -0
- package/dist/pytorch/pytorch-local-inference-adapters.d.ts +3 -0
- package/dist/pytorch/pytorch-local-inference-adapters.d.ts.map +1 -0
- package/dist/pytorch/pytorch-local-inference-adapters.js +19 -0
- package/dist/pytorch/pytorch-local-inference-adapters.js.map +1 -0
- package/dist/pytorch/pytorch-options.d.ts +8 -0
- package/dist/pytorch/pytorch-options.d.ts.map +1 -0
- package/dist/pytorch/pytorch-options.js +21 -0
- package/dist/pytorch/pytorch-options.js.map +1 -0
- package/dist/query-logger.js +1 -1
- package/dist/query-logger.js.map +1 -1
- package/dist/query-utils.d.ts +29 -0
- package/dist/query-utils.d.ts.map +1 -0
- package/dist/query-utils.js +61 -0
- package/dist/query-utils.js.map +1 -0
- package/dist/runtime/check.d.ts +10 -0
- package/dist/runtime/check.d.ts.map +1 -0
- package/dist/runtime/check.js +24 -0
- package/dist/runtime/check.js.map +1 -0
- package/dist/runtime/index.d.ts +4 -0
- package/dist/runtime/index.d.ts.map +1 -0
- package/dist/runtime/index.js +4 -0
- package/dist/runtime/index.js.map +1 -0
- package/dist/runtime/manifest-core.d.mts +27 -0
- package/dist/runtime/manifest-core.d.mts.map +1 -0
- package/dist/runtime/manifest-core.mjs +68 -0
- package/dist/runtime/manifest-core.mjs.map +1 -0
- package/dist/runtime/manifest.d.ts +18 -0
- package/dist/runtime/manifest.d.ts.map +1 -0
- package/dist/runtime/manifest.js +9 -0
- package/dist/runtime/manifest.js.map +1 -0
- package/dist/runtime/paths-core.d.mts +17 -0
- package/dist/runtime/paths-core.d.mts.map +1 -0
- package/dist/runtime/paths-core.mjs +67 -0
- package/dist/runtime/paths-core.mjs.map +1 -0
- package/dist/runtime/paths.d.ts +12 -0
- package/dist/runtime/paths.d.ts.map +1 -0
- package/dist/runtime/paths.js +17 -0
- package/dist/runtime/paths.js.map +1 -0
- package/dist/types.d.ts +20 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +8 -5
- package/scripts/download-model.js +25 -9
- package/scripts/runtime-cli.js +315 -0
- package/skills/driver-usage/SKILL.md +56 -1
- package/src/mlx-ml/python/__main__.py +43 -4
- package/src/mlx-ml/python/handlers/__init__.py +2 -1
- package/src/mlx-ml/python/handlers/cancel.py +53 -0
- package/src/mlx-ml/python/handlers/completion.py +3 -24
- package/src/mlx-ml/python/handlers/{chat.py → generate.py} +36 -106
- package/src/mlx-ml/python/handlers/render.py +40 -0
- package/src/mlx-ml/python/pyproject.toml +3 -2
- package/src/mlx-ml/python/server.py +35 -8
- package/src/mlx-ml/python/utils/template_render.py +80 -0
- package/src/mlx-ml/python/utils/token_utils.py +2 -2
- package/src/mlx-ml/python/uv.lock +549 -454
- package/src/pytorch/python/__main__.py +19 -0
- package/src/pytorch/python/backends/__init__.py +3 -0
- package/src/pytorch/python/backends/base.py +84 -0
- package/src/pytorch/python/backends/transformers_lm.py +127 -0
- package/src/pytorch/python/handlers/__init__.py +6 -0
- package/src/pytorch/python/handlers/cancel.py +53 -0
- package/src/pytorch/python/handlers/capabilities.py +6 -0
- package/src/pytorch/python/handlers/completion.py +15 -0
- package/src/pytorch/python/handlers/format_test.py +70 -0
- package/src/pytorch/python/handlers/generate.py +68 -0
- package/src/pytorch/python/handlers/render.py +40 -0
- package/src/pytorch/python/handlers/tokenize.py +63 -0
- package/src/pytorch/python/pyproject.toml +36 -0
- package/src/pytorch/python/server.py +140 -0
- package/src/pytorch/python/utils/__init__.py +0 -0
- package/src/pytorch/python/utils/chat_template_constraints.py +164 -0
- package/src/pytorch/python/utils/prompt_builder.py +54 -0
- package/src/pytorch/python/utils/template_render.py +80 -0
- package/src/pytorch/python/utils/token_utils.py +376 -0
- package/src/pytorch/python/uv.lock +694 -0
- package/dist/mlx-ml/process/process-communication.d.ts +0 -37
- package/dist/mlx-ml/process/process-communication.d.ts.map +0 -1
- package/dist/mlx-ml/process/process-communication.js.map +0 -1
- package/dist/mlx-ml/process/queue.d.ts +0 -33
- package/dist/mlx-ml/process/queue.d.ts.map +0 -1
- package/dist/mlx-ml/process/queue.js.map +0 -1
- package/scripts/setup-mlx.js +0 -53
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
import json
|
|
4
|
+
import os
|
|
4
5
|
import re
|
|
5
6
|
import sys
|
|
6
7
|
|
|
7
8
|
from backends.base import ModelBackend
|
|
8
9
|
from mlx_lm.models.cache import trim_prompt_cache
|
|
9
|
-
from
|
|
10
|
+
from handlers.cancel import poll_cancel
|
|
10
11
|
|
|
11
12
|
|
|
12
13
|
def _read_cache_token_count(cache_path: str) -> int | None:
|
|
@@ -34,6 +35,8 @@ def _stream_to_stdout(
|
|
|
34
35
|
|
|
35
36
|
last_response = None
|
|
36
37
|
for response in backend.stream_generate(prompt, options, images, prompt_cache=prompt_cache):
|
|
38
|
+
if poll_cancel():
|
|
39
|
+
break
|
|
37
40
|
print(response.text.replace("\0", "").replace("\x1e", ""), end="", flush=True)
|
|
38
41
|
last_response = response
|
|
39
42
|
|
|
@@ -50,65 +53,42 @@ def _stream_to_stdout(
|
|
|
50
53
|
print("", end="\0", flush=True)
|
|
51
54
|
|
|
52
55
|
|
|
53
|
-
def
|
|
56
|
+
def handle_generate(
|
|
54
57
|
backend: ModelBackend,
|
|
55
|
-
|
|
56
|
-
messages: list,
|
|
57
|
-
primer: str | None = None,
|
|
58
|
+
prompt: str | list[int],
|
|
58
59
|
options: dict | None = None,
|
|
59
|
-
tools: list | None = None,
|
|
60
60
|
images: list | None = None,
|
|
61
61
|
max_image_size: int = 768,
|
|
62
|
-
|
|
62
|
+
primer: str | None = None,
|
|
63
63
|
cache_path: str | None = None,
|
|
64
64
|
cache_trim_tokens: int | None = None,
|
|
65
65
|
) -> None:
|
|
66
|
-
"""
|
|
66
|
+
"""LIP generate: 整形済み prompt のストリーム推論"""
|
|
67
67
|
if options is None:
|
|
68
68
|
options = {}
|
|
69
69
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
if backend.supports_vision():
|
|
73
|
-
add_generation_prompt = True
|
|
74
|
-
fmt_messages = list(messages)
|
|
75
|
-
if primer is not None:
|
|
76
|
-
fmt_messages.append({"role": "assistant", "content": primer})
|
|
77
|
-
add_generation_prompt = False
|
|
78
|
-
|
|
79
|
-
try:
|
|
80
|
-
prompt = tokenizer.apply_chat_template(
|
|
81
|
-
fmt_messages,
|
|
82
|
-
tools=tools,
|
|
83
|
-
add_generation_prompt=add_generation_prompt,
|
|
84
|
-
tokenize=False,
|
|
85
|
-
)
|
|
86
|
-
except TypeError:
|
|
87
|
-
prompt = tokenizer.apply_chat_template(
|
|
88
|
-
fmt_messages,
|
|
89
|
-
add_generation_prompt=add_generation_prompt,
|
|
90
|
-
tokenize=False,
|
|
91
|
-
)
|
|
92
|
-
|
|
93
|
-
if primer is not None:
|
|
94
|
-
prompt = primer.join(prompt.split(primer)[0:-1]) + primer
|
|
95
|
-
|
|
96
|
-
display_prompt = re.sub(r'(<\|image_pad\|>)+', '<|image_pad|>...', prompt)
|
|
97
|
-
sys.stderr.write(f"--- vlm prompt (images: {len(images) if images else 0}, max_size: {max_image_size})\n{display_prompt}\n")
|
|
98
|
-
|
|
99
|
-
final_options = dict(options)
|
|
70
|
+
final_options = dict(options)
|
|
71
|
+
if images:
|
|
100
72
|
final_options["max_image_size"] = max_image_size
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
73
|
+
if os.getenv('MLX_DEBUG'):
|
|
74
|
+
if isinstance(prompt, str):
|
|
75
|
+
display_prompt = re.sub(r'(<\|image_pad\|>)+', '<|image_pad|>...', prompt)
|
|
76
|
+
else:
|
|
77
|
+
display_prompt = f"<token ids: len={len(prompt)}>"
|
|
78
|
+
sys.stderr.write(
|
|
79
|
+
f"--- vlm generate (images: {len(images)}, max_size: {max_image_size})\n{display_prompt}\n"
|
|
80
|
+
)
|
|
81
|
+
elif os.getenv('MLX_DEBUG'):
|
|
82
|
+
if isinstance(prompt, list):
|
|
83
|
+
sys.stderr.write(f"--- prompt: len={len(prompt)}\n")
|
|
84
|
+
else:
|
|
85
|
+
sys.stderr.write(f"--- prompt\n{prompt}\n")
|
|
109
86
|
|
|
110
|
-
|
|
87
|
+
# VLM 経路では KV キャッシュを使わない(旧 chat ハンドラと同様)
|
|
88
|
+
prompt_cache = None
|
|
111
89
|
cache_tokens = 0
|
|
90
|
+
if cache_path and not images:
|
|
91
|
+
prompt_cache = backend.load_cache_from_file(cache_path)
|
|
112
92
|
if prompt_cache is not None:
|
|
113
93
|
if cache_trim_tokens is not None:
|
|
114
94
|
current_offset = backend.get_cache_offset(prompt_cache)
|
|
@@ -125,7 +105,6 @@ def handle_chat(
|
|
|
125
105
|
if meta_count is not None:
|
|
126
106
|
cache_tokens = meta_count
|
|
127
107
|
else:
|
|
128
|
-
# Legacy cache without meta file - skip it for safety
|
|
129
108
|
sys.stderr.write(
|
|
130
109
|
f"WARNING: Cache file exists but no .meta.json found at {cache_path}. "
|
|
131
110
|
"Ignoring cache for safety (may be from old implementation).\n"
|
|
@@ -139,67 +118,11 @@ def handle_chat(
|
|
|
139
118
|
elif cache_path:
|
|
140
119
|
sys.stderr.write(f"KV cache load FAILED: {cache_path}\n")
|
|
141
120
|
|
|
142
|
-
if not supports_chat_template(tokenizer):
|
|
143
|
-
prompt = generate_merged_prompt(messages, capabilities)
|
|
144
|
-
if prompt_cache is not None:
|
|
145
|
-
sys.stderr.write("KV cache ignored: model does not support chat template\n")
|
|
146
|
-
_stream_to_stdout(backend, prompt, options, primer=primer)
|
|
147
|
-
return
|
|
148
|
-
|
|
149
|
-
add_generation_prompt = True
|
|
150
|
-
fmt_messages = list(messages)
|
|
151
|
-
if primer is not None:
|
|
152
|
-
fmt_messages.append({"role": "assistant", "content": primer})
|
|
153
|
-
add_generation_prompt = False
|
|
154
|
-
|
|
155
|
-
extra_kwargs = {}
|
|
156
|
-
if tools is not None:
|
|
157
|
-
extra_kwargs["tools"] = tools
|
|
158
|
-
if reasoning_effort is not None:
|
|
159
|
-
extra_kwargs["reasoning_effort"] = reasoning_effort
|
|
160
|
-
|
|
161
|
-
trust_remote_code = options.get("trust_remote_code")
|
|
162
|
-
if trust_remote_code is not None:
|
|
163
|
-
extra_kwargs["trust_remote_code"] = trust_remote_code
|
|
164
|
-
|
|
165
|
-
try:
|
|
166
|
-
prompt = tokenizer.apply_chat_template(
|
|
167
|
-
fmt_messages,
|
|
168
|
-
add_generation_prompt=add_generation_prompt,
|
|
169
|
-
tokenize=False,
|
|
170
|
-
**extra_kwargs,
|
|
171
|
-
)
|
|
172
|
-
except TypeError:
|
|
173
|
-
try:
|
|
174
|
-
fallback_kwargs = {}
|
|
175
|
-
if tools is not None:
|
|
176
|
-
fallback_kwargs["tools"] = tools
|
|
177
|
-
prompt = tokenizer.apply_chat_template(
|
|
178
|
-
fmt_messages,
|
|
179
|
-
add_generation_prompt=add_generation_prompt,
|
|
180
|
-
tokenize=False,
|
|
181
|
-
**fallback_kwargs,
|
|
182
|
-
)
|
|
183
|
-
except TypeError:
|
|
184
|
-
prompt = tokenizer.apply_chat_template(
|
|
185
|
-
fmt_messages,
|
|
186
|
-
add_generation_prompt=add_generation_prompt,
|
|
187
|
-
tokenize=False,
|
|
188
|
-
)
|
|
189
|
-
|
|
190
|
-
if primer is not None:
|
|
191
|
-
prompt = primer.join(prompt.split(primer)[0:-1]) + primer
|
|
192
|
-
|
|
193
|
-
if isinstance(prompt, list):
|
|
194
|
-
sys.stderr.write(f"--- prompt: len={len(prompt)}\n")
|
|
195
|
-
else:
|
|
196
|
-
sys.stderr.write(f"--- prompt\n{prompt}\n")
|
|
197
|
-
|
|
198
|
-
final_options = dict(options)
|
|
199
121
|
final_options.pop("trust_remote_code", None)
|
|
200
122
|
|
|
201
123
|
effective_prompt = prompt
|
|
202
124
|
if prompt_cache is not None and cache_tokens > 0 and isinstance(prompt, str):
|
|
125
|
+
tokenizer = backend.get_tokenizer()
|
|
203
126
|
add_special = tokenizer.bos_token is None or not prompt.startswith(
|
|
204
127
|
tokenizer.bos_token
|
|
205
128
|
)
|
|
@@ -218,4 +141,11 @@ def handle_chat(
|
|
|
218
141
|
)
|
|
219
142
|
prompt_cache = None
|
|
220
143
|
|
|
221
|
-
_stream_to_stdout(
|
|
144
|
+
_stream_to_stdout(
|
|
145
|
+
backend,
|
|
146
|
+
effective_prompt,
|
|
147
|
+
final_options,
|
|
148
|
+
images=images,
|
|
149
|
+
primer=primer,
|
|
150
|
+
prompt_cache=prompt_cache,
|
|
151
|
+
)
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import json
|
|
4
|
+
|
|
5
|
+
from backends.base import ModelBackend
|
|
6
|
+
from utils.template_render import apply_chat_template_prompt
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def handle_render(
|
|
10
|
+
backend: ModelBackend,
|
|
11
|
+
messages: list,
|
|
12
|
+
options: dict | None = None,
|
|
13
|
+
tools: list | None = None,
|
|
14
|
+
reasoning_effort: str | None = None,
|
|
15
|
+
) -> None:
|
|
16
|
+
"""LIP render: apply_chat_template のみ(推論しない)"""
|
|
17
|
+
if options is None:
|
|
18
|
+
options = {}
|
|
19
|
+
|
|
20
|
+
result: dict = {
|
|
21
|
+
"formatted_prompt": None,
|
|
22
|
+
"error": None,
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
try:
|
|
26
|
+
trust_remote_code = options.get("trust_remote_code")
|
|
27
|
+
primer = options.get("primer")
|
|
28
|
+
prompt = apply_chat_template_prompt(
|
|
29
|
+
backend,
|
|
30
|
+
messages,
|
|
31
|
+
primer=primer,
|
|
32
|
+
tools=tools,
|
|
33
|
+
reasoning_effort=reasoning_effort,
|
|
34
|
+
trust_remote_code=trust_remote_code,
|
|
35
|
+
)
|
|
36
|
+
result["formatted_prompt"] = prompt
|
|
37
|
+
except Exception as e:
|
|
38
|
+
result["error"] = str(e)
|
|
39
|
+
|
|
40
|
+
print(json.dumps(result), end="\0", flush=True)
|
|
@@ -2,14 +2,15 @@
|
|
|
2
2
|
name = "mlx_driver"
|
|
3
3
|
version = "0.1.0"
|
|
4
4
|
description = "MLX driver for moduler-prompt"
|
|
5
|
-
requires-python = ">=3.
|
|
5
|
+
requires-python = ">=3.11,<3.14"
|
|
6
6
|
dependencies = [
|
|
7
7
|
"flex==6.14.1",
|
|
8
8
|
"hf-xet==1.2.0",
|
|
9
9
|
"jinja2==3.1.6",
|
|
10
10
|
"mlx>=0.31.2; sys_platform == 'darwin'",
|
|
11
11
|
"mlx-lm==0.31.3; sys_platform == 'darwin'",
|
|
12
|
-
"mlx-
|
|
12
|
+
"mlx-optiq>=0.4.4; sys_platform == 'darwin'",
|
|
13
|
+
"mlx-vlm==0.6.4; sys_platform == 'darwin'",
|
|
13
14
|
"tokenizers==0.22.2",
|
|
14
15
|
"torch==2.9.1",
|
|
15
16
|
"torchvision==0.24.1",
|
|
@@ -3,7 +3,8 @@ import json
|
|
|
3
3
|
import sys
|
|
4
4
|
|
|
5
5
|
from backends.base import ModelBackend
|
|
6
|
-
from handlers import handle_cache_prefill, handle_capabilities,
|
|
6
|
+
from handlers import handle_cache_prefill, handle_capabilities, handle_completion, handle_format_test, handle_generate, handle_render, handle_tokenize
|
|
7
|
+
from handlers.cancel import request_cancel, reset_cancel
|
|
7
8
|
|
|
8
9
|
|
|
9
10
|
MAX_READ_LINES = 10000
|
|
@@ -26,6 +27,15 @@ def read():
|
|
|
26
27
|
continue
|
|
27
28
|
|
|
28
29
|
|
|
30
|
+
def _is_valid_generate_prompt(prompt) -> bool:
|
|
31
|
+
"""prompt は非空文字列または非空のトークン ID リスト"""
|
|
32
|
+
if isinstance(prompt, str):
|
|
33
|
+
return bool(prompt)
|
|
34
|
+
if isinstance(prompt, list):
|
|
35
|
+
return len(prompt) > 0
|
|
36
|
+
return False
|
|
37
|
+
|
|
38
|
+
|
|
29
39
|
class Server:
|
|
30
40
|
def __init__(self, backend: ModelBackend, capabilities: dict):
|
|
31
41
|
self.backend = backend
|
|
@@ -48,6 +58,12 @@ class Server:
|
|
|
48
58
|
self._error_response("'method' field is required")
|
|
49
59
|
return
|
|
50
60
|
|
|
61
|
+
if method == 'cancel':
|
|
62
|
+
request_cancel()
|
|
63
|
+
return
|
|
64
|
+
|
|
65
|
+
reset_cancel()
|
|
66
|
+
|
|
51
67
|
try:
|
|
52
68
|
if method == 'capabilities':
|
|
53
69
|
handle_capabilities(self.capabilities)
|
|
@@ -86,21 +102,32 @@ class Server:
|
|
|
86
102
|
reasoning_effort=req.get('reasoning_effort'),
|
|
87
103
|
)
|
|
88
104
|
|
|
89
|
-
elif method == '
|
|
105
|
+
elif method == 'render':
|
|
90
106
|
messages = req.get('messages')
|
|
91
107
|
if not messages:
|
|
92
|
-
self._error_response("'messages' field is required for
|
|
108
|
+
self._error_response("'messages' field is required for render method")
|
|
93
109
|
return
|
|
94
|
-
|
|
110
|
+
handle_render(
|
|
95
111
|
self.backend,
|
|
96
|
-
self.capabilities,
|
|
97
112
|
messages,
|
|
98
|
-
primer=req.get('primer'),
|
|
99
113
|
options=req.get('options', {}),
|
|
100
114
|
tools=req.get('tools'),
|
|
101
|
-
images=req.get('images', []),
|
|
102
|
-
max_image_size=req.get('maxImageSize', 768),
|
|
103
115
|
reasoning_effort=req.get('reasoning_effort'),
|
|
116
|
+
)
|
|
117
|
+
|
|
118
|
+
elif method == 'generate':
|
|
119
|
+
prompt = req.get('prompt')
|
|
120
|
+
if not _is_valid_generate_prompt(prompt):
|
|
121
|
+
self._error_response("'prompt' field is required for generate method")
|
|
122
|
+
return
|
|
123
|
+
images = req.get('images', [])
|
|
124
|
+
handle_generate(
|
|
125
|
+
self.backend,
|
|
126
|
+
prompt,
|
|
127
|
+
options=req.get('options', {}),
|
|
128
|
+
images=images if images else None,
|
|
129
|
+
max_image_size=req.get('maxImageSize', 768),
|
|
130
|
+
primer=req.get('primer'),
|
|
104
131
|
cache_path=req.get('cache_path'),
|
|
105
132
|
cache_trim_tokens=req.get('cache_trim_tokens'),
|
|
106
133
|
)
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
"""apply_chat_template によるプロンプト整形(推論なし)"""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from utils.prompt_builder import supports_chat_template
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def apply_chat_template_prompt(
|
|
9
|
+
backend,
|
|
10
|
+
messages: list,
|
|
11
|
+
*,
|
|
12
|
+
primer: str | None = None,
|
|
13
|
+
tools: list | None = None,
|
|
14
|
+
reasoning_effort: str | None = None,
|
|
15
|
+
trust_remote_code: bool | None = None,
|
|
16
|
+
) -> str | list:
|
|
17
|
+
"""messages を chat template で整形して prompt を返す"""
|
|
18
|
+
tokenizer = backend.get_tokenizer()
|
|
19
|
+
|
|
20
|
+
if not supports_chat_template(tokenizer):
|
|
21
|
+
raise ValueError("chat_template_not_available")
|
|
22
|
+
|
|
23
|
+
add_generation_prompt = True
|
|
24
|
+
fmt_messages = list(messages)
|
|
25
|
+
if primer is not None:
|
|
26
|
+
fmt_messages.append({"role": "assistant", "content": primer})
|
|
27
|
+
add_generation_prompt = False
|
|
28
|
+
|
|
29
|
+
if backend.supports_vision():
|
|
30
|
+
try:
|
|
31
|
+
prompt = tokenizer.apply_chat_template(
|
|
32
|
+
fmt_messages,
|
|
33
|
+
tools=tools,
|
|
34
|
+
add_generation_prompt=add_generation_prompt,
|
|
35
|
+
tokenize=False,
|
|
36
|
+
)
|
|
37
|
+
except TypeError:
|
|
38
|
+
prompt = tokenizer.apply_chat_template(
|
|
39
|
+
fmt_messages,
|
|
40
|
+
add_generation_prompt=add_generation_prompt,
|
|
41
|
+
tokenize=False,
|
|
42
|
+
)
|
|
43
|
+
else:
|
|
44
|
+
extra_kwargs: dict = {}
|
|
45
|
+
if tools is not None:
|
|
46
|
+
extra_kwargs["tools"] = tools
|
|
47
|
+
if reasoning_effort is not None:
|
|
48
|
+
extra_kwargs["reasoning_effort"] = reasoning_effort
|
|
49
|
+
if trust_remote_code is not None:
|
|
50
|
+
extra_kwargs["trust_remote_code"] = trust_remote_code
|
|
51
|
+
|
|
52
|
+
try:
|
|
53
|
+
prompt = tokenizer.apply_chat_template(
|
|
54
|
+
fmt_messages,
|
|
55
|
+
add_generation_prompt=add_generation_prompt,
|
|
56
|
+
tokenize=False,
|
|
57
|
+
**extra_kwargs,
|
|
58
|
+
)
|
|
59
|
+
except TypeError:
|
|
60
|
+
try:
|
|
61
|
+
fallback_kwargs: dict = {}
|
|
62
|
+
if tools is not None:
|
|
63
|
+
fallback_kwargs["tools"] = tools
|
|
64
|
+
prompt = tokenizer.apply_chat_template(
|
|
65
|
+
fmt_messages,
|
|
66
|
+
add_generation_prompt=add_generation_prompt,
|
|
67
|
+
tokenize=False,
|
|
68
|
+
**fallback_kwargs,
|
|
69
|
+
)
|
|
70
|
+
except TypeError:
|
|
71
|
+
prompt = tokenizer.apply_chat_template(
|
|
72
|
+
fmt_messages,
|
|
73
|
+
add_generation_prompt=add_generation_prompt,
|
|
74
|
+
tokenize=False,
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
if primer is not None and isinstance(prompt, str):
|
|
78
|
+
prompt = primer.join(prompt.split(primer)[0:-1]) + primer
|
|
79
|
+
|
|
80
|
+
return prompt
|
|
@@ -342,11 +342,11 @@ def get_capabilities(tokenizer):
|
|
|
342
342
|
dict: capabilities情報
|
|
343
343
|
"""
|
|
344
344
|
# 基本メソッド
|
|
345
|
-
methods = ["capabilities", "completion", "format_test"]
|
|
345
|
+
methods = ["capabilities", "completion", "generate", "format_test"]
|
|
346
346
|
|
|
347
347
|
# apply_chat_templateがある場合はchatメソッドを追加
|
|
348
348
|
if hasattr(tokenizer, 'apply_chat_template'):
|
|
349
|
-
methods.append("
|
|
349
|
+
methods.append("render")
|
|
350
350
|
|
|
351
351
|
capabilities = {
|
|
352
352
|
"methods": methods,
|