Compare commits
2 Commits
bcb3a2d45a
...
0e00d25ef3
| Author | SHA1 | Date | |
|---|---|---|---|
| 0e00d25ef3 | |||
| 69d916f0cc |
@ -15,7 +15,7 @@ def hist_cmd(args: argparse.Namespace, config: Config) -> None:
|
|||||||
tags_not=args.exclude_tags,
|
tags_not=args.exclude_tags,
|
||||||
question_contains=args.question,
|
question_contains=args.question,
|
||||||
answer_contains=args.answer)
|
answer_contains=args.answer)
|
||||||
chat = ChatDB.from_dir(Path(config.cache),
|
chat = ChatDB.from_dir(Path('.'),
|
||||||
Path(config.db),
|
Path(config.db),
|
||||||
mfilter=mfilter)
|
mfilter=mfilter)
|
||||||
chat.print(args.source_code_only,
|
chat.print(args.source_code_only,
|
||||||
|
|||||||
@ -112,7 +112,7 @@ def question_cmd(args: argparse.Namespace, config: Config) -> None:
|
|||||||
mfilter = MessageFilter(tags_or=args.or_tags if args.or_tags is not None else set(),
|
mfilter = MessageFilter(tags_or=args.or_tags if args.or_tags is not None else set(),
|
||||||
tags_and=args.and_tags if args.and_tags is not None else set(),
|
tags_and=args.and_tags if args.and_tags is not None else set(),
|
||||||
tags_not=args.exclude_tags if args.exclude_tags is not None else set())
|
tags_not=args.exclude_tags if args.exclude_tags is not None else set())
|
||||||
chat = ChatDB.from_dir(cache_path=Path(config.cache),
|
chat = ChatDB.from_dir(cache_path=Path('.'),
|
||||||
db_path=Path(config.db),
|
db_path=Path(config.db),
|
||||||
mfilter=mfilter)
|
mfilter=mfilter)
|
||||||
# if it's a new question, create and store it immediately
|
# if it's a new question, create and store it immediately
|
||||||
|
|||||||
@ -8,7 +8,7 @@ def tags_cmd(args: argparse.Namespace, config: Config) -> None:
|
|||||||
"""
|
"""
|
||||||
Handler for the 'tags' command.
|
Handler for the 'tags' command.
|
||||||
"""
|
"""
|
||||||
chat = ChatDB.from_dir(cache_path=Path(config.cache),
|
chat = ChatDB.from_dir(cache_path=Path('.'),
|
||||||
db_path=Path(config.db))
|
db_path=Path(config.db))
|
||||||
if args.list:
|
if args.list:
|
||||||
tags_freq = chat.msg_tags_frequency(args.prefix, args.contain)
|
tags_freq = chat.msg_tags_frequency(args.prefix, args.contain)
|
||||||
|
|||||||
@ -116,7 +116,6 @@ class Config:
|
|||||||
"""
|
"""
|
||||||
# all members have default values, so we can easily create
|
# all members have default values, so we can easily create
|
||||||
# a default configuration
|
# a default configuration
|
||||||
cache: str = '.'
|
|
||||||
db: str = './db/'
|
db: str = './db/'
|
||||||
ais: dict[str, AIConfig] = field(default_factory=create_default_ai_configs)
|
ais: dict[str, AIConfig] = field(default_factory=create_default_ai_configs)
|
||||||
|
|
||||||
@ -133,7 +132,6 @@ class Config:
|
|||||||
ai_conf = ai_config_instance(conf['name'], conf)
|
ai_conf = ai_config_instance(conf['name'], conf)
|
||||||
ais[ID] = ai_conf
|
ais[ID] = ai_conf
|
||||||
return cls(
|
return cls(
|
||||||
cache=str(source['cache']) if 'cache' in source else '.',
|
|
||||||
db=str(source['db']),
|
db=str(source['db']),
|
||||||
ais=ais
|
ais=ais
|
||||||
)
|
)
|
||||||
|
|||||||
@ -57,7 +57,6 @@ class TestConfig(unittest.TestCase):
|
|||||||
|
|
||||||
def test_from_dict_should_create_config_from_dict(self) -> None:
|
def test_from_dict_should_create_config_from_dict(self) -> None:
|
||||||
source_dict = {
|
source_dict = {
|
||||||
'cache': '.',
|
|
||||||
'db': './test_db/',
|
'db': './test_db/',
|
||||||
'ais': {
|
'ais': {
|
||||||
'myopenai': {
|
'myopenai': {
|
||||||
@ -74,7 +73,6 @@ class TestConfig(unittest.TestCase):
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
config = Config.from_dict(source_dict)
|
config = Config.from_dict(source_dict)
|
||||||
self.assertEqual(config.cache, '.')
|
|
||||||
self.assertEqual(config.db, './test_db/')
|
self.assertEqual(config.db, './test_db/')
|
||||||
self.assertEqual(len(config.ais), 1)
|
self.assertEqual(len(config.ais), 1)
|
||||||
self.assertEqual(config.ais['myopenai'].name, 'openai')
|
self.assertEqual(config.ais['myopenai'].name, 'openai')
|
||||||
@ -91,7 +89,6 @@ class TestConfig(unittest.TestCase):
|
|||||||
|
|
||||||
def test_from_file_should_load_config_from_file(self) -> None:
|
def test_from_file_should_load_config_from_file(self) -> None:
|
||||||
source_dict = {
|
source_dict = {
|
||||||
'cache': './test_cache/',
|
|
||||||
'db': './test_db/',
|
'db': './test_db/',
|
||||||
'ais': {
|
'ais': {
|
||||||
'default': {
|
'default': {
|
||||||
@ -111,7 +108,6 @@ class TestConfig(unittest.TestCase):
|
|||||||
yaml.dump(source_dict, f)
|
yaml.dump(source_dict, f)
|
||||||
config = Config.from_file(self.test_file.name)
|
config = Config.from_file(self.test_file.name)
|
||||||
self.assertIsInstance(config, Config)
|
self.assertIsInstance(config, Config)
|
||||||
self.assertEqual(config.cache, './test_cache/')
|
|
||||||
self.assertEqual(config.db, './test_db/')
|
self.assertEqual(config.db, './test_db/')
|
||||||
self.assertEqual(len(config.ais), 1)
|
self.assertEqual(len(config.ais), 1)
|
||||||
self.assertIsInstance(config.ais['default'], AIConfig)
|
self.assertIsInstance(config.ais['default'], AIConfig)
|
||||||
@ -119,7 +115,6 @@ class TestConfig(unittest.TestCase):
|
|||||||
|
|
||||||
def test_to_file_should_save_config_to_file(self) -> None:
|
def test_to_file_should_save_config_to_file(self) -> None:
|
||||||
config = Config(
|
config = Config(
|
||||||
cache='./test_cache/',
|
|
||||||
db='./test_db/',
|
db='./test_db/',
|
||||||
ais={
|
ais={
|
||||||
'myopenai': OpenAIConfig(
|
'myopenai': OpenAIConfig(
|
||||||
@ -138,14 +133,12 @@ class TestConfig(unittest.TestCase):
|
|||||||
config.to_file(Path(self.test_file.name))
|
config.to_file(Path(self.test_file.name))
|
||||||
with open(self.test_file.name, 'r') as f:
|
with open(self.test_file.name, 'r') as f:
|
||||||
saved_config = yaml.load(f, Loader=yaml.FullLoader)
|
saved_config = yaml.load(f, Loader=yaml.FullLoader)
|
||||||
self.assertEqual(saved_config['cache'], './test_cache/')
|
|
||||||
self.assertEqual(saved_config['db'], './test_db/')
|
self.assertEqual(saved_config['db'], './test_db/')
|
||||||
self.assertEqual(len(saved_config['ais']), 1)
|
self.assertEqual(len(saved_config['ais']), 1)
|
||||||
self.assertEqual(saved_config['ais']['myopenai']['system'], 'Custom system')
|
self.assertEqual(saved_config['ais']['myopenai']['system'], 'Custom system')
|
||||||
|
|
||||||
def test_from_file_error_unknown_ai(self) -> None:
|
def test_from_file_error_unknown_ai(self) -> None:
|
||||||
source_dict = {
|
source_dict = {
|
||||||
'cache': './test_cache/',
|
|
||||||
'db': './test_db/',
|
'db': './test_db/',
|
||||||
'ais': {
|
'ais': {
|
||||||
'default': {
|
'default': {
|
||||||
|
|||||||
@ -4,13 +4,11 @@ import argparse
|
|||||||
import tempfile
|
import tempfile
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from unittest import mock
|
from unittest import mock
|
||||||
from unittest.mock import MagicMock, call, ANY
|
from unittest.mock import MagicMock, call
|
||||||
from typing import Optional
|
|
||||||
from chatmastermind.configuration import Config
|
from chatmastermind.configuration import Config
|
||||||
from chatmastermind.commands.question import create_message, question_cmd
|
from chatmastermind.commands.question import create_message, question_cmd
|
||||||
from chatmastermind.tags import Tag
|
|
||||||
from chatmastermind.message import Message, Question, Answer
|
from chatmastermind.message import Message, Question, Answer
|
||||||
from chatmastermind.chat import Chat, ChatDB
|
from chatmastermind.chat import ChatDB
|
||||||
from chatmastermind.ai import AI, AIResponse, Tokens
|
from chatmastermind.ai import AI, AIResponse, Tokens
|
||||||
|
|
||||||
|
|
||||||
@ -21,10 +19,10 @@ class TestMessageCreate(unittest.TestCase):
|
|||||||
"""
|
"""
|
||||||
def setUp(self) -> None:
|
def setUp(self) -> None:
|
||||||
# create ChatDB structure
|
# create ChatDB structure
|
||||||
self.db_dir = tempfile.TemporaryDirectory()
|
self.db_path = tempfile.TemporaryDirectory()
|
||||||
self.cache_dir = tempfile.TemporaryDirectory()
|
self.cache_path = tempfile.TemporaryDirectory()
|
||||||
self.chat = ChatDB.from_dir(cache_path=Path(self.cache_dir.name),
|
self.chat = ChatDB.from_dir(cache_path=Path(self.cache_path.name),
|
||||||
db_path=Path(self.db_dir.name))
|
db_path=Path(self.db_path.name))
|
||||||
# create some messages
|
# create some messages
|
||||||
self.message_text = Message(Question("What is this?"),
|
self.message_text = Message(Question("What is this?"),
|
||||||
Answer("It is pure text"))
|
Answer("It is pure text"))
|
||||||
@ -87,10 +85,10 @@ Aaaand again some text."""
|
|||||||
|
|
||||||
def test_message_file_created(self) -> None:
|
def test_message_file_created(self) -> None:
|
||||||
self.args.ask = ["What is this?"]
|
self.args.ask = ["What is this?"]
|
||||||
cache_dir_files = self.message_list(self.cache_dir)
|
cache_dir_files = self.message_list(self.cache_path)
|
||||||
self.assertEqual(len(cache_dir_files), 0)
|
self.assertEqual(len(cache_dir_files), 0)
|
||||||
create_message(self.chat, self.args)
|
create_message(self.chat, self.args)
|
||||||
cache_dir_files = self.message_list(self.cache_dir)
|
cache_dir_files = self.message_list(self.cache_path)
|
||||||
self.assertEqual(len(cache_dir_files), 1)
|
self.assertEqual(len(cache_dir_files), 1)
|
||||||
message = Message.from_file(cache_dir_files[0])
|
message = Message.from_file(cache_dir_files[0])
|
||||||
self.assertIsInstance(message, Message)
|
self.assertIsInstance(message, Message)
|
||||||
@ -205,12 +203,10 @@ class TestQuestionCmd(unittest.TestCase):
|
|||||||
|
|
||||||
def setUp(self) -> None:
|
def setUp(self) -> None:
|
||||||
# create DB and cache
|
# create DB and cache
|
||||||
self.db_dir = tempfile.TemporaryDirectory()
|
self.db_path = tempfile.TemporaryDirectory()
|
||||||
self.cache_dir = tempfile.TemporaryDirectory()
|
self.cache_path = tempfile.TemporaryDirectory()
|
||||||
# create configuration
|
# create configuration
|
||||||
self.config = Config()
|
self.config = Config()
|
||||||
self.config.cache = self.cache_dir.name
|
|
||||||
self.config.db = self.db_dir.name
|
|
||||||
# create a mock argparse.Namespace
|
# create a mock argparse.Namespace
|
||||||
self.args = argparse.Namespace(
|
self.args = argparse.Namespace(
|
||||||
ask=['What is the meaning of life?'],
|
ask=['What is the meaning of life?'],
|
||||||
@ -242,79 +238,36 @@ class TestQuestionCmd(unittest.TestCase):
|
|||||||
ai=args.AI,
|
ai=args.AI,
|
||||||
model=args.model)
|
model=args.model)
|
||||||
|
|
||||||
def mock_request(self,
|
def response(self, args: argparse.Namespace) -> AIResponse:
|
||||||
question: Message,
|
|
||||||
chat: Chat,
|
|
||||||
num_answers: int = 1,
|
|
||||||
otags: Optional[set[Tag]] = None) -> AIResponse:
|
|
||||||
"""
|
"""
|
||||||
Mock the 'ai.request()' function
|
Create the expected AI response from the give arguments.
|
||||||
"""
|
"""
|
||||||
question.answer = Answer("Answer 0")
|
input_msg = self.input_message(args)
|
||||||
question.tags = otags
|
response = AIResponse(messages=[], tokens=Tokens(10, 10, 20))
|
||||||
question.ai = 'FakeAI'
|
for n in range(args.num_answers):
|
||||||
question.model = 'FakeModel'
|
response_msg = Message(input_msg.question,
|
||||||
answers: list[Message] = [question]
|
Answer(f"Answer {n}"),
|
||||||
for n in range(1, num_answers):
|
tags=input_msg.tags,
|
||||||
answers.append(Message(question=question.question,
|
ai=input_msg.ai,
|
||||||
answer=Answer(f"Answer {n}"),
|
model=input_msg.model)
|
||||||
tags=otags,
|
response.messages.append(response_msg)
|
||||||
ai='FakeAI',
|
return response
|
||||||
model='FakeModel'))
|
|
||||||
return AIResponse(answers, Tokens(10, 10, 20))
|
|
||||||
|
|
||||||
def message_list(self, tmp_dir: tempfile.TemporaryDirectory) -> list[Path]:
|
|
||||||
# exclude '.next'
|
|
||||||
return sorted([f for f in Path(tmp_dir.name).glob('*.[ty]*')])
|
|
||||||
|
|
||||||
@mock.patch('chatmastermind.commands.question.create_ai')
|
|
||||||
def test_ask_single_answer(self, mock_create_ai: MagicMock) -> None:
|
|
||||||
"""
|
|
||||||
Test single answer with no errors
|
|
||||||
"""
|
|
||||||
# create a mock AI instance
|
|
||||||
ai = MagicMock(spec=AI)
|
|
||||||
ai.request.side_effect = self.mock_request
|
|
||||||
mock_create_ai.return_value = ai
|
|
||||||
expected_question = self.input_message(self.args)
|
|
||||||
expected_responses = self.mock_request(expected_question,
|
|
||||||
Chat([]),
|
|
||||||
self.args.num_answers,
|
|
||||||
self.args.output_tags).messages
|
|
||||||
|
|
||||||
# execute the command
|
|
||||||
question_cmd(self.args, self.config)
|
|
||||||
|
|
||||||
# check for correct request call
|
|
||||||
ai.request.assert_called_once_with(expected_question,
|
|
||||||
ANY,
|
|
||||||
self.args.num_answers,
|
|
||||||
self.args.output_tags)
|
|
||||||
# check for the expected message files
|
|
||||||
chat = ChatDB.from_dir(Path(self.cache_dir.name),
|
|
||||||
Path(self.db_dir.name))
|
|
||||||
cached_msg = chat.msg_gather(loc='cache')
|
|
||||||
self.assertEqual(len(self.message_list(self.cache_dir)), 1)
|
|
||||||
self.assertSequenceEqual(cached_msg, expected_responses)
|
|
||||||
|
|
||||||
@mock.patch('chatmastermind.commands.question.ChatDB.from_dir')
|
@mock.patch('chatmastermind.commands.question.ChatDB.from_dir')
|
||||||
@mock.patch('chatmastermind.commands.question.create_ai')
|
@mock.patch('chatmastermind.commands.question.create_ai')
|
||||||
def test_ask_single_answer_mocked(self, mock_create_ai: MagicMock, mock_from_dir: MagicMock) -> None:
|
def test_ask_single_answer(self, mock_create_ai: MagicMock, mock_from_dir: MagicMock) -> None:
|
||||||
"""
|
|
||||||
Test single answer with no errors (mocked ChatDB version)
|
# FIXME: this mock is only neccessary because the cache dir is not
|
||||||
"""
|
# configurable in the configuration file
|
||||||
chat = MagicMock(spec=ChatDB)
|
chat = MagicMock(spec=ChatDB)
|
||||||
mock_from_dir.return_value = chat
|
mock_from_dir.return_value = chat
|
||||||
|
|
||||||
# create a mock AI instance
|
# create a mock AI instance
|
||||||
ai = MagicMock(spec=AI)
|
ai = MagicMock(spec=AI)
|
||||||
ai.request.side_effect = self.mock_request
|
ai.request.return_value = self.response(self.args)
|
||||||
mock_create_ai.return_value = ai
|
mock_create_ai.return_value = ai
|
||||||
expected_question = self.input_message(self.args)
|
expected_question = self.input_message(self.args)
|
||||||
expected_responses = self.mock_request(expected_question,
|
expected_responses = ai.request.return_value.messages
|
||||||
Chat([]),
|
|
||||||
self.args.num_answers,
|
|
||||||
self.args.output_tags).messages
|
|
||||||
|
|
||||||
# execute the command
|
# execute the command
|
||||||
question_cmd(self.args, self.config)
|
question_cmd(self.args, self.config)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user