bit-ttt-engine 0.6.1__cp310-cp310-win_amd64.whl → 0.7.0__cp310-cp310-win_amd64.whl
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.
- bit_ttt_engine-0.7.0.dist-info/METADATA +136 -0
- bit_ttt_engine-0.7.0.dist-info/RECORD +14 -0
- bit_ttt_engine-0.7.0.dist-info/entry_points.txt +2 -0
- bit_ttt_engine-0.7.0.dist-info/licenses/LICENSE +21 -0
- cortex_rust/__init__.py +21 -1
- cortex_rust/__main__.py +4 -0
- cortex_rust/__pycache__/__init__.cpython-310.pyc +0 -0
- cortex_rust/chat.py +196 -0
- cortex_rust/cli.py +381 -0
- cortex_rust/cortex_rust.cp310-win_amd64.pyd +0 -0
- cortex_rust/engine.py +253 -0
- cortex_rust/server.py +493 -0
- bit_ttt_engine-0.6.1.dist-info/METADATA +0 -92
- bit_ttt_engine-0.6.1.dist-info/RECORD +0 -8
- cortex_rust/__init__.pyi +0 -100
- cortex_rust/py.typed +0 -0
- /bit_ttt_engine-0.6.1.dist-info/licenses/LICENSE → /LICENSE +0 -0
- {bit_ttt_engine-0.6.1.dist-info → bit_ttt_engine-0.7.0.dist-info}/WHEEL +0 -0
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: bit-ttt-engine
|
|
3
|
+
Version: 0.7.0
|
|
4
|
+
Classifier: Development Status :: 4 - Beta
|
|
5
|
+
Classifier: Programming Language :: Rust
|
|
6
|
+
Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
7
|
+
Classifier: Programming Language :: Python :: 3
|
|
8
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
9
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
10
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
13
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
14
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
15
|
+
Classifier: Operating System :: Microsoft :: Windows
|
|
16
|
+
Requires-Dist: tokenizers>=0.19
|
|
17
|
+
Requires-Dist: huggingface-hub>=0.20
|
|
18
|
+
Requires-Dist: bit-ttt-engine[server] ; extra == 'all'
|
|
19
|
+
Requires-Dist: fastapi>=0.100 ; extra == 'server'
|
|
20
|
+
Requires-Dist: uvicorn>=0.20 ; extra == 'server'
|
|
21
|
+
Requires-Dist: sse-starlette>=1.6 ; extra == 'server'
|
|
22
|
+
Provides-Extra: all
|
|
23
|
+
Provides-Extra: server
|
|
24
|
+
License-File: LICENSE
|
|
25
|
+
Summary: Fast local LLM inference with TTT (Test-Time Training) and LoRA — the model that learns while it runs
|
|
26
|
+
Keywords: llm,inference,ttt,lora,gguf,quantization,cuda
|
|
27
|
+
Home-Page: https://github.com/imonoonoko/Bit-TTT-Engine
|
|
28
|
+
Author: imonoonoko
|
|
29
|
+
License: MIT
|
|
30
|
+
Requires-Python: >=3.8
|
|
31
|
+
Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
|
|
32
|
+
|
|
33
|
+
# 🧠 Bit-TTT-Engine
|
|
34
|
+
|
|
35
|
+
[](https://pypi.org/project/bit-ttt-engine/)
|
|
36
|
+
[](LICENSE)
|
|
37
|
+
[](https://www.rust-lang.org/)
|
|
38
|
+
|
|
39
|
+
**Fast local LLM inference that learns while it runs.**
|
|
40
|
+
|
|
41
|
+
- 🏎️ **47+ tok/s** on RTX 4060 Ti (7B Q4_K_M)
|
|
42
|
+
- 🧠 **TTT** (Test-Time Training) — adapts during inference (world's first!)
|
|
43
|
+
- 🎨 **LoRA** — fine-tune with one flag
|
|
44
|
+
- 📦 **5 models** — Llama-2/3, Gemma-2, Qwen2.5, Mistral
|
|
45
|
+
- 🔌 **OpenAI-compatible API** — drop-in replacement
|
|
46
|
+
|
|
47
|
+
## 🚀 Quick Start
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
pip install bit-ttt-engine
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
```python
|
|
54
|
+
import cortex_rust
|
|
55
|
+
|
|
56
|
+
# Load any GGUF model (auto-downloads from HuggingFace!)
|
|
57
|
+
model = cortex_rust.load("user/model-GGUF")
|
|
58
|
+
|
|
59
|
+
# Chat
|
|
60
|
+
response = model.chat([
|
|
61
|
+
{"role": "user", "content": "Hello!"}
|
|
62
|
+
])
|
|
63
|
+
print(response)
|
|
64
|
+
|
|
65
|
+
# Stream
|
|
66
|
+
for token in model.chat_stream([
|
|
67
|
+
{"role": "user", "content": "Tell me a story"}
|
|
68
|
+
]):
|
|
69
|
+
print(token, end="", flush=True)
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## 🖥️ CLI
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
# Interactive chat
|
|
76
|
+
bit-ttt chat model.gguf
|
|
77
|
+
|
|
78
|
+
# Generate text
|
|
79
|
+
bit-ttt generate model.gguf -p "Once upon a time"
|
|
80
|
+
|
|
81
|
+
# OpenAI-compatible API server
|
|
82
|
+
bit-ttt serve model.gguf --port 8000
|
|
83
|
+
|
|
84
|
+
# With LoRA + Q8 KV cache
|
|
85
|
+
bit-ttt chat model.gguf --lora adapter.bin --q8-cache
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
## 🧠 TTT — Test-Time Training
|
|
89
|
+
|
|
90
|
+
**The model learns while it generates.** No other local LLM does this.
|
|
91
|
+
|
|
92
|
+
```python
|
|
93
|
+
model = cortex_rust.load("model.gguf")
|
|
94
|
+
model.enable_ttt(True)
|
|
95
|
+
|
|
96
|
+
# Each conversation makes the model smarter
|
|
97
|
+
response = model.chat([{"role": "user", "content": "My name is Alice"}])
|
|
98
|
+
# Next time, it remembers context better!
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
## ⚡ Performance
|
|
102
|
+
|
|
103
|
+
| Model | Speed | VRAM |
|
|
104
|
+
|-------|-------|------|
|
|
105
|
+
| Llama-2 7B (Q4_K_M) | 47.8 tok/s | ~5 GB |
|
|
106
|
+
| Llama-3 8B (Q4_K_M) | 36.8 tok/s | ~6 GB |
|
|
107
|
+
| Mistral 7B (Q4_K_M) | 40.8 tok/s | ~5 GB |
|
|
108
|
+
| Qwen2.5 1.5B (Q4_K_M) | 70.4 tok/s | ~2 GB |
|
|
109
|
+
|
|
110
|
+
With `--q8-cache`: **82% VRAM reduction** for KV cache.
|
|
111
|
+
|
|
112
|
+
## 🔌 OpenAI-Compatible API
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
bit-ttt serve model.gguf --port 8000
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
```python
|
|
119
|
+
from openai import OpenAI
|
|
120
|
+
client = OpenAI(base_url="http://localhost:8000/v1", api_key="none")
|
|
121
|
+
response = client.chat.completions.create(
|
|
122
|
+
model="default",
|
|
123
|
+
messages=[{"role": "user", "content": "Hi!"}],
|
|
124
|
+
stream=True,
|
|
125
|
+
)
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
## 📖 Links
|
|
129
|
+
|
|
130
|
+
- [GitHub](https://github.com/imonoonoko/Bit-TTT-Engine)
|
|
131
|
+
- [Documentation](https://github.com/imonoonoko/Bit-TTT-Engine#readme)
|
|
132
|
+
|
|
133
|
+
## 💖 License
|
|
134
|
+
|
|
135
|
+
MIT License
|
|
136
|
+
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
LICENSE,sha256=JJLZ3h6-sbZqpBjH8srqgZ40NaAKhVqh2oXOM6E2Mak,1088
|
|
2
|
+
bit_ttt_engine-0.7.0.dist-info\METADATA,sha256=DcIuKoAPVwcTyCrC93zMP8HDeP6N_268XJuc6_4B8x0,3895
|
|
3
|
+
bit_ttt_engine-0.7.0.dist-info\WHEEL,sha256=GCQ19ZBvayuBQJpz6xNbc8p6I5GMQcns9k4vQBQ8VH8,97
|
|
4
|
+
bit_ttt_engine-0.7.0.dist-info\entry_points.txt,sha256=UDj3hFWWNAkFeEunLb_bbBXiZiR2fTdJ_3SYHGxSm8Y,47
|
|
5
|
+
bit_ttt_engine-0.7.0.dist-info\licenses\LICENSE,sha256=JJLZ3h6-sbZqpBjH8srqgZ40NaAKhVqh2oXOM6E2Mak,1088
|
|
6
|
+
cortex_rust\__init__.py,sha256=Ljn3niikl34z9Aa0H6C2mRH1-LFQUyhjHBJ-kqBevbU,847
|
|
7
|
+
cortex_rust\__main__.py,sha256=2VfobbcvxxN5ez4AlEC12IhkhfXKLilTdfhH9A9maXw,98
|
|
8
|
+
cortex_rust\__pycache__\__init__.cpython-310.pyc,sha256=buwvbY3RJ7QEIWPNXGFqEBWThA6f44RNsFpATpQc2kg,765
|
|
9
|
+
cortex_rust\chat.py,sha256=Hvk3JPA2CurvTrVGEeL0kuUU-uFxFWLRSQWGvPkQKAo,6727
|
|
10
|
+
cortex_rust\cli.py,sha256=U4K-4MT9HvVYPGnZv_C5j_8l3-EoD4kcCGIyOQHosbQ,13318
|
|
11
|
+
cortex_rust\cortex_rust.cp310-win_amd64.pyd,sha256=pdHNyK7KYKwSnzPEahJm-Jc6y_TJHHMeosqozZlDXjc,26248704
|
|
12
|
+
cortex_rust\engine.py,sha256=E5K23bonOov45gBMLEogZsvy2LeaX7kkMF3qTPzxYhs,8576
|
|
13
|
+
cortex_rust\server.py,sha256=Pna2HPxMI_lzjUmG0wHhbp1-49Cd0T97H5LxXeLkvBU,16167
|
|
14
|
+
bit_ttt_engine-0.7.0.dist-info\RECORD,,
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 imonoonoko
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
cortex_rust/__init__.py
CHANGED
|
@@ -1,5 +1,25 @@
|
|
|
1
|
+
# Auto-add CUDA DLL path on Windows
|
|
2
|
+
import os
|
|
3
|
+
import sys
|
|
4
|
+
|
|
5
|
+
if sys.platform == "win32":
|
|
6
|
+
cuda_paths = [
|
|
7
|
+
os.environ.get("CUDA_PATH", ""),
|
|
8
|
+
r"C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v12.4",
|
|
9
|
+
r"C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v12.3",
|
|
10
|
+
r"C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v12.0",
|
|
11
|
+
r"C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v11.8",
|
|
12
|
+
]
|
|
13
|
+
for cuda_path in cuda_paths:
|
|
14
|
+
bin_path = os.path.join(cuda_path, "bin")
|
|
15
|
+
if os.path.isdir(bin_path):
|
|
16
|
+
os.add_dll_directory(bin_path)
|
|
17
|
+
break
|
|
18
|
+
|
|
1
19
|
from .cortex_rust import *
|
|
20
|
+
from .chat import format_chat, format_simple, detect_template, list_templates
|
|
21
|
+
from .engine import load, Model
|
|
2
22
|
|
|
3
23
|
__doc__ = cortex_rust.__doc__
|
|
4
24
|
if hasattr(cortex_rust, "__all__"):
|
|
5
|
-
__all__ = cortex_rust.__all__
|
|
25
|
+
__all__ = cortex_rust.__all__
|
cortex_rust/__main__.py
ADDED
|
Binary file
|
cortex_rust/chat.py
ADDED
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
"""Chat template support for various LLM architectures.
|
|
2
|
+
|
|
3
|
+
Provides format_chat() to convert messages into model-specific prompt strings.
|
|
4
|
+
Supports Llama-3, Llama-2, Gemma-2, Qwen/ChatML, and generic formats.
|
|
5
|
+
|
|
6
|
+
Usage:
|
|
7
|
+
from cortex_rust.chat import format_chat, detect_template
|
|
8
|
+
|
|
9
|
+
messages = [
|
|
10
|
+
{"role": "system", "content": "You are a helpful assistant."},
|
|
11
|
+
{"role": "user", "content": "Hello!"},
|
|
12
|
+
]
|
|
13
|
+
prompt = format_chat(messages, template="llama3")
|
|
14
|
+
# Or auto-detect from model path:
|
|
15
|
+
template = detect_template("Meta-Llama-3-8B-Instruct.Q4_K_M.gguf")
|
|
16
|
+
prompt = format_chat(messages, template=template)
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
from typing import List, Dict, Optional
|
|
20
|
+
|
|
21
|
+
# ============================================================================
|
|
22
|
+
# Template Definitions
|
|
23
|
+
# ============================================================================
|
|
24
|
+
|
|
25
|
+
TEMPLATES = {
|
|
26
|
+
"llama3": {
|
|
27
|
+
"bos": "<|begin_of_text|>",
|
|
28
|
+
"system_start": "<|start_header_id|>system<|end_header_id|>\n\n",
|
|
29
|
+
"system_end": "<|eot_id|>",
|
|
30
|
+
"user_start": "<|start_header_id|>user<|end_header_id|>\n\n",
|
|
31
|
+
"user_end": "<|eot_id|>",
|
|
32
|
+
"assistant_start": "<|start_header_id|>assistant<|end_header_id|>\n\n",
|
|
33
|
+
"assistant_end": "<|eot_id|>",
|
|
34
|
+
"default_system": "You are a helpful assistant.",
|
|
35
|
+
},
|
|
36
|
+
"llama2": {
|
|
37
|
+
"bos": "<s>",
|
|
38
|
+
"system_start": "<<SYS>>\n",
|
|
39
|
+
"system_end": "\n<</SYS>>\n\n",
|
|
40
|
+
"user_start": "[INST] ",
|
|
41
|
+
"user_end": " [/INST]",
|
|
42
|
+
"assistant_start": " ",
|
|
43
|
+
"assistant_end": " </s>",
|
|
44
|
+
"default_system": "You are a helpful, respectful and honest assistant.",
|
|
45
|
+
# Llama-2 embeds system inside first [INST]
|
|
46
|
+
"system_inside_user": True,
|
|
47
|
+
},
|
|
48
|
+
"gemma2": {
|
|
49
|
+
"bos": "<bos>",
|
|
50
|
+
"system_start": "", # Gemma-2 has no system role
|
|
51
|
+
"system_end": "",
|
|
52
|
+
"user_start": "<start_of_turn>user\n",
|
|
53
|
+
"user_end": "<end_of_turn>\n",
|
|
54
|
+
"assistant_start": "<start_of_turn>model\n",
|
|
55
|
+
"assistant_end": "<end_of_turn>\n",
|
|
56
|
+
"default_system": None, # No system support
|
|
57
|
+
},
|
|
58
|
+
"chatml": {
|
|
59
|
+
# Used by Qwen, Mistral-Instruct, etc.
|
|
60
|
+
"bos": "",
|
|
61
|
+
"system_start": "<|im_start|>system\n",
|
|
62
|
+
"system_end": "<|im_end|>\n",
|
|
63
|
+
"user_start": "<|im_start|>user\n",
|
|
64
|
+
"user_end": "<|im_end|>\n",
|
|
65
|
+
"assistant_start": "<|im_start|>assistant\n",
|
|
66
|
+
"assistant_end": "<|im_end|>\n",
|
|
67
|
+
"default_system": "You are a helpful assistant.",
|
|
68
|
+
},
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
# Model name patterns → template mapping
|
|
72
|
+
_DETECTION_PATTERNS = [
|
|
73
|
+
("llama-3", "llama3"),
|
|
74
|
+
("llama3", "llama3"),
|
|
75
|
+
("meta-llama-3", "llama3"),
|
|
76
|
+
("llama-2", "llama2"),
|
|
77
|
+
("llama2", "llama2"),
|
|
78
|
+
("gemma-2", "gemma2"),
|
|
79
|
+
("gemma2", "gemma2"),
|
|
80
|
+
("qwen", "chatml"),
|
|
81
|
+
("mistral", "chatml"),
|
|
82
|
+
("yi-", "chatml"),
|
|
83
|
+
]
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
def detect_template(model_path: str) -> str:
|
|
87
|
+
"""Auto-detect chat template from model filename.
|
|
88
|
+
|
|
89
|
+
Args:
|
|
90
|
+
model_path: Path to model file (e.g., "Meta-Llama-3-8B-Instruct.Q4_K_M.gguf")
|
|
91
|
+
|
|
92
|
+
Returns:
|
|
93
|
+
Template name (e.g., "llama3", "chatml"). Falls back to "chatml" if unknown.
|
|
94
|
+
"""
|
|
95
|
+
name = model_path.lower().replace("\\", "/").split("/")[-1]
|
|
96
|
+
for pattern, template in _DETECTION_PATTERNS:
|
|
97
|
+
if pattern in name:
|
|
98
|
+
return template
|
|
99
|
+
return "chatml" # Safe default
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
def list_templates() -> List[str]:
|
|
103
|
+
"""List all available template names."""
|
|
104
|
+
return list(TEMPLATES.keys())
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
def format_chat(
|
|
108
|
+
messages: List[Dict[str, str]],
|
|
109
|
+
template: str = "chatml",
|
|
110
|
+
add_generation_prompt: bool = True,
|
|
111
|
+
) -> str:
|
|
112
|
+
"""Format chat messages into a model-specific prompt string.
|
|
113
|
+
|
|
114
|
+
Args:
|
|
115
|
+
messages: List of {"role": "system"|"user"|"assistant", "content": "..."}
|
|
116
|
+
template: Template name ("llama3", "llama2", "gemma2", "chatml")
|
|
117
|
+
add_generation_prompt: If True, append assistant start token at the end
|
|
118
|
+
|
|
119
|
+
Returns:
|
|
120
|
+
Formatted prompt string ready for model.generate()
|
|
121
|
+
|
|
122
|
+
Example:
|
|
123
|
+
>>> messages = [{"role": "user", "content": "Hello!"}]
|
|
124
|
+
>>> format_chat(messages, template="llama3")
|
|
125
|
+
'<|begin_of_text|><|start_header_id|>user<|end_header_id|>\\n\\nHello!<|eot_id|><|start_header_id|>assistant<|end_header_id|>\\n\\n'
|
|
126
|
+
"""
|
|
127
|
+
if template not in TEMPLATES:
|
|
128
|
+
raise ValueError(f"Unknown template '{template}'. Available: {list_templates()}")
|
|
129
|
+
|
|
130
|
+
tmpl = TEMPLATES[template]
|
|
131
|
+
parts = [tmpl["bos"]]
|
|
132
|
+
|
|
133
|
+
system_inside_user = tmpl.get("system_inside_user", False)
|
|
134
|
+
system_content = None
|
|
135
|
+
|
|
136
|
+
for msg in messages:
|
|
137
|
+
role = msg["role"]
|
|
138
|
+
content = msg["content"]
|
|
139
|
+
|
|
140
|
+
if role == "system":
|
|
141
|
+
if system_inside_user:
|
|
142
|
+
# Llama-2 style: save system for embedding in first user message
|
|
143
|
+
system_content = content
|
|
144
|
+
elif tmpl["system_start"]: # Skip if no system support (Gemma-2)
|
|
145
|
+
parts.append(tmpl["system_start"])
|
|
146
|
+
parts.append(content)
|
|
147
|
+
parts.append(tmpl["system_end"])
|
|
148
|
+
|
|
149
|
+
elif role == "user":
|
|
150
|
+
parts.append(tmpl["user_start"])
|
|
151
|
+
if system_inside_user and system_content is not None:
|
|
152
|
+
# Llama-2: embed system before user content
|
|
153
|
+
parts.append(tmpl["system_start"])
|
|
154
|
+
parts.append(system_content)
|
|
155
|
+
parts.append(tmpl["system_end"])
|
|
156
|
+
system_content = None # Only first user message
|
|
157
|
+
parts.append(content)
|
|
158
|
+
parts.append(tmpl["user_end"])
|
|
159
|
+
|
|
160
|
+
elif role == "assistant":
|
|
161
|
+
parts.append(tmpl["assistant_start"])
|
|
162
|
+
parts.append(content)
|
|
163
|
+
parts.append(tmpl["assistant_end"])
|
|
164
|
+
|
|
165
|
+
if add_generation_prompt:
|
|
166
|
+
parts.append(tmpl["assistant_start"])
|
|
167
|
+
|
|
168
|
+
return "".join(parts)
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
def format_simple(
|
|
172
|
+
user_message: str,
|
|
173
|
+
system_message: Optional[str] = None,
|
|
174
|
+
template: str = "chatml",
|
|
175
|
+
) -> str:
|
|
176
|
+
"""Convenience: format a single user message (with optional system prompt).
|
|
177
|
+
|
|
178
|
+
Args:
|
|
179
|
+
user_message: The user's message
|
|
180
|
+
system_message: Optional system prompt (uses template default if None)
|
|
181
|
+
template: Template name
|
|
182
|
+
|
|
183
|
+
Returns:
|
|
184
|
+
Formatted prompt string
|
|
185
|
+
"""
|
|
186
|
+
messages = []
|
|
187
|
+
|
|
188
|
+
tmpl = TEMPLATES.get(template, TEMPLATES["chatml"])
|
|
189
|
+
if system_message is not None:
|
|
190
|
+
messages.append({"role": "system", "content": system_message})
|
|
191
|
+
elif tmpl.get("default_system"):
|
|
192
|
+
messages.append({"role": "system", "content": tmpl["default_system"]})
|
|
193
|
+
|
|
194
|
+
messages.append({"role": "user", "content": user_message})
|
|
195
|
+
|
|
196
|
+
return format_chat(messages, template=template)
|