From 2ccb1725c6a2355490461ca2660cd65035157d60 Mon Sep 17 00:00:00 2001
From: exdysa <91800957+exdysa@users.noreply.github.com>
Date: Sat, 19 Apr 2025 19:03:54 -0400
Subject: [PATCH 1/3] +More model selector adj
---
nnll_08/__init__.py | 8 +--
nnll_10/__init__.py | 47 ---------------
nnll_10/package/combo.tcss | 106 +++++++++++++++++++--------------
nnll_10/package/main_screen.py | 13 ++--
nnll_10/package/selectah.py | 63 ++++++++++++++++----
nnll_10/package/voice_panel.py | 4 +-
nnll_13/__init__.py | 4 +-
nnll_16/__init__.py | 6 +-
8 files changed, 131 insertions(+), 120 deletions(-)
diff --git a/nnll_08/__init__.py b/nnll_08/__init__.py
index 40efec97..3c136f12 100644
--- a/nnll_08/__init__.py
+++ b/nnll_08/__init__.py
@@ -30,13 +30,13 @@ def seed_planter(seed, deterministic=True) -> int:
torch.manual_seed(seed)
random.seed(seed)
- if torch.cuda.is_available() is True:
- if deterministic is True:
+ if torch.cuda.is_available():
+ if deterministic:
return {"torch.backends.cudnn.deterministic": "True", "torch.backends.cudnn.benchmark": "False"}
return torch.cuda.manual_seed(seed), torch.cuda.manual_seed_all(seed)
- elif torch.backends.mps.is_available() is True:
+ elif torch.backends.mps.is_available():
return torch.mps.manual_seed(seed)
- elif torch.xpu.is_available() is True:
+ elif torch.xpu.is_available():
return torch.xpu.manual_seed(seed)
diff --git a/nnll_10/__init__.py b/nnll_10/__init__.py
index 4b2ce01c..ae4e8a0c 100644
--- a/nnll_10/__init__.py
+++ b/nnll_10/__init__.py
@@ -136,50 +136,3 @@ def edit_weight(self, selection: str, mode_in: str, mode_out: str) -> None:
nfo("Weight changed for: ", self.intent_graph[mode_in][mode_out][index[0]]["entry"].model, f"model # {index[0]}")
self.set_ckpts()
dbug("Confirm :", self.intent_graph[mode_in][mode_out])
-
-
-# model_name = entry[2].get("entry").model
-# index_name = (os.path.basename(model_name), model_name)
-# self.model_names.insert(self.model_names.index(index_name), (f"*{os.path.basename(model_name)}", model_name))
-# what should happen next is setckpts
-
-# [reg_id[2] for reg_id in self.intent_graph.edges(data=True) if selection in reg_id[2].get("entry").model]
-# right = left - weight_value
-# if weight_value
-# pass
-
-# left = int(weight_value)
-# right = left - weight_value
-
-# # def check_weights(self, entry: str) -> None:
-
-# registry_data = [reg_id[2].get('entry').model for reg_id in self.intent_graph.edges(data=True).model if 'ibm' in reg_id[2].get('entry').model]
-
-# def
-# add weight
-# check weight
-
-# async def walk_intent(self, send: bool = False, composer: Callable = None, processor: Callable = None) -> None:
-# """Provided the coordinates in the intent processor, follow the list of in and out methods"""
-# await self.confirm_available_graph()
-# await self.confirm_coordinates_path()
-# coordinates = self.coordinates_path
-# if not coordinates:
-# coordinates = ["text", "text"]
-# hop_length = len(coordinates) - 1
-# for i in range(hop_length):
-# if i + 1 < hop_length:
-# await self.confirm_coordinates_path()
-# await self.confirm_model_waypoints()
-# if send:
-# await processor(last_hop=False)
-# composer(mode_in=coordinates[i + 1], mode_out=coordinates[i + 2])
-# else:
-# old_model_names = self.model_names if self.model_names else []
-# composer(mode_in=coordinates[i + 1], mode_out=coordinates[i + 2], io_only=True)
-# self.model_names.extend(old_model_names)
-
-# elif send:
-# await self.confirm_coordinates_path()
-# await self.confirm_model_waypoints()
-# processor()
diff --git a/nnll_10/package/combo.tcss b/nnll_10/package/combo.tcss
index 6fb93b9f..7cd3dba1 100644
--- a/nnll_10/package/combo.tcss
+++ b/nnll_10/package/combo.tcss
@@ -80,34 +80,64 @@ $selection-fg: $background;
#seam {
layout: grid;
grid-size: 2 1;
- grid-columns: 60fr 60fr;
+ grid-columns: 60fr 30fr;
keyline: none;
border: none;
background:$negative-space 7%;
height: 1;
+ text-wrap: nowrap;
}
#selectah {
color: $sunken-text;
- border: vkey $negative-space 7%;
height: 2;
margin: 0 1;
padding: -1 0;
overflow: hidden;
text-align: end;
- # align: right top;
width: 100%;
layer: above;
- text-wrap:nowrap;
+ text-overflow: ellipsis;
+ &:focus {
+ background: white 10%;
+ }
+ &.active {
+ Static#label {
+ text-overflow:ellipsis;
+ overflow-x: hidden;
+ &:blur {
+ color: $accent;
+ text-align: end;
+ }
+ &:focus {
+ color: $accent;
+ }
+ &:hover {
+ color: $accent;
+ }
+ }
+ }
+ &.-expanded {
+
+ color: $raised-text;
+ text-align: end;
+ content-align: right top;
+ background:$negative-space 7%;
+ overflow-x: hidden;
+ &.-selected {
+ background: $selection-bg;
+
+ }
+ }
Static#label {
min-width: 10;
+ text-overflow:ellipsis;
+ overflow: hidden;
&:blur {
color: $sunken-text;
text-align: end;
-
}
&:focus {
- border: none;
- color: $foreground-darken-1;
+ color: $raised-text;
}
&:hover {
color: $foreground-darken-1;
@@ -116,70 +146,55 @@ $selection-fg: $background;
background: $selection-bg;
}
}
- &.active {
- Static#label {
- &:blur {
- color: $accent;
- text-align: end;
- }
- &:focus {
- color: $accent;
- }
- &:hover {
- color: $accent;
- }
- &.-selected {
- color: $accent;
- background: $selection-bg;
- }
- }
- }
+
SelectCurrent {
background:$negative-space 7%;
- color: $sunken-text;
- border:none;
+ border: vkey $focus-surface;
+ color: $raised-text;
overflow: hidden;
+ text-overflow: ellipsis;
+ border: vkey $surface;
+
+ &:blur {
+ border: vkey $surface;
+ }
&:hover {
color: $raised-text;
}
+ &:focus {
+ color: $background-lighten-3;
+ }
.arrow {
color: $sunken-text;
- &:hover {
- color: $raised-text;
- }
- }
- }
- &.-expanded {
- text-align: end;
- content-align: right top;
- background:$negative-space 7%;
- text-wrap: nowrap;
- &.-selected {
- background: $selection-bg;
}
}
SelectOverlay {
-
- text-wrap: nowrap;
+ text-overflow:ellipsis;
+ border: vkey $negative-space 7%;
overflow-x: hidden;
overflow-y: scroll;
text-align: end;
color: $sunken-text;
overlay: screen;
- scrollbar-size: 0 0;
+ scrollbar-size: 0 1;
+ scrollbar-background: $negative-space 7%;
+ scrollbar-background-active: $negative-space 7%;
+ scrollbar-color: $panel;
+ scrollbar-color-active: $focus-surface;
+ scrollbar-color-hover: $background-lighten-3;
background: $negative-space 7%;
- border: vkey $background-lighten-3;
&.-selected {
+ overflow: hidden;
background: $selection-bg;
+ border: vkey $background-lighten-3;
}
& > .option-list--option-selected {
-
+ overflow: hidden;
background: $selection-bg;
color: $selection-fg;
}
& > .option-list--option {
- text-wrap:nowrap;
overflow: hidden;
}
& > .option-list--option-highlighted {
@@ -223,7 +238,6 @@ SidebarLeft, SidebarRight {
border-subtitle-color: $foreground-darken-1;
}
&:focus {
- border: none;
border: $border-shape $focus-surface;
border-subtitle-color: $foreground;
}
diff --git a/nnll_10/package/main_screen.py b/nnll_10/package/main_screen.py
index 82f0969d..dbbd1ff3 100644
--- a/nnll_10/package/main_screen.py
+++ b/nnll_10/package/main_screen.py
@@ -16,6 +16,7 @@
# from textual.widget import Widget
from textual.widgets import Static, ContentSwitcher # , DataTable
+from textual.widget import Widget
from nnll_01 import debug_monitor, info_message as nfo, debug_message as dbug
@@ -46,6 +47,7 @@ class Fold(Screen[bool]):
# model_names = [("model", 0), ("x", 0)]
tx_data: dict = {}
counter = 0
+ hover_name: reactive[str] = reactive("")
input_map: dict = {
"text": "message_panel",
"image": "message_panel",
@@ -126,17 +128,12 @@ def is_ui_ready(self):
return True
@on(events.Focus)
- def on_focus(self, event: events.Focus) -> None:
- """Textual API event, refresh pathing"""
- if self.ui["sl"].has_focus and self.ui["sl"].expanded:
+ async def on_focus(self, event=events.Focus):
+ if event.control.id == "selectah":
self.ready_tx()
self.walk_intent()
self.ui["sl"].prompt = next(iter(self.int_proc.models))[0]
- # selection = next(iter(self.graph.models))[1]
- # else:
- # selection = self.selection
-
@work(exclusive=True)
async def _on_key(self, event: events.Key) -> None:
"""Textual API event trigger, Suppress/augment default key actions to trigger keybindings"""
@@ -264,7 +261,7 @@ async def send_tx(self, last_hop=True) -> None:
ckpt = self.ui["sl"].selection
if ckpt is None:
- ckpt = next(iter(self.int_proc.ckpts))[1]
+ ckpt = next(iter(self.int_proc.ckpts)).get("entry")
chat = ChatMachineWithMemory(sig=QASignature)
self.ui["rp"].on_text_area_changed()
self.ui["rp"].insert("\n---\n")
diff --git a/nnll_10/package/selectah.py b/nnll_10/package/selectah.py
index 18d8e41f..913b1ae6 100644
--- a/nnll_10/package/selectah.py
+++ b/nnll_10/package/selectah.py
@@ -5,13 +5,14 @@
import os
import networkx as nx
-from textual import on, events
+from rich.color import Color
+from textual import on, events, work
from textual.reactive import reactive
from textual.screen import Screen
-from textual.widgets import Select
+from textual.widgets import Select, Label
from textual.widgets._select import SelectCurrent, SelectOverlay
-from nnll_01 import debug_message as dbug # , debug_monitor
+from nnll_01 import debug_message as dbug, debug_monitor, info_message as nfo
class Selectah(Select):
@@ -19,20 +20,16 @@ class Selectah(Select):
graph: nx.Graph = None
mode_in: str = "text"
mode_out: str = "text"
+ focused = True
+ hover = True
def on_mount(self) -> None:
# self.options = self.graph.models
self.graph = self.query_ancestor(Screen).int_proc
# self.prompt = os.path.basename(next(iter(self.graph.models))[0])
- @on(events.Focus)
- async def on_focus(self) -> None:
- """Expand panel immediately when clicked in terminal"""
- if SelectOverlay.has_focus:
- self.set_options(self.graph.models)
-
@on(Select.Changed)
- def on_changed(self) -> None: # event: Select.Changed) -> None:
+ async def on_changed(self) -> None: # event: Select.Changed) -> None:
"""Rearrange models"""
try:
assert self.query_one(SelectCurrent).has_value
@@ -42,7 +39,53 @@ def on_changed(self) -> None: # event: Select.Changed) -> None:
self.graph.edit_weight(selection=self.value, mode_in=self.mode_in, mode_out=self.mode_out)
self.set_options(self.graph.models)
self.prompt = next(iter(self.graph.models))[0]
+ self.expanded = False
+
+ @debug_monitor
+ @work(exclusive=True)
+ @on(events.Enter)
+ async def on_enter(self, event: events.Enter) -> None:
+ """Force terminal mouse event monitoring"""
+ if event.node == SelectOverlay or event.node == self:
+ self.hover = True
+
+ @debug_monitor
+ @work(exclusive=True)
+ @on(events.Leave)
+ async def on_leave(self, event: events.Leave) -> None:
+ """Force terminal mouse event monitoring"""
+ if event.node == SelectOverlay or event.node == self:
+ self.hover = True
+
+ @work(exclusive=True)
+ @on(events.Focus)
+ async def on_focus(self, event: events.Focus) -> None:
+ """Expand panel immediately when clicked in terminal"""
+ if SelectOverlay.has_focus or self.has_focus:
+ self.focused = True
+ self.set_options(self.graph.models)
+
+ @work(exclusive=True)
+ @on(events.MouseDown)
+ async def on_mouse_down(self, event: events.MouseDown) -> None:
+ """Expand panel immediately when clicked in terminal"""
+ if self.hover and not self.expanded:
+ self.expanded = True
+ elif (SelectOverlay.has_focus or self.has_focus) and self.expanded:
+ self.blur()
+
+ @work(exclusive=True)
+ @on(events.MouseUp)
+ async def on_mouse_up(self, event: events.MouseUp) -> None:
+ """Expand panel immediately when clicked in terminal"""
+ if self.hover and self.focus and self.expanded:
+ self.expanded = False
+ elif self.hover and not self.expanded:
+ self.expanded = True
+
+# if self.expanded is False:
+# self.expanded = True
# @on(SelectOverlay.blur)
# def on_select_overlay_blur(self, event: events.Blur) -> None:
diff --git a/nnll_10/package/voice_panel.py b/nnll_10/package/voice_panel.py
index 0a5f4e98..e36f704a 100644
--- a/nnll_10/package/voice_panel.py
+++ b/nnll_10/package/voice_panel.py
@@ -9,7 +9,7 @@
from textual_plotext import PlotextPlot
-# from nnll_01 import debug_monitor
+from nnll_01 import info_message as nfo # , debug_monitor
class VoicePanel(PlotextPlot): # (PlotWidget)
@@ -54,7 +54,7 @@ async def play_audio(self):
sd.play(self.audio, samplerate=self.sample_freq)
sd.wait()
except TypeError as error_log:
- print(error_log)
+ nfo(error_log)
@work(exclusive=True)
async def erase_audio(self):
diff --git a/nnll_13/__init__.py b/nnll_13/__init__.py
index 23255d57..3e3b64b3 100644
--- a/nnll_13/__init__.py
+++ b/nnll_13/__init__.py
@@ -10,7 +10,7 @@
from textual_plotext import PlotextPlot
-# from nnll_01 import debug_monitor
+from nnll_01 import info_message as nfo # , debug_monitor
class VoicePanel(PlotextPlot): # (PlotWidget)
@@ -60,7 +60,7 @@ async def play_audio(self):
sd.play(self.audio, samplerate=self.sample_freq)
sd.wait()
except TypeError as error_log:
- print(error_log)
+ nfo(error_log)
@work(exclusive=True)
async def erase_audio(self):
diff --git a/nnll_16/__init__.py b/nnll_16/__init__.py
index 79c37337..b8061fc2 100644
--- a/nnll_16/__init__.py
+++ b/nnll_16/__init__.py
@@ -12,7 +12,11 @@ def first_available(processor=None):
if not processor:
processor = reduce(
lambda acc, check: check() if acc == "cpu" else acc,
- [lambda: "cuda" if torch.cuda.is_available() else "cpu", lambda: "mps" if torch.backends.mps.is_available() else "cpu", lambda: "xpu" if torch.xpu.is_available() else "cpu"],
+ [
+ lambda: "cuda" if torch.cuda.is_available() else "cpu",
+ lambda: "mps" if torch.backends.mps.is_available() else "cpu",
+ lambda: "xpu" if torch.xpu.is_available() else "cpu",
+ ],
"cpu",
)
return torch.device(processor)
From 0b3413a5d380a70cc7cd74e64c132b97c3630a9a Mon Sep 17 00:00:00 2001
From: exdysa <91800957+exdysa@users.noreply.github.com>
Date: Tue, 22 Apr 2025 17:42:13 -0400
Subject: [PATCH 2/3] +extract zodiac
---
README.md | 4 +-
_version.py | 4 +-
nnll.egg-info/PKG-INFO | 16 +-
nnll.egg-info/SOURCES.txt | 18 +-
nnll.egg-info/entry_points.txt | 1 -
nnll.egg-info/requires.txt | 9 +-
nnll.egg-info/top_level.txt | 1 +
nnll_10/__init__.py | 138 ------------
nnll_10/package/__init__.py | 39 ----
nnll_10/package/__main__.py | 42 ----
nnll_10/package/carousel.py | 78 -------
nnll_10/package/combo.tcss | 354 ------------------------------
nnll_10/package/display_bar.py | 45 ----
nnll_10/package/input_tag.py | 24 --
nnll_10/package/main_screen.py | 325 ---------------------------
nnll_10/package/message_panel.py | 19 --
nnll_10/package/output_tag.py | 24 --
nnll_10/package/response_panel.py | 27 ---
nnll_10/package/selectah.py | 130 -----------
nnll_10/package/token_counters.py | 55 -----
nnll_10/package/voice_panel.py | 80 -------
nnll_13/__init__.py | 4 +-
nnll_21/__init__.py | 114 ++++++++++
pyproject.toml | 5 +-
tests/test_14_draw_graph.py | 108 ---------
tests/test_14_graph.py | 339 ----------------------------
26 files changed, 141 insertions(+), 1862 deletions(-)
delete mode 100644 nnll_10/__init__.py
delete mode 100644 nnll_10/package/__init__.py
delete mode 100644 nnll_10/package/__main__.py
delete mode 100644 nnll_10/package/carousel.py
delete mode 100644 nnll_10/package/combo.tcss
delete mode 100644 nnll_10/package/display_bar.py
delete mode 100644 nnll_10/package/input_tag.py
delete mode 100644 nnll_10/package/main_screen.py
delete mode 100644 nnll_10/package/message_panel.py
delete mode 100644 nnll_10/package/output_tag.py
delete mode 100644 nnll_10/package/response_panel.py
delete mode 100644 nnll_10/package/selectah.py
delete mode 100644 nnll_10/package/token_counters.py
delete mode 100644 nnll_10/package/voice_panel.py
create mode 100644 nnll_21/__init__.py
delete mode 100644 tests/test_14_draw_graph.py
delete mode 100644 tests/test_14_graph.py
diff --git a/README.md b/README.md
index 9235b316..a0e00e75 100644
--- a/README.md
+++ b/README.md
@@ -9,9 +9,9 @@
* Extracting and classifying metadata from images/models
* Consumer-grade GPU/CPU inference optimization
* Misc UX/UI Experimentation
-* 🧨Diffusers, 🤗Transformers, 🦙Ollama, 🍏MLX, 🌀DSPy, 🚅LiteLLM
+* 🧨Diffusers, 🤗Transformers, 🦙Ollama, 🍏MLX, 🌀DSPy, 🚅LiteLLM
+* :shipit:
-# :shipit:
[](https://github.com/darkshapes/nnll/actions/workflows/python-app.yml)


diff --git a/_version.py b/_version.py
index 2982e340..9ab9509d 100644
--- a/_version.py
+++ b/_version.py
@@ -17,5 +17,5 @@
__version_tuple__: VERSION_TUPLE
version_tuple: VERSION_TUPLE
-__version__ = version = '0.1.dev257+gee3125e.d20250412'
-__version_tuple__ = version_tuple = (0, 1, 'dev257', 'gee3125e.d20250412')
+__version__ = version = '0.1.dev272+g2ccb172.d20250422'
+__version_tuple__ = version_tuple = (0, 1, 'dev272', 'g2ccb172.d20250422')
diff --git a/nnll.egg-info/PKG-INFO b/nnll.egg-info/PKG-INFO
index dc4b0bbe..07850c2e 100644
--- a/nnll.egg-info/PKG-INFO
+++ b/nnll.egg-info/PKG-INFO
@@ -1,6 +1,6 @@
Metadata-Version: 2.4
Name: nnll
-Version: 0.1.dev257+gee3125e.d20250412
+Version: 0.1.dev272+g2ccb172.d20250422
Summary: Neural Network Link Library : A comprehensive modular toolkit for Diffusion and Large Language Model inference processes.
Author-email: darkshapes <91800957+exdysa@users.noreply.github.com>
License: #// SPDX-License-Identifier: blessing
@@ -16,8 +16,10 @@ Keywords: ML,AI,neural network,library,diffusion,LLM,torch
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
-Requires-Dist: structlog>=25.2.0
-Requires-Dist: viztracer>=1.0.3
+Requires-Dist: nnll_01
+Provides-Extra: nnll-01
+Requires-Dist: structlog>=25.2.0; extra == "nnll-01"
+Requires-Dist: viztracer>=1.0.3; extra == "nnll-01"
Provides-Extra: nnll-02
Requires-Dist: huggingface-hub>=0.29.3; extra == "nnll-02"
Requires-Dist: litellm>=1.65.0; extra == "nnll-02"
@@ -27,7 +29,6 @@ Requires-Dist: aiohttp<=3.11.13,>=3.9.5; extra == "nnll-03"
Requires-Dist: tqdm>=4.67.1; extra == "nnll-03"
Provides-Extra: nnll-04
Requires-Dist: gguf>=0.14.0; extra == "nnll-04"
-Requires-Dist: llama-cpp-python>=0.3.8; extra == "nnll-04"
Requires-Dist: safetensors>=0.5.3; extra == "nnll-04"
Provides-Extra: nnll-05
Requires-Dist: networkx>=3.4.2; extra == "nnll-05"
@@ -102,6 +103,7 @@ Requires-Dist: torchvision>=0.21.0; extra == "nnll-62"
Provides-Extra: nnll-64
Requires-Dist: pillow>=11.1.0; extra == "nnll-64"
Provides-Extra: all
+Requires-Dist: nnll[nnll_01]; extra == "all"
Requires-Dist: nnll[nnll_02]; extra == "all"
Requires-Dist: nnll[nnll_03]; extra == "all"
Requires-Dist: nnll[nnll_04]; extra == "all"
@@ -150,9 +152,9 @@ Dynamic: license-file
* Extracting and classifying metadata from images/models
* Consumer-grade GPU/CPU inference optimization
* Misc UX/UI Experimentation
-* 🧨Diffusers, 🤗Transformers, 🦙Ollama, 🍏MLX, 🌀DSPy, 🚅LiteLLM
+* 🧨Diffusers, 🤗Transformers, 🦙Ollama, 🍏MLX, 🌀DSPy, 🚅LiteLLM
+* :shipit:
-# :shipit:
[](https://github.com/darkshapes/nnll/actions/workflows/python-app.yml)


@@ -205,7 +207,7 @@ Dynamic: license-file
Some modules are full scripts and can be run from command line. These are written here:
`zodiac` - Experimental generative system
-`astra` - Experimental generative system
+`astra` - Live diagnostic console
`nnll-hash` - Hash the layer metadata from models within a directory and write out to console.
`nnll-parse` - Process metadata headers from a model file or directory of models and write out to individual JSON files.
`nnll-find` - Search a local directory of model layer files (HuggingFace🤗 index.json, JSON from `nnll-parse`)
diff --git a/nnll.egg-info/SOURCES.txt b/nnll.egg-info/SOURCES.txt
index 5957aad0..883c6628 100644
--- a/nnll.egg-info/SOURCES.txt
+++ b/nnll.egg-info/SOURCES.txt
@@ -4,7 +4,6 @@ README.md
_version.py
pyproject.toml
pytest.ini
-textual.log
uv.lock
.github/workflows/python-app.yml
nnll.egg-info/PKG-INFO
@@ -23,19 +22,6 @@ nnll_06/__init__.py
nnll_07/__init__.py
nnll_08/__init__.py
nnll_09/__init__.py
-nnll_10/__init__.py
-nnll_10/package/__init__.py
-nnll_10/package/__main__.py
-nnll_10/package/carousel.py
-nnll_10/package/combo.tcss
-nnll_10/package/display_bar.py
-nnll_10/package/input_tag.py
-nnll_10/package/main_screen.py
-nnll_10/package/message_panel.py
-nnll_10/package/output_tag.py
-nnll_10/package/response_panel.py
-nnll_10/package/token_counters.py
-nnll_10/package/voice_panel.py
nnll_11/__init__.py
nnll_12/__init__.py
nnll_12/__main__.py
@@ -50,6 +36,7 @@ nnll_17/__main__.py
nnll_18/__init__.py
nnll_19/__init__.py
nnll_20/__init__.py
+nnll_21/__init__.py
nnll_24/__init__.py
nnll_25/__init__.py
nnll_26/__init__.py
@@ -101,8 +88,7 @@ tests/test_05.py
tests/test_07.py
tests/test_08.py
tests/test_10_register_types.py
-tests/test_14_draw_graph.py
-tests/test_14_graph.py
+tests/test_10_weight.py
tests/test_15_register_types.py
tests/test_24.py
tests/test_25.py
diff --git a/nnll.egg-info/entry_points.txt b/nnll.egg-info/entry_points.txt
index e8e2a7b2..f4a3fbce 100644
--- a/nnll.egg-info/entry_points.txt
+++ b/nnll.egg-info/entry_points.txt
@@ -4,4 +4,3 @@ nnll-find = nnll_31:main
nnll-hash = nnll_17:main
nnll-index = nnll_43:main
nnll-parse = nnll_36:main
-zodiac = nnll_10.package.__init__:main
diff --git a/nnll.egg-info/requires.txt b/nnll.egg-info/requires.txt
index 0ccf8b8f..fedd3fdc 100644
--- a/nnll.egg-info/requires.txt
+++ b/nnll.egg-info/requires.txt
@@ -1,7 +1,7 @@
-structlog>=25.2.0
-viztracer>=1.0.3
+nnll_01
[all]
+nnll[nnll_01]
nnll[nnll_02]
nnll[nnll_03]
nnll[nnll_04]
@@ -50,7 +50,6 @@ tqdm>=4.67.1
[nnll-04]
gguf>=0.14.0
-llama-cpp-python>=0.3.8
safetensors>=0.5.3
[nnll-05]
@@ -146,3 +145,7 @@ torchvision>=0.21.0
[nnll-64]
pillow>=11.1.0
+
+[nnll_01]
+structlog>=25.2.0
+viztracer>=1.0.3
diff --git a/nnll.egg-info/top_level.txt b/nnll.egg-info/top_level.txt
index 94e3d920..15087d41 100644
--- a/nnll.egg-info/top_level.txt
+++ b/nnll.egg-info/top_level.txt
@@ -18,6 +18,7 @@ nnll_17
nnll_18
nnll_19
nnll_20
+nnll_21
nnll_24
nnll_25
nnll_26
diff --git a/nnll_10/__init__.py b/nnll_10/__init__.py
deleted file mode 100644
index ae4e8a0c..00000000
--- a/nnll_10/__init__.py
+++ /dev/null
@@ -1,138 +0,0 @@
-# # #
-# # #
-
-# pylint: disable=import-outside-toplevel
-
-
-import sys
-import os
-
-
-# pylint:disable=import-outside-toplevel
-sys.path.append(os.getcwd())
-
-import networkx as nx
-from nnll_01 import debug_monitor, info_message as nfo, debug_message as dbug
-
-# from nnll_15.constants import ModeType
-from nnll_15 import RegistryEntry
-
-
-class IntentProcessor:
- intent_graph: nx.Graph = None
- coord_path: list[str] = None
- ckpts: list[dict[RegistryEntry]] = None
- models: list[tuple[str]] = None
- # additional_model_names: dict = None
-
- def __init__(self):
- """
- Create instance of graph processor & initialize objectives for tracing paths
- """
-
- @debug_monitor
- def calc_graph(self) -> None:
- """Generate graph of coordinate pairs from valid conversions\n
- Model libraries are auto-detected from cache loading\n
- :param nx_graph: Preassembled graph of models to label
- :return: Graph modeling all current ML/AI tasks appended with model data"""
- from nnll_15 import VALID_CONVERSIONS, from_cache
-
- self.intent_graph = nx.MultiDiGraph()
- self.intent_graph.add_nodes_from(VALID_CONVERSIONS)
- registry_entries = from_cache()
- if registry_entries:
- for model in registry_entries:
- self.intent_graph.add_edges_from(model.available_tasks, entry=model, weight=1.0)
- else:
- nfo("Registry error, graph attributes not applied")
- return self.intent_graph
-
- @debug_monitor
- def has_graph(self) -> None:
- """Verify the graph has been created"""
- try:
- assert self.intent_graph is not None
- except AssertionError as error_log:
- dbug(error_log)
- return False
- return True
-
- @debug_monitor
- def has_path(self) -> None:
- """Verify the path has been created"""
- try:
- assert self.coord_path is not None
- except AssertionError as error_log:
- dbug(error_log)
- return False
- return True
-
- @debug_monitor
- def has_ckpt(self) -> None:
- """Verify the model checkpoints are known"""
- try:
- assert self.ckpts is not None
- except AssertionError as error_log:
- dbug(error_log)
- return False
- return True
-
- @debug_monitor
- def set_path(self, mode_in: str, mode_out: str) -> None:
- """
- Find a valid path from current state (mode_in) to designated state (mode_out)\n
- :param mode_in: Input prompt type or starting state/states
- :param mode_out: The user-selected ending-state
- :return: An iterator for the edges forming a way towards the mode out, or Note
- """
-
- self.has_graph()
- if nx.has_path(self.intent_graph, mode_in, mode_out): # Ensure path exists (otherwise 'bidirectional' may loop infinitely)
- if mode_in == mode_out and mode_in != "text":
- orig_mode_out = mode_out # Solve case of non-text self-loop edge being incomplete transformation
- mode_out = "text"
- self.coord_path = nx.bidirectional_shortest_path(self.intent_graph, mode_in, mode_out)
- self.coord_path.append(orig_mode_out)
- else:
- self.coord_path = nx.bidirectional_shortest_path(self.intent_graph, mode_in, mode_out)
- if len(self.coord_path) == 1:
- self.coord_path.append(mode_out) # this behaviour likely to change in future
-
- @debug_monitor
- def set_ckpts(self) -> None:
- from nnll_05 import pull_path_entries
-
- self.has_graph()
- self.has_path()
- self.ckpts = pull_path_entries(self.intent_graph, self.coord_path)
- self.models = []
- nfo(self.ckpts)
- self.ckpts = sorted(self.ckpts, key=lambda x: x["weight"])
- nfo([x["weight"] for x in self.ckpts])
- for registry in self.ckpts:
- model = registry["entry"].model
- weight = registry.get("weight")
- if weight != 1.0:
- self.models.insert(0, (f"*{os.path.basename(model)}", model))
- nfo("adjusted model :", f"*{os.path.basename(model)}", weight)
- else:
- self.models.append((os.path.basename(model), model))
- # nfo("model : ", model, weight)
- self.models = sorted(self.models, key=lambda x: "*" in x)
-
- @debug_monitor
- def edit_weight(self, selection: str, mode_in: str, mode_out: str) -> None:
- """Determine entry edge, determine index, then adjust weight"""
- reg_entries = [nbrdict for n, nbrdict in self.intent_graph.adjacency()]
- index = [x for x in reg_entries[0][mode_out] if selection in reg_entries[0][mode_out][x].get("entry").model]
- model = reg_entries[0][mode_out][index[0]].get("entry").model
- weight = reg_entries[0][mode_out][index[0]].get("weight")
- nfo(model, index, weight)
- if weight < 1.0:
- self.intent_graph[mode_in][mode_out][index[0]]["weight"] = weight + 0.1
- else:
- self.intent_graph[mode_in][mode_out][index[0]]["weight"] = weight - 0.1
- nfo("Weight changed for: ", self.intent_graph[mode_in][mode_out][index[0]]["entry"].model, f"model # {index[0]}")
- self.set_ckpts()
- dbug("Confirm :", self.intent_graph[mode_in][mode_out])
diff --git a/nnll_10/package/__init__.py b/nnll_10/package/__init__.py
deleted file mode 100644
index b766124d..00000000
--- a/nnll_10/package/__init__.py
+++ /dev/null
@@ -1,39 +0,0 @@
-import sys
-import os
-
-# pylint:disable=import-outside-toplevel
-sys.path.append(os.getcwd())
-
-
-def main():
- """Launch textual UI"""
- from nnll_10.package.__main__ import Combo
- from nnll_01 import info_message as nfo
-
- trace = False
- if sys.argv[0] == "-t" or sys.argv[0] == "--trace":
- import litellm
- from viztracer import VizTracer
-
- litellm.suppress_debug_info = False
- trace = True
- tracer = VizTracer()
- tracer.start()
-
- app = Combo(ansi_color=False)
-
- nfo("Launching...")
- app.run()
- if trace:
- from datetime import datetime
-
- os.makedirs("log", exist_ok=True)
- assembled_path = os.path.join("log", f".nnll{datetime.now().strftime('%Y%m%d')}_trace.json")
- tracer.stop()
- tracer.save(output_file=assembled_path) # also takes output_file as an optional argument
-
-
-if __name__ == "__main__":
- # import asyncio
- main()
- # asyncio.run(main())
diff --git a/nnll_10/package/__main__.py b/nnll_10/package/__main__.py
deleted file mode 100644
index 037794b7..00000000
--- a/nnll_10/package/__main__.py
+++ /dev/null
@@ -1,42 +0,0 @@
-# # #
-# # #
-
-# pylint: disable=missing-module-docstring, disable=missing-class-docstring
-
-from textual import work, events, on
-from textual.app import App
-from textual.binding import Binding
-from textual.reactive import reactive
-
-# from nnll_01 import info_message as nfo
-from nnll_10.package.main_screen import Fold # pylint: disable=import-error
-
-# from theme import fluoresce_theme
-
-
-class Combo(App):
- SCREENS = {"fold": Fold}
- CSS_PATH = "combo.tcss"
- BINDINGS = [Binding("escape", "safe_exit", "◼︎ / ⏏︎")] # Cancel response
-
- safety: reactive[int] = reactive(1)
-
- def on_mount(self) -> None:
- """Draw screen"""
- self.push_screen("fold")
- self.scroll_sensitivity_y = 1
- self.supports_smooth_scrolling = True
- self.theme = "flexoki"
-
- @work(exit_on_error=True)
- @on(events.Key)
- async def _on_key(self, event: events.Key):
- """Window for triggering key bindings"""
- if event.key not in ["escape", "ctrl+left_square_brace"]:
- self.safety += 1
- else:
- self.safety -= 1
- if self.safety < 0:
- event.prevent_default()
-
- await self.app.action_quit()
diff --git a/nnll_10/package/carousel.py b/nnll_10/package/carousel.py
deleted file mode 100644
index 7a5f4e7c..00000000
--- a/nnll_10/package/carousel.py
+++ /dev/null
@@ -1,78 +0,0 @@
-# # #
-# # #
-
-"""Selection Function"""
-
-from textual.widgets import DataTable
-from textual.screen import Screen
-from textual.reactive import reactive
-
-from nnll_01 import debug_monitor, info_message as nfo # debug_message as dbug,
-
-
-class Carousel(DataTable):
- """Revolving text-line component based on default DataTable widget class"""
-
- nx_graph: dict
- content_cell: reactive[int] = reactive(0)
-
- up = "[@click='scroll_button(1)']▲[/]"
- dwn = "[@click='scroll_button']▼[/]"
- current_cell = "text"
- current_row = 0
- y_coord = 1
- scroll_counter = 10
-
- def on_mount(self) -> None:
- self.show_header = False
- self.cursor_type = "cell"
-
- @debug_monitor
- def emulate_scroll_down(self, interval: int = 1) -> str:
- """Trigger datatable cursor movement using fractional sensitivity
- :param ceiling: Total entry count of the table *column*
- :return: The datata in the table *row*
- """
-
- if (self.row_count - 1) >= (self.current_row + interval):
- if self.y_coord < self.scroll_counter:
- self.y_coord += interval
- else:
- self.y_coord = interval
- self.current_row += interval
- self.move_cursor(row=self.current_row, column=1)
- self.current_cell = self.get_cell_at((self.current_row, 1))
- return self.current_cell
-
- @debug_monitor
- def emulate_scroll_up(self, interval: int = 1) -> str:
- """Trigger datatable cursor movement using fractional sensitivity
- :param ceiling: Total entry count of the table *column*
- :return: The datata in the table *row*
- """
-
- if 0 <= self.current_row - interval:
- if self.y_coord >= 1:
- self.y_coord -= interval
- else:
- self.y_coord = self.scroll_counter
- self.current_row -= interval
- self.move_cursor(row=self.current_row, column=1)
- self.current_cell = self.get_cell_at((self.current_row, 1))
- return self.current_cell
-
- @debug_monitor
- def action_scroll_button(self, up: bool = False) -> None:
- """Manually trigger scrolling and panel switching
- :param up: Scroll direction, defaults to False
- """
- if up:
- self.current_cell = self.emulate_scroll_up(interval=self.y_coord + 1)
- if self.id == "input_tag":
- self.query_ancestor(Screen).foldr["ps"].current = self.query_ancestor(Screen).input_map[self.current_cell]
- self.query_ancestor(Screen).ready_tx(io_only=True)
- else:
- self.current_cell = self.emulate_scroll_down(interval=self.scroll_counter - self.y_coord - 1)
- if self.id == "input_tag":
- self.query_ancestor(Screen).foldr["ps"].current = self.query_ancestor(Screen).input_map[self.current_cell]
- self.query_ancestor(Screen).ready_tx(io_only=True)
diff --git a/nnll_10/package/combo.tcss b/nnll_10/package/combo.tcss
deleted file mode 100644
index 7cd3dba1..00000000
--- a/nnll_10/package/combo.tcss
+++ /dev/null
@@ -1,354 +0,0 @@
-# # # #
-# # # #
-
-
-
-
-$min-height: 3;
-# #dedede;
-# #000000;
-# #1f1f1f; #333333;
-# #0F0F0F; #888888;
-# #48D1CC; #8c92ac;
-# #EF8E35 #eb4983;
-# #F2C641;# #9a80cF;
- # rgb(28, 26, 26)
-# rgb(31, 0, 65)
-# surfaces
-$negative-space: $background-darken-3;
-$main-background: $background;
-$top-surface: $surface;
-$focus-surface: $foreground;
-
-# text
-$sunken-text: $background-lighten-3;
-$raised-text: $foreground-darken-3; # $secondary;
-$hover-focus: $foreground;
-
-
-# layout
-$layout-type: grid;
-$centre-frame-margin: 0 1 0 1;
-$vertical-grid: 1 3;
-$horizontal-grid: 3 1;
-$proportions: 0.7fr 4.5fr 0.7fr;
-$vertical-proportions: 0.6fr 5fr 0.55fr;
-$grid-fraction: 1fr;
-$invisible-scrollbar: 0 0;
-$margin-size: 0;
-
-# alignment
-$title-align: left;
-$border-shape: round;
-$hatch-border: horizontal;
-$hatch-align: left;
-
-# color
-$message-panel-subtitle: $raised-text;
-$selection-bg: $foreground;
-$selection-fg: $background;
-
-
-
-#footer {
- background: $main-background;
-}
-
-.app-grid-vertical { # mobile layout
- layout: $layout-type;
- grid-size: $vertical-grid;
- grid-rows: $vertical-proportions;
- grid-columns: $grid-fraction;
-}
-
-.app-grid-horizontal { # laptop layout
- layout: $layout-type;
- grid-size: $horizontal-grid;
- grid-columns: $proportions;
- grid-rows: $grid-fraction;
- min-height: $min-height;
-}
-
-#centre-frame {
- layout: grid;
- grid-size: $vertical-grid;
- grid-rows: 3fr 1 3fr;
- margin: $centre-frame-margin;
- keyline: none;
-
-}
-#seam {
- layout: grid;
- grid-size: 2 1;
- grid-columns: 60fr 30fr;
- keyline: none;
- border: none;
- background:$negative-space 7%;
- height: 1;
- text-wrap: nowrap;
-}
-#selectah {
- color: $sunken-text;
- height: 2;
- margin: 0 1;
- padding: -1 0;
- overflow: hidden;
- text-align: end;
- width: 100%;
- layer: above;
- text-overflow: ellipsis;
- &:focus {
- background: white 10%;
- }
- &.active {
- Static#label {
- text-overflow:ellipsis;
- overflow-x: hidden;
- &:blur {
- color: $accent;
- text-align: end;
- }
- &:focus {
- color: $accent;
- }
- &:hover {
- color: $accent;
- }
- }
- }
- &.-expanded {
-
- color: $raised-text;
- text-align: end;
- content-align: right top;
- background:$negative-space 7%;
- overflow-x: hidden;
- &.-selected {
- background: $selection-bg;
-
- }
- }
- Static#label {
- min-width: 10;
- text-overflow:ellipsis;
- overflow: hidden;
- &:blur {
- color: $sunken-text;
- text-align: end;
- }
- &:focus {
- color: $raised-text;
- }
- &:hover {
- color: $foreground-darken-1;
- }
- &.-selected {
- background: $selection-bg;
- }
- }
-
-
- SelectCurrent {
- background:$negative-space 7%;
- border: vkey $focus-surface;
- color: $raised-text;
- overflow: hidden;
- text-overflow: ellipsis;
- border: vkey $surface;
-
- &:blur {
- border: vkey $surface;
- }
- &:hover {
- color: $raised-text;
- }
- &:focus {
- color: $background-lighten-3;
- }
- .arrow {
- color: $sunken-text;
- }
- }
- SelectOverlay {
- text-overflow:ellipsis;
- border: vkey $negative-space 7%;
- overflow-x: hidden;
- overflow-y: scroll;
- text-align: end;
- color: $sunken-text;
- overlay: screen;
- scrollbar-size: 0 1;
- scrollbar-background: $negative-space 7%;
- scrollbar-background-active: $negative-space 7%;
- scrollbar-color: $panel;
- scrollbar-color-active: $focus-surface;
- scrollbar-color-hover: $background-lighten-3;
- background: $negative-space 7%;
- &.-selected {
- overflow: hidden;
- background: $selection-bg;
- border: vkey $background-lighten-3;
- }
- & > .option-list--option-selected {
- overflow: hidden;
- background: $selection-bg;
- color: $selection-fg;
- }
- & > .option-list--option {
- overflow: hidden;
- }
- & > .option-list--option-highlighted {
- overflow: hidden;
- background: $accent 75%;
- text-style: none;
- }
- }
-}
-#top-frame, #bottom-frame, #left-frame, #right-frame {
- background: $negative-space;
-}
-
-#bottom-frame:focus-within {
- border: $border-shape $focus-surface; # orange highlight
-
-}
-
-SidebarLeft, SidebarRight {
- margin-left: $margin-size;
- margin-right: $margin-size;
- background: $negative-space;
-}
-
-#message_panel > .textarea--fixed-cursor {
- color: transparent;
-
-}
-
-#message_panel, #response_panel {
- background: $top-surface;
- border: $border-shape $main-background;
- border-subtitle-align: $title-align;
- border-subtitle-color: $background-lighten-3;
- scrollbar-size: $invisible-scrollbar;
- .text-area--selection {
- background: $selection-bg;
- color: $selection-fg;
- }
- &:hover {
- border-subtitle-color: $foreground-darken-1;
- }
- &:focus {
- border: $border-shape $focus-surface;
- border-subtitle-color: $foreground;
- }
-
-
-}
-
-#response_panel {
- width: 100%;
- margin: 0 0;
- height: 100%;
- border: round $main-background;
- hatch: $hatch-align $main-background;
- &:focus-within {
- border: round $focus-surface;
- }
-}
-#response_panel, #output_tag, {
- scrollbar-size: $invisible-scrollbar;
-
-}
-
-#display_bar {
- color: $panel-lighten-1;
- margin: 0 0;
- padding: 0 0;
- height: 1;
- min-width: 10;
- content-align: left top;
- align: left top;
- text-align: start;
- width: 100%;
- layer: above;
- overflow: hidden;
- scrollbar-size: $invisible-scrollbar;
- background: $negative-space 7%;
- &:blur {
- color: $panel-lighten-1;
- }
- &:hover {
- color: $panel-lighten-1;
- }
- &:focus {
- color: $sunken-text;
- }
-}
-
-#output_tag {
- margin: 0 2;
-}
-
-#output_tag, #input_tag {
- color: $background-lighten-3;
- width: auto;
- hatch: $hatch-border $main-background;
- border: none;
- overflow: hidden;
- height: 1;
- layer: above;
- background: $top-surface;
- background-tint: 0%;
- .datatable--cursor {
- color: $background-lighten-3;
- background: $top-surface;
- }
- &:hover {
- .datatable--cursor {
- color: $foreground-darken-1;
- background: $top-surface;
- }
- }
- &:focus {
- .datatable--cursor {
- color: $foreground;
- text-style: none;
- background: $top-surface;
- }
- }
-}
-
-#input_tag {
- margin-bottom: 0;
- margin-left: 2;
- padding: 0;
- border: none;
- background: $top-surface;
-}
-
-#responsive_input{
- align: left bottom;
-
-}
-#panel_swap {
- align: center top;
- # scrollbar-gutter: stable;
- scrollbar-size: 0 0;
-}
-#voice_panel {
- background: $top-surface;
- box-sizing: content-box;
- overflow: hidden;
- padding: 0;
- margin: 0;
- scrollbar-size: 0 0;
- # scrollbar-gutter: stable;
- color: $accent;
- outline: round $background; # round $top-surface;
- # border: none;
- &:focus {
- outline: round $focus-surface;
- }
-
-}
-
diff --git a/nnll_10/package/display_bar.py b/nnll_10/package/display_bar.py
deleted file mode 100644
index 9ff7af40..00000000
--- a/nnll_10/package/display_bar.py
+++ /dev/null
@@ -1,45 +0,0 @@
-# # #
-# # #
-
-from typing import Callable
-from textual import work
-from textual.reactive import reactive
-from textual.screen import Screen
-from textual.widgets import DataTable
-from nnll_10.package.token_counters import tk_count
-
-
-class DisplayBar(DataTable):
- """Thin instant user feedback display"""
-
- UNIT1 = "chr / " # Display Bar Units
- UNIT2 = "tkn / "
- UNIT3 = "″"
- unit_labels = [UNIT1, UNIT2, UNIT3]
- duration: reactive[float] = reactive(0.0, recompose=True)
-
- def on_mount(self):
- rows: list[tuple] = [
- (0, 0, 0, 0),
- (f" 0{self.UNIT1}", f"0{self.UNIT2}", f"0.0{self.UNIT3}", " "),
- ]
- self.add_columns(*rows[0])
- self.add_rows(rows[1:])
- self.show_header = False
- self.show_row_labels = False
- self.cursor_type = None
-
- @work(exclusive=True)
- async def calculate_tokens(self, tokenizer_model: str, message: str):
- """Live display of tokens and characters"""
- token_count = await tk_count(tokenizer_model, message)
- character_count = len(message)
- self.update_cell_at((0, 0), f" {character_count}{self.unit_labels[0]}")
- self.update_cell_at((0, 1), f"{token_count}{self.unit_labels[1]}")
- self.update_cell_at((0, 2), f"{self.duration}{self.unit_labels[2]}")
-
- @work(exclusive=True)
- async def calculate_audio(self, duration):
- """Live display of sound recording length"""
- self.duration = duration if duration > 0.0 else 0.0
- self.update_cell_at((0, 2), f"{self.duration}{self.unit_labels[2]}", update_width=True)
diff --git a/nnll_10/package/input_tag.py b/nnll_10/package/input_tag.py
deleted file mode 100644
index b5680a0c..00000000
--- a/nnll_10/package/input_tag.py
+++ /dev/null
@@ -1,24 +0,0 @@
-# # #
-# # #
-
-from textual.reactive import reactive
-from textual.screen import Screen
-
-from nnll_10.package.carousel import Carousel
-
-
-class InputTag(Carousel):
- """Populate Input Types List"""
-
- target_options: reactive[set] = reactive({})
-
- def on_mount(self):
- scrn = self.query_ancestor(Screen)
- if scrn.int_proc.has_graph():
- graph_edges = scrn.int_proc.intent_graph.edges
- # note: Length sort on target_options kinda poor way to get text on top, works for the moment tho
- self.target_options = sorted({edge[1] for edge in graph_edges}, key=len)
- self.add_columns("0", "1", "2")
- self.add_rows([self.up.strip(), row.strip(), self.dwn.strip()] for row in self.target_options)
- self.cursor_foreground_priority = "css"
- self.cursor_background_priority = "css"
diff --git a/nnll_10/package/main_screen.py b/nnll_10/package/main_screen.py
deleted file mode 100644
index dbbd1ff3..00000000
--- a/nnll_10/package/main_screen.py
+++ /dev/null
@@ -1,325 +0,0 @@
-# # #
-# # #
-
-"""Auto-Orienting Split screen"""
-
-import os
-from collections import defaultdict
-from typing import Callable # , Any
-from textual import events, on, work
-from textual.app import ComposeResult
-from textual.binding import Binding
-from textual.containers import Container
-from textual.message import Message
-from textual.reactive import reactive
-from textual.screen import Screen
-
-# from textual.widget import Widget
-from textual.widgets import Static, ContentSwitcher # , DataTable
-from textual.widget import Widget
-
-
-from nnll_01 import debug_monitor, info_message as nfo, debug_message as dbug
-from nnll_10.package.message_panel import MessagePanel
-from nnll_10 import IntentProcessor
-from nnll_10.package.input_tag import InputTag
-from nnll_10.package.output_tag import OutputTag
-from nnll_10.package.selectah import Selectah
-
-
-class Fold(Screen[bool]):
- """Orienting display Horizontal
- Main interface container"""
-
- DEFAULT_CSS = """Screen { min-height: 5; }"""
-
- BINDINGS = [
- Binding("bk", "alternate_panel('text',0)", "⌨️"), # Return to text input panel
- Binding("alt+bk", "clear_input", "del"), # Empty focused prompt panel
- Binding("ent", "start_recording", "◉", priority=True), # Start audio prompt
- Binding("space", "play", "▶︎", priority=True), # Listen to prompt audio
- Binding("escape", "cancel_generation", "◼︎ / ⏏︎"), # Cancel response
- Binding("`", "loop_sender", "✎", priority=True), # Send to LLM
- ]
-
- ui: dict = defaultdict(dict)
- int_proc: reactive[Callable] = reactive(None)
- # model_names = [("model", 0), ("x", 0)]
- tx_data: dict = {}
- counter = 0
- hover_name: reactive[str] = reactive("")
- input_map: dict = {
- "text": "message_panel",
- "image": "message_panel",
- "speech": "voice_panel",
- }
-
- def compose(self) -> ComposeResult:
- """Textual API widget constructor, build graph, apply custom widget classes"""
- from textual.containers import Horizontal
- from textual.widgets import Footer
- from nnll_10.package.display_bar import DisplayBar
-
- from nnll_10.package.response_panel import ResponsePanel
- from nnll_10.package.voice_panel import VoicePanel
-
- self.int_proc = IntentProcessor()
- self.int_proc.calc_graph()
- self.ready_tx(mode_in="text", mode_out="text")
- yield Footer(id="footer")
- with Horizontal(id="app-grid", classes="app-grid-horizontal"):
- yield ResponsiveLeftTop(id="left-frame")
- with Container(id="centre-frame"): # 3:1:3 ratio
- with Container(id="responsive_input"): # 3:
- with ContentSwitcher(id="panel_swap", initial="message_panel"):
- yield MessagePanel("""""", id="message_panel", max_checkpoints=100)
- yield VoicePanel(id="voice_panel")
- yield InputTag(id="input_tag", classes="input_tag")
- with Horizontal(id="seam"):
- yield DisplayBar(id="display_bar") # 1:
- yield Selectah(
- id="selectah",
- classes="selectah",
- prompt=os.path.basename(next(iter(self.int_proc.models))[0]),
- options=self.int_proc.models,
- type_to_search=True,
- )
- with Container(id="responsive_display"): #
- yield ResponsePanel("\n", id="response_panel", language="markdown")
- yield OutputTag(id="output_tag", classes="output_tag")
- yield ResponsiveRightBottom(id="right-frame")
-
- @work(exclusive=True)
- async def on_mount(self) -> None:
- """Textual API, Query all available widgets at once"""
- self.ui["db"] = self.query_one("#display_bar")
- self.ui["it"] = self.query_one("#input_tag")
- self.ui["mp"] = self.query_one("#message_panel")
- self.ui["ot"] = self.query_one("#output_tag") # type : ignore
- self.ui["ps"] = self.query_one(ContentSwitcher)
- self.ui["rd"] = self.query_one("#responsive_display")
- self.ui["rp"] = self.query_one("#response_panel")
- self.ui["vp"] = self.query_one("#voice_panel")
- self.ui["sl"] = self.query_one("#selectah")
- self.ready_tx()
- self.walk_intent()
- # id_name = self.input_tag.highlight_link_id
-
- @work(exit_on_error=False)
- async def on_resize(self, event=events.Resize) -> None:
- """Textual API, scale/orientation screen responsivity"""
- if self.is_ui_ready():
- display = self.query_one("#app-grid")
- width = event.container_size.width
- height = event.container_size.height
- if width / 2 >= height: # Screen is wide
- display.set_classes("app-grid-horizontal")
- elif width / 2 < height: # Screen is tall
- display.set_classes("app-grid-vertical")
-
- @debug_monitor
- def is_ui_ready(self):
- """Confirm UI is active"""
- try:
- assert hasattr(self.ui["sl"], "is_mounted")
- except AssertionError as error_log:
- dbug(error_log)
- return False
- return True
-
- @on(events.Focus)
- async def on_focus(self, event=events.Focus):
- if event.control.id == "selectah":
- self.ready_tx()
- self.walk_intent()
- self.ui["sl"].prompt = next(iter(self.int_proc.models))[0]
-
- @work(exclusive=True)
- async def _on_key(self, event: events.Key) -> None:
- """Textual API event trigger, Suppress/augment default key actions to trigger keybindings"""
- if (hasattr(event, "character") and event.character == "`") or event.key == "grave_accent":
- event.prevent_default()
- self.ready_tx(io_only=False)
- if self.int_proc.has_graph() and self.int_proc.has_path():
- self.walk_intent(send=True)
- elif event.key == "escape" and "active" in self.ui["sl"].classes:
- Message.stop(True)
- self.stop_gen()
- elif (hasattr(event, "character") and event.character == "\r") or event.key == "enter":
- self.flip_panel("voice_panel", 1)
- self.ui["vp"].record_audio()
- self.audio_to_token()
- elif (hasattr(event, "character") and event.character == " ") or event.key == "space":
- self.flip_panel("voice_panel", 1)
- self.ui["vp"].play_audio()
- elif (event.name) == "ctrl_w" or event.key == "ctrl+w":
- self.clear_input()
- elif not self.ui["rp"].has_focus and ((hasattr(event, "character") and event.character == "\x7f") or event.key == "backspace"):
- self.flip_panel("message_panel", 0)
-
- @debug_monitor
- def _on_mouse_scroll_down(self, event: events.MouseScrollUp) -> None:
- """Textual API event trigger, Translate scroll events into datatable cursor movement
- Trigger scroll at 1/10th intensity when menu has focus
- :param event: Event data for the trigger"""
-
- scroll_delta = [self.ui["it"].current_cell, self.ui["ot"].current_cell]
- if self.ui["rd"].has_focus_within != self.ui["rp"].has_focus and not self.ui["sl"].has_focus:
- event.prevent_default()
- self.ui["ot"].emulate_scroll_down()
- elif self.ui["it"].has_focus:
- event.prevent_default()
- mode_in_name = self.ui["it"].emulate_scroll_down()
- self.ui["ps"].current = self.input_map.get(mode_in_name)
- if scroll_delta != [self.ui["it"].current_cell, self.ui["ot"].current_cell]:
- self.ready_tx()
- self.walk_intent()
- self.ui["sl"].mode_in = self.ui["it"].current_cell
- self.ui["sl"].mode_out = self.ui["ot"].current_cell
- self.ui["sl"].prompt = next(iter(self.int_proc.models))[0]
-
- @debug_monitor
- def _on_mouse_scroll_up(self, event: events.MouseScrollUp) -> None:
- """Textual API event trigger,Translate scroll events into datatable cursor movement
- Trigger scroll at 1/10th intensity when menu has focus
- :param event: Event data for the trigger"""
-
- scroll_delta = [self.ui["it"].current_cell, self.ui["ot"].current_cell]
- if self.ui["rd"].has_focus_within != self.ui["rp"].has_focus and not self.ui["sl"].has_focus:
- event.prevent_default()
- self.ui["ot"].emulate_scroll_up()
- elif self.ui["it"].has_focus:
- event.prevent_default()
- mode_name = self.ui["it"].emulate_scroll_up()
- self.ui["ps"].current = self.input_map.get(mode_name)
- if scroll_delta != [self.ui["it"].current_cell, self.ui["ot"].current_cell]:
- self.ready_tx()
- self.walk_intent()
- self.ui["sl"].mode_in = self.ui["it"].current_cell
- self.ui["sl"].mode_out = self.ui["ot"].current_cell
- self.ui["sl"].prompt = next(iter(self.int_proc.models))[0]
-
- # @work(exclusive=True)
- @on(MessagePanel.Changed, "#message_panel")
- async def txt_to_token(self) -> None:
- """Transmit info to token calculation"""
- message = self.ui["mp"].text
- next_model = next(iter(self.int_proc.models))[1]
- self.ui["db"].calculate_tokens(next_model, message=message)
-
- @work(exclusive=True)
- async def audio_to_token(self) -> None:
- """Transmit audio to sample length"""
- duration = self.ui["vp"].calculate_sample_length()
- self.ui["db"].calculate_audio(duration)
-
- # @work(exclusive=True)
- def ready_tx(self, io_only: bool = True, mode_in: str = None, mode_out: str = None) -> None:
- """Retrieve graph"""
- if not mode_in:
- mode_in = self.ui["it"].get_cell_at((self.ui["it"].current_row, 1))
- if not mode_out:
- mode_out = self.ui["ot"].get_cell_at((self.ui["ot"].current_row, 1))
- self.int_proc.set_path(mode_in=mode_in, mode_out=mode_out)
- self.int_proc.set_ckpts()
- if not io_only:
- self.tx_data = {
- "text": self.ui["mp"].text,
- "audio": self.ui["vp"].audio,
- # "attachment": self.message_panel.file # drag and drop from external window
- # "image": self.image_panel.image # active video feed / screenshot / import file
- }
-
- # @work(exclusive=True)
- def walk_intent(self, send=False) -> None:
- """Provided the coordinates in the intent processor, follow the list of in and out methods"""
- coords = self.int_proc.coord_path
- if not coords:
- coords = ["text", "text"]
- hops = len(coords) - 1
- for i in range(hops):
- if i + 1 < hops:
- if send:
- self.tx_data = self.send_tx(last_hop=False)
- self.ready_tx(mode_in=coords[i + 1], mode_out=coords[i + 2])
- else:
- old_models = self.int_proc.models if self.int_proc.models else []
- dbug(old_models, "walk_intent")
- self.ready_tx(mode_in=coords[i + 1], mode_out=coords[i + 2])
- self.int_proc.models.extend(old_models)
- self.model_names = self.int_proc.models
- dbug(self.int_proc.models)
-
- elif send:
- self.send_tx()
-
- @work(exclusive=True)
- async def send_tx(self, last_hop=True) -> None:
- """Transfer path and promptmedia to generative processing endpoint"""
-
- from nnll_11 import ChatMachineWithMemory, QASignature
-
- ckpt = self.ui["sl"].selection
- if ckpt is None:
- ckpt = next(iter(self.int_proc.ckpts)).get("entry")
- chat = ChatMachineWithMemory(sig=QASignature)
- self.ui["rp"].on_text_area_changed()
- self.ui["rp"].insert("\n---\n")
- self.ui["sl"].add_class("active")
- if last_hop:
- nfo(ckpt)
- async for chunk in chat.forward(
- tx_data=self.tx_data,
- model=ckpt.model,
- library=ckpt.library,
- max_workers=8,
- ):
- if chunk is not None:
- self.ui["rp"].insert(chunk)
- self.ui["sl"].set_classes(["selectah"])
- else:
- self.tx_data = chat.forward(
- tx_data=self.tx_data,
- model=ckpt.model,
- library=ckpt.library,
- max_workers=8,
- )
-
- @work(exclusive=True)
- async def stop_gen(self) -> None:
- """Cancel the inference processing of a model"""
- self.ui["rp"].workers.cancel_all()
- self.ui["ot"].set_classes("output_tag")
-
- @work(exclusive=True)
- async def clear_input(self) -> None:
- """Clear the input on the focused panel"""
- if self.ui["vp"].has_focus:
- self.ui["vp"].erase_audio()
- self.audio_to_token()
- elif self.ui["mp"].has_focus:
- self.ui["mp"].erase_message()
-
- @work(exclusive=True)
- async def flip_panel(self, id_name: str, y_coord: int) -> None:
- """Switch between text input and audio input
- :param id_name: The panel to switch to
- :param y_coordinate: _description_
- """
- self.ui["it"].scroll_to(x=1, y=y_coord, force=True, immediate=True, on_complete=self.ui["it"].refresh)
- self.ui["ps"].current = id_name
-
-
-class ResponsiveLeftTop(Container):
- """Sidebar Left/Top"""
-
- def compose(self) -> ComposeResult:
- yield Static()
-
-
-class ResponsiveRightBottom(Container):
- """Sidebar Right/Bottom"""
-
- def compose(self) -> ComposeResult:
- yield Static()
- yield Static()
diff --git a/nnll_10/package/message_panel.py b/nnll_10/package/message_panel.py
deleted file mode 100644
index f248acdb..00000000
--- a/nnll_10/package/message_panel.py
+++ /dev/null
@@ -1,19 +0,0 @@
-# #
-# #
-from textual import work
-from textual.widgets import TextArea
-
-
-# from nnll_01 import debug_monitor
-
-
-class MessagePanel(TextArea):
- """User entry field"""
-
- def on_mount(self):
- self.cursor_blink = True
-
- @work(exclusive=True)
- async def erase_message(self):
- """Empty panel contents"""
- self.clear()
diff --git a/nnll_10/package/output_tag.py b/nnll_10/package/output_tag.py
deleted file mode 100644
index 76417573..00000000
--- a/nnll_10/package/output_tag.py
+++ /dev/null
@@ -1,24 +0,0 @@
-# # #
-# # #
-
-from textual.reactive import reactive
-from textual.screen import Screen
-
-from nnll_10.package.carousel import Carousel
-
-
-class OutputTag(Carousel):
- """Populate Output types list"""
-
- target_options: reactive[set] = reactive({})
-
- def on_mount(self):
- scrn = self.query_ancestor(Screen)
- if scrn.int_proc.has_graph():
- graph_edges = scrn.int_proc.intent_graph.edges
-
- self.target_options = sorted({edge[0] for edge in graph_edges}, key=len)
- self.add_columns("0", "1", "2")
- self.add_rows([self.up.strip(), row.strip(), self.dwn.strip()] for row in self.target_options)
- self.cursor_foreground_priority = "css"
- self.cursor_background_priority = "css"
diff --git a/nnll_10/package/response_panel.py b/nnll_10/package/response_panel.py
deleted file mode 100644
index 89d48164..00000000
--- a/nnll_10/package/response_panel.py
+++ /dev/null
@@ -1,27 +0,0 @@
-# # #
-# # #
-
-
-# from typing import Callable
-from textual import work
-from textual.widgets import TextArea
-
-
-# from nnll_01 import debug_message as dbug
-# from nnll_11 import chat_machine
-
-
-class ResponsePanel(TextArea):
- """Machine response field"""
-
- def on_mount(self) -> None:
- self.language = "markdown"
- self.read_only = True
- self.soft_wrap = True
-
- @work(group="chat")
- async def on_text_area_changed(self):
- """Send cursor to end of document and animate scroll"""
- self.move_cursor(self.document.end)
- self.scroll_cursor_visible(center=True, animate=True)
- self.scroll_end(animate=True)
diff --git a/nnll_10/package/selectah.py b/nnll_10/package/selectah.py
deleted file mode 100644
index 913b1ae6..00000000
--- a/nnll_10/package/selectah.py
+++ /dev/null
@@ -1,130 +0,0 @@
-# # #
-# # #
-
-# pylint: disable=import-outside-toplevel
-
-import os
-import networkx as nx
-from rich.color import Color
-from textual import on, events, work
-from textual.reactive import reactive
-from textual.screen import Screen
-from textual.widgets import Select, Label
-from textual.widgets._select import SelectCurrent, SelectOverlay
-
-from nnll_01 import debug_message as dbug, debug_monitor, info_message as nfo
-
-
-class Selectah(Select):
- models: reactive[list[tuple[str, str]]] = reactive([("", "")])
- graph: nx.Graph = None
- mode_in: str = "text"
- mode_out: str = "text"
- focused = True
- hover = True
-
- def on_mount(self) -> None:
- # self.options = self.graph.models
- self.graph = self.query_ancestor(Screen).int_proc
- # self.prompt = os.path.basename(next(iter(self.graph.models))[0])
-
- @on(Select.Changed)
- async def on_changed(self) -> None: # event: Select.Changed) -> None:
- """Rearrange models"""
- try:
- assert self.query_one(SelectCurrent).has_value
- except AssertionError as error_log:
- dbug(error_log)
- else:
- self.graph.edit_weight(selection=self.value, mode_in=self.mode_in, mode_out=self.mode_out)
- self.set_options(self.graph.models)
- self.prompt = next(iter(self.graph.models))[0]
- self.expanded = False
-
- @debug_monitor
- @work(exclusive=True)
- @on(events.Enter)
- async def on_enter(self, event: events.Enter) -> None:
- """Force terminal mouse event monitoring"""
- if event.node == SelectOverlay or event.node == self:
- self.hover = True
-
- @debug_monitor
- @work(exclusive=True)
- @on(events.Leave)
- async def on_leave(self, event: events.Leave) -> None:
- """Force terminal mouse event monitoring"""
- if event.node == SelectOverlay or event.node == self:
- self.hover = True
-
- @work(exclusive=True)
- @on(events.Focus)
- async def on_focus(self, event: events.Focus) -> None:
- """Expand panel immediately when clicked in terminal"""
- if SelectOverlay.has_focus or self.has_focus:
- self.focused = True
- self.set_options(self.graph.models)
-
- @work(exclusive=True)
- @on(events.MouseDown)
- async def on_mouse_down(self, event: events.MouseDown) -> None:
- """Expand panel immediately when clicked in terminal"""
- if self.hover and not self.expanded:
- self.expanded = True
- elif (SelectOverlay.has_focus or self.has_focus) and self.expanded:
- self.blur()
-
- @work(exclusive=True)
- @on(events.MouseUp)
- async def on_mouse_up(self, event: events.MouseUp) -> None:
- """Expand panel immediately when clicked in terminal"""
- if self.hover and self.focus and self.expanded:
- self.expanded = False
- elif self.hover and not self.expanded:
- self.expanded = True
-
-
-# if self.expanded is False:
-# self.expanded = True
-
-# @on(SelectOverlay.blur)
-# def on_select_overlay_blur(self, event: events.Blur) -> None:
-# from rich.text import Text
-
-# nfo(event.control.id, "blah blah blah")
-# # if event.control == SelectOverlay:
-# self.ui["sl"].prompt = next(iter(self.int_proc.models))[0]
-# label = self.ui["sl"].query_one("#label", Static)
-# try:
-# assert label.renderable == next(iter(self.int_proc.models))[0]
-# except AssertionError as error_log:
-# dbug(error_log)
-# self.ui["sl"].prompt = next(iter(self.int_proc.models))[0]
-
-# @on(OptionList.OptionSelected)
-# def on_select_overlay_option_selected(self, event: OptionList.OptionSelected) -> None:
-# """Textual API event, refresh pathing, Switch checkpoint assignments"""
-# nfo(" test write")
-# overlay = self.ui["sl"].query_one(SelectOverlay)
-# mode_in = self.ui["it"].get_cell_at((self.ui["it"].current_row, 1))
-# mode_out = self.ui["ot"].get_cell_at((self.ui["ot"].current_row, 1))
-# if self.ui["sl"].selection == Select.BLANK or self.ui["sl"].selection is None:
-# selection = next(iter(self.int_proc.models))[1]
-# else:
-# selection = self.ui["sl"].selection
-# self.int_proc.edit_weight(selection=selection, mode_in=mode_in, mode_out=mode_out)
-# self.ready_tx()
-# self.walk_intent()
-# overlay.recompose()
-# # self.ui["sl"].set_options(self.int_proc.models)
-
-# self.ready_tx()
-# if self.int_proc.has_graph() and self.int_proc.has_path():
-# self.walk_intent()
-# if self.int_proc.has_ckpt():
-
-# self.ui["sl"].set_options(options=self.int_proc.models)
-# nfo(self.int_proc.has_ckpt())
-# self.ui["sl"].expanded = False
-
-# @work(exclusive=True)
diff --git a/nnll_10/package/token_counters.py b/nnll_10/package/token_counters.py
deleted file mode 100644
index 5c711bf2..00000000
--- a/nnll_10/package/token_counters.py
+++ /dev/null
@@ -1,55 +0,0 @@
-# # #
-# # #
-
-
-# from nnll_30 import read_json_file
-
-
-async def tk_count(model: str, message: str):
- """Pass message to model routine
- :param model: Path to model
- :param message: Text to encode
- :return: Token embeddings
- """
- return await litellm_counter(model, message)
-
-
-async def litellm_counter(model: str, message: str):
- """
- Return token count of message based on model\n
- :param model: Model path to lookup tokenizer for
- :param message: Message to tokenize
- :return: `int` Number of tokens needed to represent message
- """
- from litellm.utils import token_counter
- import os
-
- model_name = os.path.split(model)
- model_name = os.path.join(os.path.split(model_name[0])[-1], model_name[-1])
- return token_counter(model_name, text=message)
-
-
-async def ollama_counter(model: str, message: str):
- """
- Return token count of message based on ollama model\n
- :param model: Model to lookup tokenizer for
- :param message: Message to tokenize
- :return: `int` Number of tokens needed to represent message
- """
- from ollama import embed
-
- response = embed(model, input=message)
- return len(response["embeddings"])
-
-
-async def tiktoken_counter(model="cl100k_base", message: str = ""):
- """
- Return token count of gpt based on model\n
- :param model: Model path to lookup tokenizer for
- :param message: Message to tokenize
- :return: `int` Number of tokens needed to represent message
- """
- import tiktoken
-
- encoding = tiktoken.get_encoding(model)
- return len(encoding.encode(message))
diff --git a/nnll_10/package/voice_panel.py b/nnll_10/package/voice_panel.py
deleted file mode 100644
index e36f704a..00000000
--- a/nnll_10/package/voice_panel.py
+++ /dev/null
@@ -1,80 +0,0 @@
-# # #
-# # #
-
-# import array
-import sounddevice as sd
-
-from textual import work
-from textual.reactive import reactive
-
-from textual_plotext import PlotextPlot
-
-from nnll_01 import info_message as nfo # , debug_monitor
-
-
-class VoicePanel(PlotextPlot): # (PlotWidget)
- """Create an unselectable display element"""
-
- ALLOW_SELECT = False
- audio = [0]
- sample_freq: int = 16000
- duration: float = 3.0
- sample_len: reactive[float] = reactive(0.0, recompose=True)
-
- def on_mount(self):
- self.can_focus = True
- # self.theme = "flexoki"
-
- @work(exclusive=True)
- async def record_audio(self) -> None:
- """Get audio from mic"""
- self.plt.clear_data()
- precision = self.duration * self.sample_freq
- self.audio = [0]
- self.audio = sd.rec(int(precision), samplerate=self.sample_freq, channels=1)
- sd.wait()
- self.graph_audio()
- # self.calculate_sample_length()
-
- @work(exclusive=True)
- async def graph_audio(self):
- """Draw audio waveform"""
- self.plt.frame(0)
- self.plt.canvas_color((0, 0, 0))
- self.can_focus = True
- self.plt.xfrequency("0", "0")
- self.plt.yfrequency("0", "0")
- self.plt.scatter(self.audio[:, 0], marker="braille", color=(128, 0, 255))
- # self.calculate_sample_length()
-
- @work(exclusive=True)
- async def play_audio(self):
- """Playback audio recordings"""
- try:
- sd.play(self.audio, samplerate=self.sample_freq)
- sd.wait()
- except TypeError as error_log:
- nfo(error_log)
-
- @work(exclusive=True)
- async def erase_audio(self):
- """Clear audio graph and recording"""
- self.plt.clear_data()
- self.audio = [0]
-
- def calculate_sample_length(self):
- sample_length = len(self.audio)
- duration = float(sample_length / self.sample_freq) if sample_length > 1 else 0.0
- return duration
-
- # from textual_plot import PlotWidget, HiResMode
- # to use PlotWidget
- # self.clear()
- # self.set_xticks([])
- # self.set_yticks([])
- # self.set_xlabel("")
- # self.set_ylabel("")
- # self.set_styles("background: #333333;")
- # self.scatter([i for i in range(0, len(self.audio))], self.audio[:, 0], hires_mode=HiResMode.BRAILLE, marker_style="purple")
-
- # self.clear()
diff --git a/nnll_13/__init__.py b/nnll_13/__init__.py
index 3e3b64b3..02f5c7ee 100644
--- a/nnll_13/__init__.py
+++ b/nnll_13/__init__.py
@@ -51,7 +51,7 @@ async def graph_audio(self):
self.plt.xfrequency("0", "0")
self.plt.yfrequency("0", "0")
self.plt.scatter(self.audio[:, 0], marker="braille", color=(128, 0, 255))
- self.calculate_sample_length()
+ self.time_audio()
@work(exclusive=True)
async def play_audio(self):
@@ -69,7 +69,7 @@ async def erase_audio(self):
self.audio = [0]
@work(exclusive=True)
- async def calculate_sample_length(self):
+ async def time_audio(self):
sample_len = float(len(self.audio) / self.sample_freq)
self.sample_len = sample_len
self.refresh()
diff --git a/nnll_21/__init__.py b/nnll_21/__init__.py
new file mode 100644
index 00000000..a60fa89b
--- /dev/null
+++ b/nnll_21/__init__.py
@@ -0,0 +1,114 @@
+from enum import Enum
+from typing import Literal
+
+
+class AspectImage(str, Enum):
+ """Aspects for 2D image models
+ incl. Flux, SD3, SDXL, AuraFlow"""
+
+ RATIOS = {
+ "1:1___1024x1024": (1024, 1024),
+ "16:15_1024x960": (1024, 960),
+ "17:15_1088x960": (1088, 960),
+ "17:14_1088x896": (1088, 896),
+ "18:13_1152x832": (1152, 832),
+ "4:3___1152x896": (1152, 896),
+ "3:2___1216x832": (1216, 832),
+ # "72:32_1232x832" : ( 1232, 832),
+ "5:3___1280x768": (1280, 768),
+ "21:11_1344x704": (1344, 704),
+ "7:4___1344x768": (1344, 768),
+ "2:1___1408x704": (1408, 704),
+ "23:11_1472x704": (1472, 704),
+ "21:9__1536x640": (1536, 640),
+ "2:1___1536x768": (1536, 768),
+ "5:2___1600x640": (1600, 640),
+ "26:9__1664x576": (1664, 576),
+ "3:1___1728x576": (1728, 576),
+ "28:9__1792x576": (1792, 576),
+ "29:8__1856x512": (1856, 512),
+ "15:4__1920x512": (1920, 512),
+ "31:8__1984x512": (1984, 512),
+ "4:1___2048x512": (2048, 512),
+ }
+
+
+class AspectVideo(str, Enum):
+ """Aspects for Video models
+ incl. HunyuanVideo, Pyramid, Sora"""
+
+ RATIOS = {
+ "1:1___V_256x256": (256, 256),
+ "4:3___V_320x240": (320, 240),
+ "32:27_V_576x486": (576, 486),
+ "22:15_V_704x480": (704, 480),
+ "9:5___V_720x400": (720, 400),
+ "3:2___V_720x480": (720, 480),
+ "5:4___V_720x576": (720, 576),
+ "3:2___V_768x512": (768, 512),
+ "4:3___V_832x624": (832, 624),
+ "53:30_V_848x480": (848, 480),
+ "4:3___V 960x704": (960, 704),
+ "1:1___V_960x960": (960, 960),
+ "20:11_V_1280x704": (1280, 704),
+ "16:9__V_1024X576": (1024, 576),
+ }
+
+
+class AspectRender(str, Enum):
+ """Aspects for 3d-generative models
+ incl. SV3D"""
+
+ RATIOS = {
+ "1:1__SV3D_576x576": (576, 576),
+ }
+
+
+class AspectLegacy(str, Enum):
+ """Aspect ratios for earlier 2d Diffusion models
+ incl. Latent/Stable Diffusion, Pixart A, Playground 1, etc"""
+
+ RATIOS = {
+ "1:1____SD_512x512": (512, 512),
+ "4:3____SD_682x512": (682, 512),
+ "3:2____SD_768x512": (768, 512),
+ "1:1____SD_768x768": (768, 768),
+ "16:9___SD_910x512": (910, 512),
+ "1:85:1_SD_952x512": (952, 512),
+ "2:1____SD_1024x512": (1024, 512),
+ }
+
+
+class Precision(str, Enum):
+ MIXED = "mixed"
+ FP64 = "float64"
+ FP32 = "float32"
+ FP16 = "float16"
+ BF16 = "bfloat16"
+ FP8E4M3FN = "float8_e4m3fn"
+ FP8E5M2 = "float8_e5m2"
+ IN64 = "int64"
+ IN32 = "int32"
+ IN16 = "int16"
+ IN8 = "int8"
+ UN8 = "uint8"
+ NF4 = "nf4"
+
+
+class TensorDataType:
+ TYPE_T = Literal["F64", "F32", "F16", "BF16", "F8_E4M3", "F8_E5M2", "I64", "I32", "I16", "I8", "U8", "nf4", "BOOL"]
+ TYPE_R = Literal["fp64", "fp32", "fp16", "bf16", "fp8_e4m3fn", "fp8_e5m2", "i64", "i32", "i16", "i8", "u8", "nf4", "bool"]
+
+
+# class TensorData:
+# dtype: DTYPE_T
+# shape: List[int]
+# data_offsets: Tuple[int, int]
+# parameter_count: int = field(init=False)
+
+# def __post_init__(self) -> None:
+# # Taken from https://stackoverflow.com/a/13840436
+# try:
+# self.parameter_count = functools.reduce(operator.mul, self.shape)
+# except TypeError:
+# self.parameter_count = 1 # scalar value has no shape
diff --git a/pyproject.toml b/pyproject.toml
index 3607c302..0f568ceb 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -26,8 +26,9 @@ keywords = [
"torch",
]
-dependencies = ["structlog>=25.2.0", "viztracer>=1.0.3"]
+dependencies = ["nnll_01"]
[project.optional-dependencies]
+nnll_01 = ["structlog>=25.2.0", "viztracer>=1.0.3"]
nnll-02 = ["huggingface-hub>=0.29.3", "litellm>=1.65.0"]
nnll-03 = ["aiofiles>=24.1.0", "aiohttp>=3.9.5, <=3.11.13", "tqdm>=4.67.1"]
nnll-04 = ["gguf>=0.14.0", "safetensors>=0.5.3"]
@@ -73,6 +74,7 @@ nnll-56 = ["hidiffusion>=0.1.10", "torch>=2.6.0", "torchvision>=0.21.0"]
nnll-62 = ["diffusers>=0.32.2", "torch>=2.6.0", "torchvision>=0.21.0"]
nnll-64 = ["pillow>=11.1.0"]
all = [
+ "nnll[nnll_01]",
"nnll[nnll_02]",
"nnll[nnll_03]",
"nnll[nnll_04]",
@@ -112,7 +114,6 @@ dev = [
]
[project.scripts]
-zodiac = "nnll_10.package.__init__:main"
astra = "nnll_12:__main__"
nnll-find = "nnll_31:main"
nnll-hash = "nnll_17:main"
diff --git a/tests/test_14_draw_graph.py b/tests/test_14_draw_graph.py
deleted file mode 100644
index 79d2c025..00000000
--- a/tests/test_14_draw_graph.py
+++ /dev/null
@@ -1,108 +0,0 @@
-# import networkx as nx
-# from nnll_14 import calculate_graph
-# import matplotlib.pyplot as plt
-# import numpy as np
-
-# from nnll_15.constants import LibType
-
-
-# def draw_matplot_labeled(nx_graph: nx.Graph) -> None:
-# nx_graph = calculate_graph()
-# path = nx.bidirectional_shortest_path(nx_graph, "text", "image")
-# path_edges = list(zip(path, path[1:]))
-# edge_colors = ["red" if edge in path_edges or tuple(reversed(edge)) in path_edges else "black" for edge in nx_graph.edges()]
-# pos = nx.spring_layout(nx_graph)
-# nx.draw_networkx_nodes(nx_graph, pos)
-# nx.draw_networkx_edges(nx_graph, pos, edge_color=edge_colors)
-# nx.draw_networkx_labels(nx_graph, pos)
-# # nx.draw_networkx_edges(nx_graph, pos)
-# # nx.draw_networkx_edges(nx_graph, pos, edge_labels={(u, v): d for u, v, d in nx_graph.edges(data=True)})
-# nx.draw_networkx_edge_labels(nx_graph, pos, edge_labels={(u, v): d for u, v, d in nx_graph.edges(data=True)}, font_size=3, alpha=0.5, rotate=False)
-# plt.show()
-
-
-# def draw_matplot_circular() -> None:
-# nx_graph = calculate_graph()
-# path = nx.bidirectional_shortest_path(nx_graph, "image", "speech")
-# path_edges = list(zip(path, path[1:]))
-# edge_colors = ["red" if edge in path_edges or tuple(reversed(edge)) in path_edges else "black" for edge in nx_graph.edges()]
-# pos = nx.circular_layout(nx_graph)
-# nx.draw_networkx_nodes(nx_graph, pos)
-# nx.draw_networkx_edges(nx_graph, pos, edge_color=edge_colors)
-# nx.draw_networkx_labels(nx_graph, pos)
-# nx.draw_circular(nx_graph)
-# plt.show()
-
-
-# def draw_matplot_graphviz() -> None:
-# nx_graph = calculate_graph()
-# path = nx.bidirectional_shortest_path(nx_graph, "image", "speech")
-# path_edges = list(zip(path, path[1:]))
-# edge_colors = ["red" if edge in path_edges or tuple(reversed(edge)) in path_edges else "black" for edge in nx_graph.edges()]
-# pos = nx.nx_agraph.graphviz_layout(nx_graph, prog="twopi", root=0)
-# options = {"with_labels": False, "alpha": 0.5, "node_size": 15}
-# nx.draw(nx_graph, pos, node_color=edge_colors, **options)
-# plt.show()
-
-
-# def draw_matplot_weights() -> None:
-# nx_graph = calculate_graph()
-# pos = nx.spring_layout(nx_graph, scale=20, k=3 / np.sqrt(nx_graph.order()))
-# nx.draw(nx_graph, pos=pos, node_color="lightblue", with_labels=True, node_size=500)
-# labels = nx.get_edge_attributes(nx_graph, "weight")
-# nx.draw_networkx_edge_labels(nx_graph, pos, edge_labels=labels)
-# plt.show()
-
-
-# if __name__ == "__main__":
-# # draw_matplot_weights()
-# draw_matplot_circular()
-
-
-# # from textual.app import App, ComposeResult
-# # from textual.widgets import Static
-# # from textual_plot import HiResMode # , PlotWidget
-# # from textual_plotext import PlotextPlot
-# # from networkx import convert_node_labels_to_integers
-# # import numpy as np
-# # from typing import Sequence
-# # class MinimalApp(App[None]):
-# # def compose(self) -> ComposeResult:
-# # yield Static()
-# # # yield PlotextPlot(id="plotext")
-# # # yield PlotWidget(id="plot)
-
-# # def on_mount(self) -> None:
-
-# # nx_graph = label_edge_attrib_for(nx_graph)
-# # self.draw_matplot(nx_graph)
-# # # nx_graph_num = convert_node_labels_to_integers(nx_graph)
-# # # self.draw_textual_plotext(nx_graph_num)
-# # # self.draw_textual_plot(nx_graph_num)
-
-
-# # def draw_textual_plotext(self, nx_graph_num: nx.Graph) -> None:
-# # plot = self.query_one("#plotext")
-# # first_column = [item[0] for item in list(nx_graph_num.edges())]
-# # second_column = [item[1] for item in list(nx_graph_num.edges())]
-# # plot.plot(x=first_column, y=second_column, hires_mode=HiResMode.BRAILLE, line_style="purple")
-
-# # def draw_textual_plot(self, nx_graph_num: nx.Graph) -> None:
-# # plot = self.query_one("#plot")
-# # plot.plt.scatter(nx_graph_num.edges())
-
-
-# # if __name__ == "__main__":
-# # MinimalApp().run()
-
-# # data = dict(list(nx_graph_num.edges()))
-# # for each in list(nx_graph_num.edges()):
-
-
-# # # nx
-# # # plt.show()
-# # # # plot.set_xticks([])
-# # # # plot.set_yticks([])
-# # # # plot.set_xlabel("")
-# # # # plot.set_ylabel("")
-# # # # plot.set_styles("background: #1f1f1f;")
diff --git a/tests/test_14_graph.py b/tests/test_14_graph.py
deleted file mode 100644
index 6b806efe..00000000
--- a/tests/test_14_graph.py
+++ /dev/null
@@ -1,339 +0,0 @@
-# # # #
-# # # #
-
-# # pylint:disable=redefined-outer-name
-# # pylint:disable=redefined-builtin
-
-# import datetime
-# from pathlib import PosixPath
-# from unittest import mock
-
-# # import matplotlib.pyplot as plt
-# import pytest
-# from nnll_14 import calculate_graph
-# from nnll_15.constants import VALID_CONVERSIONS
-
-
-# class Model:
-# """Mock ollama Model class"""
-
-# def __init__(self, model=None, modified_at=None, digest=None, size=None, details=None):
-# self.model = model
-# self.modified_at = modified_at
-# self.digest = digest
-# self.size = size
-# self.details = details
-
-
-# class ModelDetails:
-# """Mock ollama ModelDetails class"""
-
-# def __init__(self, parent_model=None, format=None, family=None, families=None, parameter_size=None, quantization_level=None):
-# self.parent_model = parent_model
-# self.format = format
-# self.family = family
-# self.families = families
-# self.parameter_size = parameter_size
-# self.quantization_level = quantization_level
-
-
-# class ListResponse:
-# """Mock ollama ListResponse class"""
-
-# def __init__(self, models=None):
-# self.models = models
-
-
-# @pytest.fixture(scope="session")
-# def mock_ollama_data():
-# """Mock ollama response"""
-# with mock.patch("ollama.list", new_callable=mock.MagicMock()) as mock_get_registry_data:
-# data = ListResponse(
-# models=[
-# Model(
-# model="hf.co/unsloth/gemma-3-27b-it-GGUF:Q8_0",
-# modified_at=datetime.datetime(2025, 3, 19, 12, 21, 19, 112890, tzinfo=None),
-# digest="965289b1e3e63c66bfc018051b6a907b2f0b18620d5721dd1cdfad759b679a2c",
-# size=29565711760,
-# details=ModelDetails(parent_model="", format="gguf", family="gemma3", families=["gemma3"], parameter_size="27B", quantization_level="unknown"),
-# ),
-# Model(
-# model="hf.co/unsloth/gemma-3-27b-it-GGUF:Q5_K_M",
-# modified_at=datetime.datetime(2025, 3, 18, 12, 13, 57, 294851, tzinfo=None),
-# digest="82c7d241b764d0346f382a9059a7b08056075c7bc2d81ac21dfa20d525556b16",
-# size=20129415184,
-# details=ModelDetails(parent_model="", format="gguf", family="gemma3", families=["gemma3"], parameter_size="27B", quantization_level="unknown"),
-# ),
-# Model(
-# model="hf.co/bartowski/RekaAI_reka-flash-3-GGUF:Q5_K_M",
-# modified_at=datetime.datetime(2025, 3, 13, 18, 28, 57, 859962, tzinfo=None),
-# digest="43d35cd4e25e90f9cbb33585f60823450bd1f279c4703a1b2831a9cba73e60e4",
-# size=15635474582,
-# details=ModelDetails(parent_model="", format="gguf", family="llama", families=["llama"], parameter_size="20.9B", quantization_level="unknown"),
-# ),
-# ]
-# )
-# mock_get_registry_data.return_value = data
-# yield mock_get_registry_data
-
-
-# class HFCacheInfo:
-# """Mock hub cache"""
-
-# def __init__(self, size_on_disk, repos):
-# self.size_on_disk = size_on_disk
-# self.repos = repos
-
-
-# class CachedRepoInfo:
-# """Mock hub repo cache"""
-
-# def __init__(self, repo_id, repo_type, repo_path, size_on_disk, nb_files, revisions, files, last_accessed, last_modified):
-# self.repo_id = repo_id
-# self.repo_type = repo_type
-# self.repo_path = repo_path
-# self.size_on_disk = size_on_disk
-# self.nb_files = nb_files
-# self.revisions = revisions
-# self.files = files
-# self.last_accessed = last_accessed
-# self.last_modified = last_modified
-
-
-# @pytest.fixture(scope="session")
-# def mock_hub_data():
-# """Mock hub data"""
-# with mock.patch("huggingface_hub.scan_cache_dir", new_callable=mock.MagicMock()) as mock_get_registry_data:
-# data = HFCacheInfo(
-# size_on_disk=91018285403,
-# repos=frozenset(
-# {
-# CachedRepoInfo(
-# repo_id="parler-tts/parler-tts-large-v1",
-# repo_type="model",
-# repo_path=PosixPath("/Users/unauthorized/.cache/huggingface/hub/models--parler-tts--parler-tts-large-v1"),
-# size_on_disk=9335526346,
-# nb_files=14,
-# revisions=None,
-# files=None,
-# last_accessed=1741910585.3828554,
-# last_modified=1741908821.5103855,
-# ),
-# CachedRepoInfo(
-# repo_id="THUDM/CogView3-Plus-3B",
-# repo_type="model",
-# repo_path=PosixPath("/Users/unauthorized/.cache/huggingface/hub/models--THUDM--CogView3-Plus-3B"),
-# size_on_disk=25560123724,
-# nb_files=20,
-# revisions=None,
-# files=None,
-# last_accessed=1741827083.5111423,
-# last_modified=1741827083.4126444,
-# ),
-# }
-# ),
-# )
-# mock_get_registry_data.return_value = data
-# yield mock_get_registry_data
-
-
-# def test_mocked_ollama(mock_ollama_data):
-# """Check if mocking ollama correctly"""
-# result = mock_ollama_data()
-
-# assert len(result.models) == 3
-# next_model = next(iter(result.models))
-# assert next_model.model == "hf.co/unsloth/gemma-3-27b-it-GGUF:Q8_0"
-# assert next_model.size == 29565711760
-
-
-# def test_mocked_hub(mock_hub_data):
-# """Check if mocking hub correctly.
-# `frozenset` is converted to a sorted list
-# Otherwise hashed return becomes unordered"""
-# result = mock_hub_data()
-# new_list = []
-# assert len(result.repos) == 2
-# next_model = [*result.repos]
-# for x in next_model:
-# new_list.append([x.repo_id, x.size_on_disk])
-# new_list.sort(key=lambda x: x[1])
-# assert new_list[0][0] == "parler-tts/parler-tts-large-v1"
-# assert new_list[0][1] == 9335526346
-
-
-# def test_create_graph(mock_ollama_data, mock_hub_data):
-# """Run test of graph creation"""
-# nx_graph = calculate_graph()
-
-# assert list(nx_graph) == VALID_CONVERSIONS
-# key_data = nx_graph.edges.data("key")
-# for edge in key_data:
-# if edge[2] is not None:
-# assert isinstance(edge[2], str)
-# else:
-# assert isinstance(edge[1], str)
-
-# size_data = nx_graph.edges.data("size")
-# for edge in size_data:
-# if edge[2] is not None:
-# assert isinstance(edge[2], int)
-# else:
-# assert isinstance(edge[1], str)
-
-
-# # when user presses trigger :
-# # run shortest distance, then run operations identified on edges
-
-# # seen = set()
-# # [e[1] for e in nx_graph.edges if e[1] not in seen and not seen.add(e[1])]
-
-# # nx_graph['speech']['text’] get all paths towards
-# # get all size on graph
-# # nx_graph.edges.data(“keys”) get all model name on graph
-# # nx_graph.edges['text','speech',0]['key']
-
-# # nx_graph.out_degree('text') get number of edges/paths pointing away
-# # nx_graph.in_degree('text') get number of edges/paths pointing towards
-# # nx_graph.edges[‘text’, ‘image’][‘weight'] = 4.2 change attribute
-
-
-# # node_attrib = nx.get_node_attributes(nx_graph, “model”)
-# # node_attrib[‘text’]
-
-
-# # nx.draw_networkx
-# # adjacent_pairs = [(key, item) for key, value in VALID_CONVERSIONS.input.items() for item in (value.values if isinstance(value.values, tuple) else ())]
-# # from typing import Dict, Tuple
-# # from pydantic import BaseModel, Field
-
-# # class ConversionValue(BaseModel):
-# # """(output_medium, more_output_medium)"""
-
-# # values: Field()
-
-
-# # class ConversionMap(BaseModel):
-# # """{input_medium: (output_medium, more_output_medium)"""
-
-# # input: Dict[str, ConversionValue]
-
-
-# # from networkx import convert_node_labels_to_integers
-
-
-# # mllama (vllm), text-to-image, text-generation
-
-# # 2. Add nodes for each unique data type and model combination (e.g., `['text']`, `['image']`, etc.) and edges representing the transformations between them using models.
-
-
-# # # Define a function to add edges based on input-output pairs
-# # def add_model_edges(G, input_type, model_dict, output_type):
-# # for model_name, model_path in model_dict.items():
-# # G.add_edge(str(input_type), str(output_type), model_name=model_name, model_path=model_path)
-
-
-# # # Add the specified paths to your graph
-# # add_model_edges(G, ["text"], {"model1": "path1"}, ["text"])
-# # add_model_edges(G, ["text", "image"], {"model2": "path2"}, ["text"])
-# # add_model_edges(G, ["image"], {"model3": "path3"}, ["text"])
-# # add_model_edges(G, ["text"], {"model4": "path4"}, ["image"])
-# # add_model_edges(G, ["speech"], {"model5": "path5"}, ["text"])
-# # add_model_edges(G, ["text"], {"model6": "path6"}, ["speech"])
-
-# # # Example: Find all paths from ['text'] to ['image']
-# # paths = list(nx.all_simple_paths(G, str(["text"]), str(["image"])))
-# # print(paths)
-
-
-# # node would be format
-# # edge would be conversion model
-# # 'vllm'
-# # 'text-generation'
-
-# # input #output
-# # node #edge #node
-# # {['text']} { model name: model path} } { ['text']] }
-# # [['text', 'image']: { model name: model path} } { ['text'] }
-# # {['image']: { model name: model path} } { ['text'] }
-# # {['text']: { model name: model path} } { ['image'] }
-# # {['speech']: { model name: model path} } { ['text'] }
-# # {['text']: { model name: model path} } { ['speech']}
-
-
-# # bidirectional_shortest_path(G, mode_in, mode_out)
-
-# # G.add_edges_from[(2, 3, {"weight": 3.1415})] #add edge with attribute
-# # G.add_nodes_from([(4, {"color": "red"}), (5, {"color": "green"})]) #add node with attribute
-# # H = nx.path_graph(10)
-# # G.add_nodes_from(H) # import one graph into another
-# # G.add_node(H) # the entire graph as a node
-# # G.clear()
-
-# # class ConversionGraph:
-# # def __init__(self, graph):
-# # self.graph = graph # Graph where keys are formats, values are dict of {format: (steps, quality)}
-
-# # def manhattan_distance(self, node1, node2):
-# # return abs(node1[0] - node2[0]) + abs(node1[1] - node2[1])
-
-# # def find_conversion_path(self, initial_format, target_format):
-# # # Check if direct conversion is possible
-# # if target_format in self.graph[initial_format]:
-# # return [(initial_format, target_format)]
-
-# # # Initialize variables for pathfinding
-# # queue = [[(initial_format, 0, float("inf"))]] # (format, steps, quality)
-# # visited = set()
-
-# # while queue:
-# # path = queue.pop(0)
-# # current_node = path[-1][0]
-# # current_steps = path[-1][1]
-# # current_quality = path[-1][2]
-
-# # if current_node == target_format:
-# # return path
-
-# # for neighbor, (steps, quality) in self.graph[current_node].items():
-# # # Avoid backtracking and only move forward
-# # if neighbor not in visited:
-# # new_steps = current_steps + steps
-# # new_quality = min(current_quality, quality)
-# # distance_to_goal = self.manhattan_distance((new_steps, new_quality), (0, float("inf")))
-
-# # # Prioritize paths with fewer steps but consider higher quality nodes
-# # queue.append(path + [(neighbor, new_steps, new_quality)])
-
-# # visited.add(current_node)
-# # queue.sort(key=lambda p: (len(p), -p[-1][2])) # Sort by path length and quality
-
-# # return None
-
-
-# # # (steps, quality)
-# # graph = {
-# # "FormatA": {"FormatB": (1, 8), "FormatC": (2, 9)},
-# # "FormatB": {"FormatD": (1, 7)},
-# # "FormatC": {"FormatD": (3, 6), "FormatE": (2, 10)},
-# # "FormatD": {"TargetFormat": (1, 5)},
-# # "FormatE": {"TargetFormat": (1, 9)},
-# # }
-
-# # if __name__ == "__main__":
-# # converter = ConversionGraph(graph)
-# # path = converter.find_conversion_path("FormatA", "TargetFormat")
-# # print("Conversion Path:", path)
-
-
-# # for model, details in ollama_models.items():
-# # nx_graph.add_edges_from(details.available_tasks, key=model, weight=details.size)
-# # for model, details in hub_models.items():
-# # nx_graph.add_edges_from(details.available_tasks, key=model, weight=details.size)
-# # nx_graph = build_conversion_graph()
-# # ollama_models = from_ollama_cache()
-# # hub_models = from_hf_hub_cache()
-# # for model, details in ollama_models.items():
-# # nx_graph.add_edges_from(details.available_tasks, label=model, weight=details.size)
-# # for model, details in hub_models.items():
-# # nx_graph.add_edges_from(details.available_tasks, label=model, weight=details.size)
From eef99c67d0cbc6ebddf4f3b755dbce1b599c0ef9 Mon Sep 17 00:00:00 2001
From: exdysa <91800957+exdysa@users.noreply.github.com>
Date: Tue, 22 Apr 2025 17:43:22 -0400
Subject: [PATCH 3/3] +dependency adjustments
---
pyproject.toml | 1 -
1 file changed, 1 deletion(-)
diff --git a/pyproject.toml b/pyproject.toml
index 0f568ceb..2bd44cf5 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -26,7 +26,6 @@ keywords = [
"torch",
]
-dependencies = ["nnll_01"]
[project.optional-dependencies]
nnll_01 = ["structlog>=25.2.0", "viztracer>=1.0.3"]
nnll-02 = ["huggingface-hub>=0.29.3", "litellm>=1.65.0"]