From 458ec20cbd3f040b4d584af789b1e1d8556add8f Mon Sep 17 00:00:00 2001 From: Oleksandr Kozachuk Date: Sat, 9 Sep 2023 19:24:45 +0200 Subject: [PATCH 1/4] Make `cmm q -a "test"` completely work, similar as before, tests are not fixed yet. --- chatmastermind/ai.py | 6 ++++++ chatmastermind/ais/openai.py | 19 ++++++++++++++----- chatmastermind/chat.py | 4 +--- chatmastermind/commands/question.py | 14 +++++++++----- 4 files changed, 30 insertions(+), 13 deletions(-) diff --git a/chatmastermind/ai.py b/chatmastermind/ai.py index e94de8e..b97b5f1 100644 --- a/chatmastermind/ai.py +++ b/chatmastermind/ai.py @@ -66,3 +66,9 @@ class AI(Protocol): and is not implemented for all AIs. """ raise NotImplementedError + + def print(self) -> None: + """ + Print some info about the current AI, like system message. + """ + pass diff --git a/chatmastermind/ais/openai.py b/chatmastermind/ais/openai.py index 14ce33f..1db4d20 100644 --- a/chatmastermind/ais/openai.py +++ b/chatmastermind/ais/openai.py @@ -43,16 +43,20 @@ class OpenAI(AI): n=num_answers, frequency_penalty=self.config.frequency_penalty, presence_penalty=self.config.presence_penalty) - answers: list[Message] = [] - for choice in response['choices']: # type: ignore + question.answer = Answer(response['choices'][0]['message']['content']) + question.tags = otags + question.ai = self.name + question.model = self.config.model + answers: list[Message] = [question] + for choice in response['choices'][1:]: # type: ignore answers.append(Message(question=question.question, answer=Answer(choice['message']['content']), tags=otags, ai=self.name, model=self.config.model)) - return AIResponse(answers, Tokens(response['usage']['prompt'], - response['usage']['completion'], - response['usage']['total'])) + return AIResponse(answers, Tokens(response['usage']['prompt_tokens'], + response['usage']['completion_tokens'], + response['usage']['total_tokens'])) def models(self) -> list[str]: """ @@ -95,3 +99,8 @@ class OpenAI(AI): def tokens(self, data: Union[Message, Chat]) -> int: raise NotImplementedError + + def print(self) -> None: + print(f"MODEL: {self.config.model}") + print("=== SYSTEM ===") + print(self.config.system) diff --git a/chatmastermind/chat.py b/chatmastermind/chat.py index 4e8fb20..9a62d68 100644 --- a/chatmastermind/chat.py +++ b/chatmastermind/chat.py @@ -201,7 +201,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') + # output.append('\n' + ('-' * terminal_width()) + '\n') if paged: print_paged('\n'.join(output)) else: @@ -361,8 +361,6 @@ class ChatDB(Chat): Add the given new messages and set the file_path to the cache directory. Only accepts messages without a file_path. """ - if any(m.file_path is not None for m in messages): - raise ChatError("Can't add new messages with existing file_path") if write: write_dir(self.cache_path, messages, diff --git a/chatmastermind/commands/question.py b/chatmastermind/commands/question.py index 756a051..5f72c7e 100644 --- a/chatmastermind/commands/question.py +++ b/chatmastermind/commands/question.py @@ -63,15 +63,19 @@ def question_cmd(args: argparse.Namespace, config: Config) -> None: # create the correct AI instance ai: AI = create_ai(args, config) if args.ask: + ai.print() + chat.print(paged=False) response: AIResponse = ai.request(message, chat, args.num_answers, # FIXME args.output_tags) # FIXME - assert response - # TODO: - # * add answer to the message above (and create - # more messages for any additional answers) - pass + chat.add_to_cache(response.messages) + for idx, msg in enumerate(response.messages): + print(f"=== ANSWER {idx+1} ===") + print(msg.answer) + if response.tokens: + print("===============") + print(response.tokens) elif args.repeat: lmessage = chat.latest_message() assert lmessage -- 2.36.6 From be955c31e541bd68642f21bf70e57f8dfb690027 Mon Sep 17 00:00:00 2001 From: Oleksandr Kozachuk Date: Sat, 9 Sep 2023 19:52:43 +0200 Subject: [PATCH 2/4] Fix tests. --- tests/test_chat.py | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/tests/test_chat.py b/tests/test_chat.py index 8e4aa8c..342b109 100644 --- a/tests/test_chat.py +++ b/tests/test_chat.py @@ -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, terminal_width, ChatError +from chatmastermind.chat import Chat, ChatDB, ChatError class TestChat(unittest.TestCase): @@ -92,16 +92,10 @@ 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) @@ -115,18 +109,12 @@ 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) @@ -415,9 +403,6 @@ class TestChatDB(unittest.TestCase): db_dir_files = self.message_list(self.db_path) self.assertEqual(len(db_dir_files), 5) - with self.assertRaises(ChatError): - chat_db.add_to_cache([Message(Question("?"), file_path=pathlib.Path("foo"))]) - def test_chat_db_write_messages(self) -> None: # create a new ChatDB instance chat_db = ChatDB.from_dir(pathlib.Path(self.cache_path.name), -- 2.36.6 From 77a42367b52fcba9a17c6ca451ffe8487217845d Mon Sep 17 00:00:00 2001 From: Oleksandr Kozachuk Date: Sat, 9 Sep 2023 21:18:29 +0200 Subject: [PATCH 3/4] Fix the filter for `question -a` --- chatmastermind/commands/question.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/chatmastermind/commands/question.py b/chatmastermind/commands/question.py index 5f72c7e..110eaf3 100644 --- a/chatmastermind/commands/question.py +++ b/chatmastermind/commands/question.py @@ -3,7 +3,7 @@ from pathlib import Path from itertools import zip_longest from ..configuration import Config from ..chat import ChatDB -from ..message import Message, Question, source_code +from ..message import Message, MessageFilter, Question, source_code from ..ai_factory import create_ai from ..ai import AI, AIResponse @@ -52,8 +52,12 @@ def question_cmd(args: argparse.Namespace, config: Config) -> None: """ Handler for the 'question' command. """ + mfilter = MessageFilter(tags_or=args.or_tags, + tags_and=args.and_tags, + tags_not=args.exclude_tags) chat = ChatDB.from_dir(cache_path=Path('.'), - db_path=Path(config.db)) + db_path=Path(config.db), + mfilter=mfilter) # if it's a new question, create and store it immediately if args.ask or args.create: message = create_message(chat, args) @@ -76,14 +80,14 @@ def question_cmd(args: argparse.Namespace, config: Config) -> None: if response.tokens: print("===============") print(response.tokens) - elif args.repeat: + elif args.repeat is not None: lmessage = chat.latest_message() assert lmessage # TODO: repeat either the last question or the # one(s) given in 'args.repeat' (overwrite # existing ones if 'args.overwrite' is True) pass - elif args.process: + elif args.process is not None: # TODO: process either all questions without an # answer or the one(s) given in 'args.process' pass -- 2.36.6 From 0b2924303605de0ee9eda6bfd21369d13e9601c7 Mon Sep 17 00:00:00 2001 From: Oleksandr Kozachuk Date: Sat, 9 Sep 2023 21:37:48 +0200 Subject: [PATCH 4/4] Fix to use ID instead of name in message.ai. --- chatmastermind/ais/openai.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/chatmastermind/ais/openai.py b/chatmastermind/ais/openai.py index 1db4d20..a388a7a 100644 --- a/chatmastermind/ais/openai.py +++ b/chatmastermind/ais/openai.py @@ -45,14 +45,14 @@ class OpenAI(AI): presence_penalty=self.config.presence_penalty) question.answer = Answer(response['choices'][0]['message']['content']) question.tags = otags - question.ai = self.name + question.ai = self.ID question.model = self.config.model answers: list[Message] = [question] for choice in response['choices'][1:]: # type: ignore answers.append(Message(question=question.question, answer=Answer(choice['message']['content']), tags=otags, - ai=self.name, + ai=self.ID, model=self.config.model)) return AIResponse(answers, Tokens(response['usage']['prompt_tokens'], response['usage']['completion_tokens'], -- 2.36.6