Compare commits

..

No commits in common. "310cb9421ed0e6fa841ce41567208fb438838000" and "a895c1fc6a3a5f8099792454844a19b1dd132fbe" have entirely different histories.

9 changed files with 61 additions and 102 deletions

116
README.md
View File

@ -37,95 +37,63 @@ cmm [global options] command [command options]
### Global Options
- `-C`, `--config`: Config file name (defaults to `.config.yaml`).
- `-c`, `--config`: Config file name (defaults to `.config.yaml`).
### Commands
- `ask`: Ask a question.
- `hist`: Print chat history.
- `tag`: Manage tags.
- `config`: Manage configuration.
- `print`: Print files.
### Command Options
#### Question
#### `ask` Command Options
The `question` command is used to ask, create, and process questions.
- `-q`, `--question`: Question to ask (required).
- `-m`, `--max-tokens`: Max tokens to use.
- `-T`, `--temperature`: Temperature to use.
- `-M`, `--model`: Model to use.
- `-n`, `--number`: Number of answers to produce (default is 3).
- `-s`, `--source`: Add content of a file to the query.
- `-S`, `--only-source-code`: Add pure source code to the chat history.
- `-t`, `--tags`: List of tag names.
- `-e`, `--extags`: List of tag names to exclude.
- `-o`, `--output-tags`: List of output tag names (default is the input tags).
- `-a`, `--match-all-tags`: All given tags must match when selecting chat history entries.
```bash
cmm question [-t OTAGS]... [-k ATAGS]... [-x XTAGS]... [-o OUTTAGS]... [-A AI] [-M MODEL] [-n NUM] [-m MAX] [-T TEMP] (-a ASK | -c CREATE | -r REPEAT | -p PROCESS) [-O] [-s SOURCE]... [-S SOURCE]...
```
#### `hist` Command Options
* `-t, --or-tags OTAGS` : List of tags (one must match)
* `-k, --and-tags ATAGS` : List of tags (all must match)
* `-x, --exclude-tags XTAGS` : List of tags to exclude
* `-o, --output-tags OUTTAGS` : List of output tags (default: use input tags)
* `-A, --AI AI` : AI ID to use
* `-M, --model MODEL` : Model to use
* `-n, --num-answers NUM` : Number of answers to request
* `-m, --max-tokens MAX` : Max. number of tokens
* `-T, --temperature TEMP` : Temperature value
* `-a, --ask ASK` : Ask a question
* `-c, --create CREATE` : Create a question
* `-r, --repeat REPEAT` : Repeat a question
* `-p, --process PROCESS` : Process existing questions
* `-O, --overwrite` : Overwrite existing messages when repeating them
* `-s, --source-text SOURCE` : Add content of a file to the query
* `-S, --source-code SOURCE` : Add source code file content to the chat history
- `-d`, `--dump`: Print chat history as Python structure.
- `-w`, `--with-tags`: Print chat history with tags.
- `-W`, `--with-files`: Print chat history with filenames.
- `-S`, `--only-source-code`: Print only source code.
- `-t`, `--tags`: List of tag names.
- `-e`, `--extags`: List of tag names to exclude.
- `-a`, `--match-all-tags`: All given tags must match when selecting chat history entries.
#### Hist
#### `tag` Command Options
The `hist` command is used to print the chat history.
- `-l`, `--list`: List all tags and their frequency.
```bash
cmm hist [-t OTAGS]... [-k ATAGS]... [-x XTAGS]... [-w] [-W] [-S] [-A ANSWER] [-Q QUESTION]
```
#### `config` Command Options
* `-t, --or-tags OTAGS` : List of tags (one must match)
* `-k, --and-tags ATAGS` : List of tags (all must match)
* `-x, --exclude-tags XTAGS` : List of tags to exclude
* `-w, --with-tags` : Print chat history with tags
* `-W, --with-files` : Print chat history with filenames
* `-S, --source-code-only` : Print only source code
* `-A, --answer ANSWER` : Search for answer substring
* `-Q, --question QUESTION` : Search for question substring
- `-l`, `--list-models`: List all available models.
- `-m`, `--print-model`: Print the currently configured model.
- `-M`, `--model`: Set model in the config file.
#### Tags
#### `print` Command Options
The `tags` command is used to manage tags.
```bash
cmm tags (-l | -p PREFIX | -c CONTENT)
```
* `-l, --list` : List all tags and their frequency
* `-p, --prefix PREFIX` : Filter tags by prefix
* `-c, --contain CONTENT` : Filter tags by contained substring
#### Config
The `config` command is used to manage the configuration.
```bash
cmm config (-l | -m | -c CREATE)
```
* `-l, --list-models` : List all available models
* `-m, --print-model` : Print the currently configured model
* `-c, --create CREATE` : Create config with default settings in the given file
#### Print
The `print` command is used to print message files.
```bash
cmm print -f FILE [-q | -a | -S]
```
* `-f, --file FILE` : File to print
* `-q, --question` : Print only question
* `-a, --answer` : Print only answer
* `-S, --only-source-code` : Print only source code
- `-f`, `--file`: File to print (required).
- `-S`, `--only-source-code`: Print only source code.
### Examples
1. Ask a question:
```bash
cmm question -a "What is the meaning of life?" -t philosophy -x religion
cmm ask -q "What is the meaning of life?" -t philosophy -e religion
```
2. Display the chat history:
@ -137,19 +105,19 @@ cmm hist
3. Filter chat history by tags:
```bash
cmm hist --or-tags tag1 tag2
cmm hist -t tag1 tag2
```
4. Exclude chat history by tags:
```bash
cmm hist --exclude-tags tag3 tag4
cmm hist -e tag3 tag4
```
5. List all tags and their frequency:
```bash
cmm tags -l
cmm tag -l
```
6. Print the contents of a file:

