Compare commits
No commits in common. "8f563998443268ed9aab521397e1cf91314faa8f" and "e19c6bb1ea06be626fcd84ab61b614a316fa2a24" have entirely different histories.
8f56399844
...
e19c6bb1ea
13
README.md
13
README.md
@ -68,21 +68,20 @@ cmm question [-t OTAGS]... [-k ATAGS]... [-x XTAGS]... [-o OUTTAGS]... [-A AI_ID
|
|||||||
|
|
||||||
#### Hist
|
#### Hist
|
||||||
|
|
||||||
The `hist` command is used to print and manage the chat history.
|
The `hist` command is used to print the chat history.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cmm hist [--print | --convert FORMAT] [-t OTAGS]... [-k ATAGS]... [-x XTAGS]... [-w] [-W] [-S] [-A SUBSTRING] [-Q SUBSTRING]
|
cmm hist [-t OTAGS]... [-k ATAGS]... [-x XTAGS]... [-w] [-W] [-S] [-A SUBSTRING] [-Q SUBSTRING]
|
||||||
```
|
```
|
||||||
|
|
||||||
* `-p, --print`: Print the DB chat history
|
|
||||||
* `-c, --convert FORMAT`: Convert all messages to the given format
|
|
||||||
* `-t, --or-tags OTAGS`: List of tags (one must match)
|
* `-t, --or-tags OTAGS`: List of tags (one must match)
|
||||||
* `-k, --and-tags ATAGS`: List of tags (all must match)
|
* `-k, --and-tags ATAGS`: List of tags (all must match)
|
||||||
* `-x, --exclude-tags XTAGS`: List of tags to exclude
|
* `-x, --exclude-tags XTAGS`: List of tags to exclude
|
||||||
* `-w, --with-metadata`: Print chat history with metadata (tags, filenames, AI, etc.)
|
* `-w, --with-tags`: Print chat history with tags
|
||||||
|
* `-W, --with-files`: Print chat history with filenames
|
||||||
* `-S, --source-code-only`: Only print embedded source code
|
* `-S, --source-code-only`: Only print embedded source code
|
||||||
* `-A, --answer SUBSTRING`: Filter for answer substring
|
* `-A, --answer SUBSTRING`: Search for answer substring
|
||||||
* `-Q, --question SUBSTRING`: Filter for question substring
|
* `-Q, --question SUBSTRING`: Search for question substring
|
||||||
|
|
||||||
#### Tags
|
#### Tags
|
||||||
|
|
||||||
|
|||||||
@ -255,14 +255,14 @@ class Chat:
|
|||||||
return sum(m.tokens() for m in self.messages)
|
return sum(m.tokens() for m in self.messages)
|
||||||
|
|
||||||
def print(self, source_code_only: bool = False,
|
def print(self, source_code_only: bool = False,
|
||||||
with_metadata: bool = False,
|
with_tags: bool = False, with_files: bool = False,
|
||||||
paged: bool = True) -> None:
|
paged: bool = True) -> None:
|
||||||
output: list[str] = []
|
output: list[str] = []
|
||||||
for message in self.messages:
|
for message in self.messages:
|
||||||
if source_code_only:
|
if source_code_only:
|
||||||
output.append(message.to_str(source_code_only=True))
|
output.append(message.to_str(source_code_only=True))
|
||||||
continue
|
continue
|
||||||
output.append(message.to_str(with_metadata))
|
output.append(message.to_str(with_tags, with_files))
|
||||||
if paged:
|
if paged:
|
||||||
print_paged('\n'.join(output))
|
print_paged('\n'.join(output))
|
||||||
else:
|
else:
|
||||||
|
|||||||
@ -57,7 +57,8 @@ def print_chat(args: argparse.Namespace, config: Config) -> None:
|
|||||||
Path(config.db),
|
Path(config.db),
|
||||||
mfilter=mfilter)
|
mfilter=mfilter)
|
||||||
chat.print(args.source_code_only,
|
chat.print(args.source_code_only,
|
||||||
args.with_metadata)
|
args.with_tags,
|
||||||
|
args.with_files)
|
||||||
|
|
||||||
|
|
||||||
def hist_cmd(args: argparse.Namespace, config: Config) -> None:
|
def hist_cmd(args: argparse.Namespace, config: Config) -> None:
|
||||||
|
|||||||
@ -79,7 +79,9 @@ def create_parser() -> argparse.ArgumentParser:
|
|||||||
hist_group = hist_cmd_parser.add_mutually_exclusive_group(required=True)
|
hist_group = hist_cmd_parser.add_mutually_exclusive_group(required=True)
|
||||||
hist_group.add_argument('-p', '--print', help='Print the DB chat history', action='store_true')
|
hist_group.add_argument('-p', '--print', help='Print the DB chat history', action='store_true')
|
||||||
hist_group.add_argument('-c', '--convert', help='Convert all message files to the given format [txt|yaml]', metavar='FORMAT')
|
hist_group.add_argument('-c', '--convert', help='Convert all message files to the given format [txt|yaml]', metavar='FORMAT')
|
||||||
hist_cmd_parser.add_argument('-w', '--with-metadata', help="Print chat history with metadata (tags, filename, AI, etc.).",
|
hist_cmd_parser.add_argument('-w', '--with-tags', help="Print chat history with tags.",
|
||||||
|
action='store_true')
|
||||||
|
hist_cmd_parser.add_argument('-W', '--with-files', help="Print chat history with filenames.",
|
||||||
action='store_true')
|
action='store_true')
|
||||||
hist_cmd_parser.add_argument('-S', '--source-code-only', help='Only print embedded source code',
|
hist_cmd_parser.add_argument('-S', '--source-code-only', help='Only print embedded source code',
|
||||||
action='store_true')
|
action='store_true')
|
||||||
|
|||||||
@ -422,7 +422,7 @@ class Message():
|
|||||||
except Exception:
|
except Exception:
|
||||||
raise MessageError(f"'{file_path}' does not contain a valid message")
|
raise MessageError(f"'{file_path}' does not contain a valid message")
|
||||||
|
|
||||||
def to_str(self, with_metadata: bool = False, source_code_only: bool = False) -> str:
|
def to_str(self, with_tags: bool = False, with_file: bool = False, source_code_only: bool = False) -> str:
|
||||||
"""
|
"""
|
||||||
Return the current Message as a string.
|
Return the current Message as a string.
|
||||||
"""
|
"""
|
||||||
@ -432,11 +432,10 @@ class Message():
|
|||||||
if self.answer:
|
if self.answer:
|
||||||
output.extend(self.answer.source_code(include_delims=True))
|
output.extend(self.answer.source_code(include_delims=True))
|
||||||
return '\n'.join(output) if len(output) > 0 else ''
|
return '\n'.join(output) if len(output) > 0 else ''
|
||||||
if with_metadata:
|
if with_tags:
|
||||||
output.append(self.tags_str())
|
output.append(self.tags_str())
|
||||||
|
if with_file:
|
||||||
output.append('FILE: ' + str(self.file_path))
|
output.append('FILE: ' + str(self.file_path))
|
||||||
output.append('AI: ' + str(self.ai))
|
|
||||||
output.append('MODEL: ' + str(self.model))
|
|
||||||
output.append(Question.txt_header)
|
output.append(Question.txt_header)
|
||||||
output.append(self.question)
|
output.append(self.question)
|
||||||
if self.answer:
|
if self.answer:
|
||||||
|
|||||||
@ -41,14 +41,10 @@ class TestChat(TestChatBase):
|
|||||||
self.message1 = Message(Question('Question 1'),
|
self.message1 = Message(Question('Question 1'),
|
||||||
Answer('Answer 1'),
|
Answer('Answer 1'),
|
||||||
{Tag('atag1'), Tag('btag2')},
|
{Tag('atag1'), Tag('btag2')},
|
||||||
ai='FakeAI',
|
|
||||||
model='FakeModel',
|
|
||||||
file_path=pathlib.Path(f'0001{msg_suffix}'))
|
file_path=pathlib.Path(f'0001{msg_suffix}'))
|
||||||
self.message2 = Message(Question('Question 2'),
|
self.message2 = Message(Question('Question 2'),
|
||||||
Answer('Answer 2'),
|
Answer('Answer 2'),
|
||||||
{Tag('btag2')},
|
{Tag('btag2')},
|
||||||
ai='FakeAI',
|
|
||||||
model='FakeModel',
|
|
||||||
file_path=pathlib.Path(f'0002{msg_suffix}'))
|
file_path=pathlib.Path(f'0002{msg_suffix}'))
|
||||||
self.maxDiff = None
|
self.maxDiff = None
|
||||||
|
|
||||||
@ -160,21 +156,17 @@ Answer 2
|
|||||||
self.assertEqual(mock_stdout.getvalue(), expected_output)
|
self.assertEqual(mock_stdout.getvalue(), expected_output)
|
||||||
|
|
||||||
@patch('sys.stdout', new_callable=StringIO)
|
@patch('sys.stdout', new_callable=StringIO)
|
||||||
def test_print_with_metadata(self, mock_stdout: StringIO) -> None:
|
def test_print_with_tags_and_file(self, mock_stdout: StringIO) -> None:
|
||||||
self.chat.msg_add([self.message1, self.message2])
|
self.chat.msg_add([self.message1, self.message2])
|
||||||
self.chat.print(paged=False, with_metadata=True)
|
self.chat.print(paged=False, with_tags=True, with_files=True)
|
||||||
expected_output = f"""{TagLine.prefix} atag1 btag2
|
expected_output = f"""{TagLine.prefix} atag1 btag2
|
||||||
FILE: 0001{msg_suffix}
|
FILE: 0001{msg_suffix}
|
||||||
AI: FakeAI
|
|
||||||
MODEL: FakeModel
|
|
||||||
{Question.txt_header}
|
{Question.txt_header}
|
||||||
Question 1
|
Question 1
|
||||||
{Answer.txt_header}
|
{Answer.txt_header}
|
||||||
Answer 1
|
Answer 1
|
||||||
{TagLine.prefix} btag2
|
{TagLine.prefix} btag2
|
||||||
FILE: 0002{msg_suffix}
|
FILE: 0002{msg_suffix}
|
||||||
AI: FakeAI
|
|
||||||
MODEL: FakeModel
|
|
||||||
{Question.txt_header}
|
{Question.txt_header}
|
||||||
Question 2
|
Question 2
|
||||||
{Answer.txt_header}
|
{Answer.txt_header}
|
||||||
|
|||||||
@ -856,8 +856,6 @@ class MessageToStrTestCase(unittest.TestCase):
|
|||||||
def setUp(self) -> None:
|
def setUp(self) -> None:
|
||||||
self.message = Message(Question('This is a question.'),
|
self.message = Message(Question('This is a question.'),
|
||||||
Answer('This is an answer.'),
|
Answer('This is an answer.'),
|
||||||
ai=('FakeAI'),
|
|
||||||
model=('FakeModel'),
|
|
||||||
tags={Tag('atag1'), Tag('btag2')},
|
tags={Tag('atag1'), Tag('btag2')},
|
||||||
file_path=pathlib.Path('/tmp/foo/bla'))
|
file_path=pathlib.Path('/tmp/foo/bla'))
|
||||||
|
|
||||||
@ -871,13 +869,11 @@ This is an answer."""
|
|||||||
def test_to_str_with_tags_and_file(self) -> None:
|
def test_to_str_with_tags_and_file(self) -> None:
|
||||||
expected_output = f"""{TagLine.prefix} atag1 btag2
|
expected_output = f"""{TagLine.prefix} atag1 btag2
|
||||||
FILE: /tmp/foo/bla
|
FILE: /tmp/foo/bla
|
||||||
AI: FakeAI
|
|
||||||
MODEL: FakeModel
|
|
||||||
{Question.txt_header}
|
{Question.txt_header}
|
||||||
This is a question.
|
This is a question.
|
||||||
{Answer.txt_header}
|
{Answer.txt_header}
|
||||||
This is an answer."""
|
This is an answer."""
|
||||||
self.assertEqual(self.message.to_str(with_metadata=True), expected_output)
|
self.assertEqual(self.message.to_str(with_tags=True, with_file=True), expected_output)
|
||||||
|
|
||||||
|
|
||||||
class MessageRmFileTestCase(unittest.TestCase):
|
class MessageRmFileTestCase(unittest.TestCase):
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user