cortex-llm 1.0.0__py3-none-any.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.
- cortex/__init__.py +73 -0
- cortex/__main__.py +83 -0
- cortex/config.py +329 -0
- cortex/conversation_manager.py +468 -0
- cortex/fine_tuning/__init__.py +8 -0
- cortex/fine_tuning/dataset.py +332 -0
- cortex/fine_tuning/mlx_lora_trainer.py +502 -0
- cortex/fine_tuning/trainer.py +957 -0
- cortex/fine_tuning/wizard.py +707 -0
- cortex/gpu_validator.py +467 -0
- cortex/inference_engine.py +727 -0
- cortex/metal/__init__.py +275 -0
- cortex/metal/gpu_validator.py +177 -0
- cortex/metal/memory_pool.py +886 -0
- cortex/metal/mlx_accelerator.py +678 -0
- cortex/metal/mlx_converter.py +638 -0
- cortex/metal/mps_optimizer.py +417 -0
- cortex/metal/optimizer.py +665 -0
- cortex/metal/performance_profiler.py +364 -0
- cortex/model_downloader.py +130 -0
- cortex/model_manager.py +2187 -0
- cortex/quantization/__init__.py +5 -0
- cortex/quantization/dynamic_quantizer.py +736 -0
- cortex/template_registry/__init__.py +15 -0
- cortex/template_registry/auto_detector.py +144 -0
- cortex/template_registry/config_manager.py +234 -0
- cortex/template_registry/interactive.py +260 -0
- cortex/template_registry/registry.py +347 -0
- cortex/template_registry/template_profiles/__init__.py +5 -0
- cortex/template_registry/template_profiles/base.py +142 -0
- cortex/template_registry/template_profiles/complex/__init__.py +5 -0
- cortex/template_registry/template_profiles/complex/reasoning.py +263 -0
- cortex/template_registry/template_profiles/standard/__init__.py +9 -0
- cortex/template_registry/template_profiles/standard/alpaca.py +73 -0
- cortex/template_registry/template_profiles/standard/chatml.py +82 -0
- cortex/template_registry/template_profiles/standard/gemma.py +103 -0
- cortex/template_registry/template_profiles/standard/llama.py +87 -0
- cortex/template_registry/template_profiles/standard/simple.py +65 -0
- cortex/ui/__init__.py +120 -0
- cortex/ui/cli.py +1685 -0
- cortex/ui/markdown_render.py +185 -0
- cortex/ui/terminal_app.py +534 -0
- cortex_llm-1.0.0.dist-info/METADATA +275 -0
- cortex_llm-1.0.0.dist-info/RECORD +48 -0
- cortex_llm-1.0.0.dist-info/WHEEL +5 -0
- cortex_llm-1.0.0.dist-info/entry_points.txt +2 -0
- cortex_llm-1.0.0.dist-info/licenses/LICENSE +21 -0
- cortex_llm-1.0.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
"""Markdown rendering helpers with <think> dimming support."""
|
|
2
|
+
|
|
3
|
+
from typing import List
|
|
4
|
+
|
|
5
|
+
from rich.console import Console
|
|
6
|
+
from rich.markdown import Markdown
|
|
7
|
+
from rich.segment import Segment
|
|
8
|
+
from rich.style import Style
|
|
9
|
+
from rich.syntax import Syntax
|
|
10
|
+
|
|
11
|
+
THINK_START_MARKER = "[[[THINK_START]]]"
|
|
12
|
+
THINK_END_MARKER = "[[[THINK_END]]]"
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def _mark_think_sections(text: str) -> str:
|
|
16
|
+
"""Replace <think> tags with sentinel markers outside fenced code blocks."""
|
|
17
|
+
lines = text.splitlines(keepends=True)
|
|
18
|
+
in_code_block = False
|
|
19
|
+
output: List[str] = []
|
|
20
|
+
|
|
21
|
+
for line in lines:
|
|
22
|
+
stripped = line.lstrip()
|
|
23
|
+
if stripped.startswith("```"):
|
|
24
|
+
in_code_block = not in_code_block
|
|
25
|
+
output.append(line)
|
|
26
|
+
continue
|
|
27
|
+
|
|
28
|
+
if in_code_block:
|
|
29
|
+
output.append(line)
|
|
30
|
+
continue
|
|
31
|
+
|
|
32
|
+
output.append(
|
|
33
|
+
line.replace("<think>", THINK_START_MARKER).replace("</think>", THINK_END_MARKER)
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
return "".join(output)
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
class CodeBlockWithLineNumbers(Markdown.elements["fence"]):
|
|
40
|
+
"""Markdown code block with line numbers."""
|
|
41
|
+
|
|
42
|
+
def __rich_console__(self, console: Console, options):
|
|
43
|
+
code = str(self.text).rstrip()
|
|
44
|
+
syntax = Syntax(code, self.lexer_name, theme=self.theme, line_numbers=True)
|
|
45
|
+
yield syntax
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
class MarkdownWithLineNumbers(Markdown):
|
|
49
|
+
"""Markdown renderer that keeps line numbers for fenced code blocks."""
|
|
50
|
+
|
|
51
|
+
elements = Markdown.elements.copy()
|
|
52
|
+
elements.update({
|
|
53
|
+
"fence": CodeBlockWithLineNumbers,
|
|
54
|
+
"code_block": CodeBlockWithLineNumbers,
|
|
55
|
+
})
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
class ThinkMarkdown:
|
|
59
|
+
"""Markdown renderer that dims content inside <think> tags."""
|
|
60
|
+
|
|
61
|
+
def __init__(
|
|
62
|
+
self,
|
|
63
|
+
markup: str,
|
|
64
|
+
code_theme: str = "monokai",
|
|
65
|
+
use_line_numbers: bool = False,
|
|
66
|
+
) -> None:
|
|
67
|
+
marked = _mark_think_sections(markup)
|
|
68
|
+
markdown_cls = MarkdownWithLineNumbers if use_line_numbers else Markdown
|
|
69
|
+
self._markdown = markdown_cls(marked, code_theme=code_theme)
|
|
70
|
+
|
|
71
|
+
def __rich_console__(self, console: Console, options):
|
|
72
|
+
segments = console.render(self._markdown, options)
|
|
73
|
+
start_marker = THINK_START_MARKER
|
|
74
|
+
end_marker = THINK_END_MARKER
|
|
75
|
+
markers = (start_marker, end_marker)
|
|
76
|
+
in_think = False
|
|
77
|
+
carry = ""
|
|
78
|
+
carry_style = None
|
|
79
|
+
|
|
80
|
+
def pending_suffix(text: str) -> tuple[str, str]:
|
|
81
|
+
max_prefix = 0
|
|
82
|
+
for marker in markers:
|
|
83
|
+
for i in range(1, len(marker)):
|
|
84
|
+
if text.endswith(marker[:i]) and i > max_prefix:
|
|
85
|
+
max_prefix = i
|
|
86
|
+
if max_prefix:
|
|
87
|
+
return text[:-max_prefix], text[-max_prefix:]
|
|
88
|
+
return text, ""
|
|
89
|
+
|
|
90
|
+
def emit(text: str, style: Style | None):
|
|
91
|
+
if not text:
|
|
92
|
+
return
|
|
93
|
+
if in_think:
|
|
94
|
+
style = (style or Style()) + Style(dim=True)
|
|
95
|
+
yield Segment(text, style)
|
|
96
|
+
|
|
97
|
+
for segment in segments:
|
|
98
|
+
if segment.control:
|
|
99
|
+
if carry:
|
|
100
|
+
yield from emit(carry, carry_style)
|
|
101
|
+
carry = ""
|
|
102
|
+
carry_style = None
|
|
103
|
+
yield segment
|
|
104
|
+
continue
|
|
105
|
+
|
|
106
|
+
text = segment.text
|
|
107
|
+
style = segment.style
|
|
108
|
+
|
|
109
|
+
if carry:
|
|
110
|
+
if carry_style != style:
|
|
111
|
+
yield from emit(carry, carry_style)
|
|
112
|
+
carry = ""
|
|
113
|
+
carry_style = None
|
|
114
|
+
else:
|
|
115
|
+
text = carry + text
|
|
116
|
+
carry = ""
|
|
117
|
+
carry_style = None
|
|
118
|
+
|
|
119
|
+
output = ""
|
|
120
|
+
index = 0
|
|
121
|
+
while index < len(text):
|
|
122
|
+
if text.startswith(start_marker, index):
|
|
123
|
+
if output:
|
|
124
|
+
yield from emit(output, style)
|
|
125
|
+
output = ""
|
|
126
|
+
in_think = True
|
|
127
|
+
index += len(start_marker)
|
|
128
|
+
continue
|
|
129
|
+
if text.startswith(end_marker, index):
|
|
130
|
+
if output:
|
|
131
|
+
yield from emit(output, style)
|
|
132
|
+
output = ""
|
|
133
|
+
in_think = False
|
|
134
|
+
index += len(end_marker)
|
|
135
|
+
continue
|
|
136
|
+
output += text[index]
|
|
137
|
+
index += 1
|
|
138
|
+
|
|
139
|
+
output, carry = pending_suffix(output)
|
|
140
|
+
if output:
|
|
141
|
+
yield from emit(output, style)
|
|
142
|
+
if carry:
|
|
143
|
+
carry_style = style
|
|
144
|
+
|
|
145
|
+
if carry:
|
|
146
|
+
yield from emit(carry, carry_style)
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
class PrefixedRenderable:
|
|
150
|
+
"""Render a prefix before the first line and an indent after newlines."""
|
|
151
|
+
|
|
152
|
+
def __init__(
|
|
153
|
+
self,
|
|
154
|
+
renderable,
|
|
155
|
+
prefix: str,
|
|
156
|
+
prefix_style: Style | None = None,
|
|
157
|
+
indent: str | None = None,
|
|
158
|
+
) -> None:
|
|
159
|
+
self.renderable = renderable
|
|
160
|
+
self.prefix = prefix
|
|
161
|
+
self.prefix_style = prefix_style
|
|
162
|
+
self.indent = indent if indent is not None else " " * len(prefix)
|
|
163
|
+
|
|
164
|
+
def __rich_console__(self, console: Console, options):
|
|
165
|
+
yield Segment(self.prefix, self.prefix_style)
|
|
166
|
+
|
|
167
|
+
for segment in console.render(self.renderable, options):
|
|
168
|
+
if segment.control:
|
|
169
|
+
yield segment
|
|
170
|
+
continue
|
|
171
|
+
|
|
172
|
+
text = segment.text
|
|
173
|
+
style = segment.style
|
|
174
|
+
|
|
175
|
+
if "\n" not in text:
|
|
176
|
+
yield segment
|
|
177
|
+
continue
|
|
178
|
+
|
|
179
|
+
parts = text.split("\n")
|
|
180
|
+
for index, part in enumerate(parts):
|
|
181
|
+
if part:
|
|
182
|
+
yield Segment(part, style)
|
|
183
|
+
if index < len(parts) - 1:
|
|
184
|
+
yield Segment("\n", style)
|
|
185
|
+
yield Segment(self.indent, None)
|