View File

@ -59,12 +59,6 @@ class AI(Protocol):
"""
raise NotImplementedError
def print_models(self) -> None:
"""
Print all models supported by this AI.
"""
raise NotImplementedError
def tokens(self, data: Union[Message, Chat]) -> int:
"""
Computes the nr. of AI language tokens for the given message

View File

@ -17,7 +17,7 @@ def create_ai(args: argparse.Namespace, config: Config) -> AI: # noqa: 11
is not found, it uses the first AI in the list.
"""
ai_conf: AIConfig
if 'AI' in args and args.AI:
if args.AI:
try:
ai_conf = config.ais[args.AI]
except KeyError:
@ -32,11 +32,11 @@ def create_ai(args: argparse.Namespace, config: Config) -> AI: # noqa: 11
if ai_conf.name == 'openai':
ai = OpenAI(cast(OpenAIConfig, ai_conf))
if 'model' in args and args.model:
if args.model:
ai.config.model = args.model
if 'max_tokens' in args and args.max_tokens:
if args.max_tokens:
ai.config.max_tokens = args.max_tokens
if 'temperature' in args and args.temperature:
if args.temperature:
ai.config.temperature = args.temperature
return ai
else:

View File

@ -62,12 +62,7 @@ class OpenAI(AI):
"""
Return all models supported by this AI.
"""
ret = []
for engine in sorted(openai.Engine.list()['data'], key=lambda x: x['id']):
if engine['ready']:
ret.append(engine['id'])
ret.sort()
return ret
raise NotImplementedError
def print_models(self) -> None:
"""

View File

@ -204,6 +204,7 @@ class Chat:
output.append(message.to_str(source_code_only=True))
continue
output.append(message.to_str(with_tags, with_files))
output.append('\n' + ('-' * terminal_width()) + '\n')
if paged:
print_paged('\n'.join(output))
else:

View File

@ -1,8 +1,6 @@
import argparse
from pathlib import Path
from ..configuration import Config
from ..ai import AI
from ..ai_factory import create_ai
def config_cmd(args: argparse.Namespace) -> None:
@ -11,10 +9,3 @@ def config_cmd(args: argparse.Namespace) -> None:
"""
if args.create:
Config.create_default(Path(args.create))
elif args.list_models or args.print_model:
config: Config = Config.from_file(args.config)
ai: AI = create_ai(args, config)
if args.list_models:
ai.print_models()
else:
print(ai.config.model)

View File

@ -39,7 +39,6 @@ class AIConfig:
name: ClassVar[str]
# a user-defined ID for an AI configuration entry
ID: str
model: str = 'n/a'
# the name must not be changed
def __setattr__(self, name: str, value: Any) -> None:

View File

@ -100,7 +100,6 @@ def create_parser() -> argparse.ArgumentParser:
help="Manage configuration",
aliases=['c'])
config_cmd_parser.set_defaults(func=config_cmd)
config_cmd_parser.add_argument('-A', '--AI', help='AI ID to use')
config_group = config_cmd_parser.add_mutually_exclusive_group(required=True)
config_group.add_argument('-l', '--list-models', help="List all available models",
action='store_true')

View File

@ -6,7 +6,7 @@ from io import StringIO
from unittest.mock import patch
from chatmastermind.tags import TagLine
from chatmastermind.message import Message, Question, Answer, Tag, MessageFilter
from chatmastermind.chat import Chat, ChatDB, ChatError
from chatmastermind.chat import Chat, ChatDB, terminal_width, ChatError
class TestChat(unittest.TestCase):
@ -92,10 +92,16 @@ class TestChat(unittest.TestCase):
Question 1
{Answer.txt_header}
Answer 1
{'-'*terminal_width()}
{Question.txt_header}
Question 2
{Answer.txt_header}
Answer 2
{'-'*terminal_width()}
"""
self.assertEqual(mock_stdout.getvalue(), expected_output)
@ -109,12 +115,18 @@ FILE: 0001.txt
Question 1
{Answer.txt_header}
Answer 1
{'-'*terminal_width()}
{TagLine.prefix} btag2
FILE: 0002.txt
{Question.txt_header}
Question 2
{Answer.txt_header}
Answer 2
{'-'*terminal_width()}
"""
self.assertEqual(mock_stdout.getvalue(), expected_output)