shadow-tools 0.7.2__tar.gz → 0.8.0__tar.gz
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.
- {shadow_tools-0.7.2 → shadow_tools-0.8.0}/PKG-INFO +17 -1
- {shadow_tools-0.7.2 → shadow_tools-0.8.0}/README.md +16 -0
- {shadow_tools-0.7.2 → shadow_tools-0.8.0}/pyproject.toml +1 -1
- {shadow_tools-0.7.2 → shadow_tools-0.8.0}/src/shadowtools/__init__.py +4 -4
- {shadow_tools-0.7.2 → shadow_tools-0.8.0}/src/shadowtools/generator.py +23 -1
- {shadow_tools-0.7.2 → shadow_tools-0.8.0}/.gitignore +0 -0
- {shadow_tools-0.7.2 → shadow_tools-0.8.0}/LICENSE +0 -0
- {shadow_tools-0.7.2 → shadow_tools-0.8.0}/src/shadowtools/ai.py +0 -0
- {shadow_tools-0.7.2 → shadow_tools-0.8.0}/src/shadowtools/async_tools.py +0 -0
- {shadow_tools-0.7.2 → shadow_tools-0.8.0}/src/shadowtools/bpe.py +0 -0
- {shadow_tools-0.7.2 → shadow_tools-0.8.0}/src/shadowtools/cli.py +0 -0
- {shadow_tools-0.7.2 → shadow_tools-0.8.0}/src/shadowtools/config.py +0 -0
- {shadow_tools-0.7.2 → shadow_tools-0.8.0}/src/shadowtools/data.py +0 -0
- {shadow_tools-0.7.2 → shadow_tools-0.8.0}/src/shadowtools/files.py +0 -0
- {shadow_tools-0.7.2 → shadow_tools-0.8.0}/src/shadowtools/hashing.py +0 -0
- {shadow_tools-0.7.2 → shadow_tools-0.8.0}/src/shadowtools/http.py +0 -0
- {shadow_tools-0.7.2 → shadow_tools-0.8.0}/src/shadowtools/ids.py +0 -0
- {shadow_tools-0.7.2 → shadow_tools-0.8.0}/src/shadowtools/network.py +0 -0
- {shadow_tools-0.7.2 → shadow_tools-0.8.0}/src/shadowtools/retry.py +0 -0
- {shadow_tools-0.7.2 → shadow_tools-0.8.0}/src/shadowtools/security.py +0 -0
- {shadow_tools-0.7.2 → shadow_tools-0.8.0}/src/shadowtools/text.py +0 -0
- {shadow_tools-0.7.2 → shadow_tools-0.8.0}/src/shadowtools/training.py +0 -0
- {shadow_tools-0.7.2 → shadow_tools-0.8.0}/src/shadowtools/validation.py +0 -0
- {shadow_tools-0.7.2 → shadow_tools-0.8.0}/src/shadowtools/websocket.py +0 -0
- {shadow_tools-0.7.2 → shadow_tools-0.8.0}/tests/test_core.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: shadow-tools
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.8.0
|
|
4
4
|
Summary: A practical all-in-one Python toolkit for HTTP, WebSockets, files, data, validation, async work, and CLIs.
|
|
5
5
|
Project-URL: Homepage, https://github.com/WilliamLaurento/shadow-tools
|
|
6
6
|
Project-URL: Issues, https://github.com/WilliamLaurento/shadow-tools/issues
|
|
@@ -76,6 +76,22 @@ bot.save("my_text_model")
|
|
|
76
76
|
Training prints the tokenizer status plus each epoch and loss. Use
|
|
77
77
|
`learn("corpus.txt", epochs=20, verbose=False)` when you do not want updates.
|
|
78
78
|
|
|
79
|
+
## Train a question-and-answer bot
|
|
80
|
+
|
|
81
|
+
```python
|
|
82
|
+
from shadowtools import ask, teach
|
|
83
|
+
|
|
84
|
+
bot = teach({
|
|
85
|
+
"What is ChatGPT?": "ChatGPT is an AI system that predicts useful next tokens to answer a prompt.",
|
|
86
|
+
"How does a tokenizer work?": "A tokenizer splits text into smaller tokens a model can process.",
|
|
87
|
+
"What is machine learning?": "Machine learning is when a model learns patterns from examples.",
|
|
88
|
+
}, epochs=20)
|
|
89
|
+
|
|
90
|
+
print(ask(bot, "What is ChatGPT?"))
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
Add many more real Q&A pairs for better answers.
|
|
94
|
+
|
|
79
95
|
Install it with `pip install "shadow-tools[ml,nlp]"`. The package trains the
|
|
80
96
|
tokenizer and Transformer together, then converts predicted token IDs back to
|
|
81
97
|
normal text for you.
|
|
@@ -48,6 +48,22 @@ bot.save("my_text_model")
|
|
|
48
48
|
Training prints the tokenizer status plus each epoch and loss. Use
|
|
49
49
|
`learn("corpus.txt", epochs=20, verbose=False)` when you do not want updates.
|
|
50
50
|
|
|
51
|
+
## Train a question-and-answer bot
|
|
52
|
+
|
|
53
|
+
```python
|
|
54
|
+
from shadowtools import ask, teach
|
|
55
|
+
|
|
56
|
+
bot = teach({
|
|
57
|
+
"What is ChatGPT?": "ChatGPT is an AI system that predicts useful next tokens to answer a prompt.",
|
|
58
|
+
"How does a tokenizer work?": "A tokenizer splits text into smaller tokens a model can process.",
|
|
59
|
+
"What is machine learning?": "Machine learning is when a model learns patterns from examples.",
|
|
60
|
+
}, epochs=20)
|
|
61
|
+
|
|
62
|
+
print(ask(bot, "What is ChatGPT?"))
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Add many more real Q&A pairs for better answers.
|
|
66
|
+
|
|
51
67
|
Install it with `pip install "shadow-tools[ml,nlp]"`. The package trains the
|
|
52
68
|
tokenizer and Transformer together, then converts predicted token IDs back to
|
|
53
69
|
normal text for you.
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "shadow-tools"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.8.0"
|
|
8
8
|
description = "A practical all-in-one Python toolkit for HTTP, WebSockets, files, data, validation, async work, and CLIs."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.10"
|
|
@@ -5,7 +5,7 @@ from .bpe import BPETokenizer
|
|
|
5
5
|
from .config import env, require_env, to_bool
|
|
6
6
|
from .files import append_text, ensure_dir, read_text, write_text
|
|
7
7
|
from .hashing import file_hash, hash_text
|
|
8
|
-
from .generator import GeneratorConfig, TextGenerator, generate_text, learn, say, train_generator
|
|
8
|
+
from .generator import GeneratorConfig, TextGenerator, ask, generate_text, learn, say, teach, train_generator
|
|
9
9
|
from .http import get, request
|
|
10
10
|
from .ids import random_token, timestamp_id, uuid4
|
|
11
11
|
from .network import generate_random_ips, generate_test_ips, is_subdomain_of, make_subdomain, resolve_dns, reverse_dns
|
|
@@ -15,10 +15,10 @@ from .text import chunks, slugify, to_camel, to_snake
|
|
|
15
15
|
from .training import SmartTokenizer, fine_tune, make_loaders, predict_text, train, train_text
|
|
16
16
|
from .validation import is_email, is_url, require_keys
|
|
17
17
|
|
|
18
|
-
__version__ = "0.
|
|
18
|
+
__version__ = "0.8.0"
|
|
19
19
|
|
|
20
20
|
__all__ = [
|
|
21
|
-
"append_text", "audit_headers", "BPETokenizer", "chunks", "ensure_dir", "env", "file_hash", "GeneratorConfig", "generate_random_ips", "generate_test_ips", "generate_text", "get", "hash_text", "is_email", "is_subdomain_of", "is_url", "learn", "make_password", "make_subdomain", "random_token", "read_csv",
|
|
22
|
-
"read_json", "read_text", "request", "require_env", "require_keys", "retry", "reverse_dns", "resolve_dns", "say", "slugify", "timestamp_id", "to_bool", "to_camel", "to_snake", "TextGenerator", "train", "train_generator", "fine_tune", "make_loaders", "SmartTokenizer", "train_text", "predict_text", "uuid4", "write_csv",
|
|
21
|
+
"append_text", "ask", "audit_headers", "BPETokenizer", "chunks", "ensure_dir", "env", "file_hash", "GeneratorConfig", "generate_random_ips", "generate_test_ips", "generate_text", "get", "hash_text", "is_email", "is_subdomain_of", "is_url", "learn", "make_password", "make_subdomain", "random_token", "read_csv",
|
|
22
|
+
"read_json", "read_text", "request", "require_env", "require_keys", "retry", "reverse_dns", "resolve_dns", "say", "slugify", "teach", "timestamp_id", "to_bool", "to_camel", "to_snake", "TextGenerator", "train", "train_generator", "fine_tune", "make_loaders", "SmartTokenizer", "train_text", "predict_text", "uuid4", "write_csv",
|
|
23
23
|
"write_json", "write_text", "redact_secrets", "verify_file_hash",
|
|
24
24
|
]
|
|
@@ -3,7 +3,7 @@ from __future__ import annotations
|
|
|
3
3
|
|
|
4
4
|
from dataclasses import asdict, dataclass
|
|
5
5
|
from pathlib import Path
|
|
6
|
-
from typing import Any, Sequence
|
|
6
|
+
from typing import Any, Mapping, Sequence
|
|
7
7
|
|
|
8
8
|
from .bpe import BPETokenizer
|
|
9
9
|
|
|
@@ -226,3 +226,25 @@ def learn(source: str | Path | Sequence[str], *, epochs: int = 10,
|
|
|
226
226
|
def say(generator: TextGenerator, prompt: str, **options: Any) -> str:
|
|
227
227
|
"""Beginner-friendly name for generating text from a trained model."""
|
|
228
228
|
return generator.generate(prompt, **options)
|
|
229
|
+
|
|
230
|
+
|
|
231
|
+
def teach(questions_and_answers: Mapping[str, str] | Sequence[tuple[str, str]], *,
|
|
232
|
+
epochs: int = 10, verbose: bool = True, **options: Any) -> TextGenerator:
|
|
233
|
+
"""Train a small Q&A bot from question-and-answer pairs."""
|
|
234
|
+
pairs = list(questions_and_answers.items()) if isinstance(questions_and_answers, Mapping) else list(questions_and_answers)
|
|
235
|
+
if len(pairs) < 2:
|
|
236
|
+
raise ValueError("Give teach() at least two question-and-answer pairs.")
|
|
237
|
+
sections: list[str] = []
|
|
238
|
+
for question, answer in pairs:
|
|
239
|
+
if not isinstance(question, str) or not isinstance(answer, str) or not question.strip() or not answer.strip():
|
|
240
|
+
raise ValueError("Every question and answer must be non-empty text.")
|
|
241
|
+
sections.append(f"Question: {question.strip()}\nAnswer: {answer.strip()}")
|
|
242
|
+
return learn("\n\n".join(sections), epochs=epochs, verbose=verbose, **options)
|
|
243
|
+
|
|
244
|
+
|
|
245
|
+
def ask(generator: TextGenerator, question: str, *, max_tokens: int = 200,
|
|
246
|
+
**options: Any) -> str:
|
|
247
|
+
"""Ask a Q&A bot a question and get its generated answer."""
|
|
248
|
+
if not isinstance(question, str) or not question.strip():
|
|
249
|
+
raise ValueError("question must be non-empty text.")
|
|
250
|
+
return generator.generate(f"Question: {question.strip()}\nAnswer:", max_tokens=max_tokens, **options)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|