From bdf76139e34280124215ad271f6518e9eaae5c12 Mon Sep 17 00:00:00 2001 From: josephedward <15126922+josephedward@users.noreply.github.com> Date: Sat, 4 May 2024 16:44:10 -0400 Subject: [PATCH 1/4] BUG: Chat History Defaults to Spanish Despite English Language Selected - added param that interpolates a language for the model to use, or defaults to english - added a test that iterates through the languages supported by the project --- backend/app/usecases/chat.py | 7 +++-- backend/tests/test_usecases/test_chat.py | 39 ++++++++++++++++++++++++ 2 files changed, 43 insertions(+), 3 deletions(-) diff --git a/backend/app/usecases/chat.py b/backend/app/usecases/chat.py index 0d3c6d0dc..06967b2fd 100644 --- a/backend/app/usecases/chat.py +++ b/backend/app/usecases/chat.py @@ -412,6 +412,7 @@ def chat(user_id: str, chat_input: ChatInput) -> ChatOutput: def propose_conversation_title( user_id: str, conversation_id: str, + language: str = "english", model: Literal[ "claude-instant-v1", "claude-v2", @@ -421,14 +422,14 @@ def propose_conversation_title( "mistral-7b-instruct", "mixtral-8x7b-instruct", "mistral-large", - ] = "claude-v3-haiku", + ] = "claude-v3-haiku" ) -> str: - PROMPT = """Reading the conversation above, what is the appropriate title for the conversation? When answering the title, please follow the rules below: + PROMPT = f"""Reading the conversation above, what is the appropriate title for the conversation? When answering the title, please follow the rules below: - Title length must be from 15 to 20 characters. - Prefer more specific title than general. Your title should always be distinct from others. - Return the conversation title only. DO NOT include any strings other than the title. -- Title must be in the same language as the conversation. +- Title must be in the {language} language. """ # Fetch existing conversation diff --git a/backend/tests/test_usecases/test_chat.py b/backend/tests/test_usecases/test_chat.py index ceb47bd20..68c324afa 100644 --- a/backend/tests/test_usecases/test_chat.py +++ b/backend/tests/test_usecases/test_chat.py @@ -46,6 +46,10 @@ create_test_private_bot, create_test_public_bot, ) +import pytest +from langdetect import detect +from pydantic import ValidationError + MODEL: type_model_name = "claude-instant-v1" MISTRAL_MODEL: type_model_name = "mistral-7b-instruct" @@ -525,6 +529,19 @@ def setUp(self) -> None: mistral_output: ChatOutput = chat(user_id="user1", chat_input=chat_input) self.mistral_output = mistral_output print(mistral_output) + + self.example_texts = { + 'en': "What are the top tourist attractions in New York?", + 'ja': "日本の有名な観光地はどこですか?", + 'ko': "서울의 주요 관광지는 어디인가요?", + 'es': "¿Cuáles son los principales destinos turísticos en España?", + 'zh-Hans': "中国的主要旅游景点在哪里?", + 'zh-Hant': "台灣的主要旅遊景點在哪裡?", + 'fr': "Quelles sont les principales attractions touristiques en France?", + 'de': "Was sind die Haupttouristenattraktionen in Deutschland?", + 'it': "Quali sono le principali attrazioni turistiche in Italia?" + } + def test_propose_title(self): title = propose_conversation_title("user1", self.output.conversation_id) @@ -533,6 +550,28 @@ def test_propose_title(self): def test_propose_title_mistral(self): title = propose_conversation_title("user1", self.mistral_output.conversation_id) print(f"[title]: {title}") + + def test_language_titles(self): + for lang_code, text in self.example_texts.items(): + with self.subTest(lang_code=lang_code): + # Mock your chat function or use the actual one if possible + chat_input = ChatInput( + conversation_id="test_conversation_id", + message=MessageInput( + role="user", + content=[Content(content_type="text", body=text)], + model="MODEL_NAME", # Replace with actual model variable + parent_message_id=None, + message_id=None + ), + bot_id=None + ) + output = chat(self.user_id, chat_input) + title, detected_language = propose_conversation_title(self.user_id, output.conversation_id, lang_code) + self.assertEqual(detected_language, lang_code, f"Expected language {lang_code}, but got {detected_language}") + detected_title_lang = detect(title) + self.assertEqual(detected_title_lang, lang_code, f"Title language mismatch: expected {lang_code}, detected {detected_title_lang}") + def tearDown(self) -> None: delete_conversation_by_id("user1", self.output.conversation_id) From 2722f6f1f5b929017f3cd03cc68013bd9a00b6dd Mon Sep 17 00:00:00 2001 From: josephedward <15126922+josephedward@users.noreply.github.com> Date: Wed, 8 May 2024 13:50:16 -0400 Subject: [PATCH 2/4] BUG: language parameter Black formatted --- backend/app/usecases/chat.py | 2 +- backend/tests/test_usecases/test_chat.py | 72 +++++++++++++----------- 2 files changed, 41 insertions(+), 33 deletions(-) diff --git a/backend/app/usecases/chat.py b/backend/app/usecases/chat.py index 06967b2fd..bcd6cf945 100644 --- a/backend/app/usecases/chat.py +++ b/backend/app/usecases/chat.py @@ -422,7 +422,7 @@ def propose_conversation_title( "mistral-7b-instruct", "mixtral-8x7b-instruct", "mistral-large", - ] = "claude-v3-haiku" + ] = "claude-v3-haiku", ) -> str: PROMPT = f"""Reading the conversation above, what is the appropriate title for the conversation? When answering the title, please follow the rules below: diff --git a/backend/tests/test_usecases/test_chat.py b/backend/tests/test_usecases/test_chat.py index 68c324afa..575a37859 100644 --- a/backend/tests/test_usecases/test_chat.py +++ b/backend/tests/test_usecases/test_chat.py @@ -529,20 +529,19 @@ def setUp(self) -> None: mistral_output: ChatOutput = chat(user_id="user1", chat_input=chat_input) self.mistral_output = mistral_output print(mistral_output) - + self.example_texts = { - 'en': "What are the top tourist attractions in New York?", - 'ja': "日本の有名な観光地はどこですか?", - 'ko': "서울의 주요 관광지는 어디인가요?", - 'es': "¿Cuáles son los principales destinos turísticos en España?", - 'zh-Hans': "中国的主要旅游景点在哪里?", - 'zh-Hant': "台灣的主要旅遊景點在哪裡?", - 'fr': "Quelles sont les principales attractions touristiques en France?", - 'de': "Was sind die Haupttouristenattraktionen in Deutschland?", - 'it': "Quali sono le principali attrazioni turistiche in Italia?" + "en": "What are the top tourist attractions in New York?", + "ja": "日本の有名な観光地はどこですか?", + "ko": "서울의 주요 관광지는 어디인가요?", + "es": "¿Cuáles son los principales destinos turísticos en España?", + "zh-Hans": "中国的主要旅游景点在哪里?", + "zh-Hant": "台灣的主要旅遊景點在哪裡?", + "fr": "Quelles sont les principales attractions touristiques en France?", + "de": "Was sind die Haupttouristenattraktionen in Deutschland?", + "it": "Quali sono le principali attrazioni turistiche in Italia?", } - def test_propose_title(self): title = propose_conversation_title("user1", self.output.conversation_id) print(f"[title]: {title}") @@ -550,28 +549,37 @@ def test_propose_title(self): def test_propose_title_mistral(self): title = propose_conversation_title("user1", self.mistral_output.conversation_id) print(f"[title]: {title}") - - def test_language_titles(self): - for lang_code, text in self.example_texts.items(): - with self.subTest(lang_code=lang_code): - # Mock your chat function or use the actual one if possible - chat_input = ChatInput( - conversation_id="test_conversation_id", - message=MessageInput( - role="user", - content=[Content(content_type="text", body=text)], - model="MODEL_NAME", # Replace with actual model variable - parent_message_id=None, - message_id=None - ), - bot_id=None - ) - output = chat(self.user_id, chat_input) - title, detected_language = propose_conversation_title(self.user_id, output.conversation_id, lang_code) - self.assertEqual(detected_language, lang_code, f"Expected language {lang_code}, but got {detected_language}") - detected_title_lang = detect(title) - self.assertEqual(detected_title_lang, lang_code, f"Title language mismatch: expected {lang_code}, detected {detected_title_lang}") + def test_language_titles(self): + for lang_code, text in self.example_texts.items(): + with self.subTest(lang_code=lang_code): + # Mock your chat function or use the actual one if possible + chat_input = ChatInput( + conversation_id="test_conversation_id", + message=MessageInput( + role="user", + content=[Content(content_type="text", body=text)], + model="MODEL_NAME", # Replace with actual model variable + parent_message_id=None, + message_id=None, + ), + bot_id=None, + ) + output = chat(self.user_id, chat_input) + title, detected_language = propose_conversation_title( + self.user_id, output.conversation_id, lang_code + ) + self.assertEqual( + detected_language, + lang_code, + f"Expected language {lang_code}, but got {detected_language}", + ) + detected_title_lang = detect(title) + self.assertEqual( + detected_title_lang, + lang_code, + f"Title language mismatch: expected {lang_code}, detected {detected_title_lang}", + ) def tearDown(self) -> None: delete_conversation_by_id("user1", self.output.conversation_id) From 66cc309d8c3b7a3cd08339b033bcc645b594a0be Mon Sep 17 00:00:00 2001 From: josephedward <15126922+josephedward@users.noreply.github.com> Date: Mon, 20 May 2024 02:40:06 -0400 Subject: [PATCH 3/4] BUG: propose-title-language - added useTranslation hook to useConversationApi.ts - updated the interpolation text in propose_conversation_title in chat.py - added a URL segment corresponding to the lanugage param in conversaption.py --- backend/app/routes/conversation.py | 2 +- backend/app/usecases/chat.py | 4 ++-- frontend/src/hooks/useConversationApi.ts | 12 ++++++++++-- 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/backend/app/routes/conversation.py b/backend/app/routes/conversation.py index 18500b68e..60049565f 100644 --- a/backend/app/routes/conversation.py +++ b/backend/app/routes/conversation.py @@ -115,7 +115,7 @@ def patch_conversation_title( @router.get( - "/conversation/{conversation_id}/proposed-title", response_model=ProposedTitle + "/conversation/{conversation_id}/proposed-title/{language}", response_model=ProposedTitle ) def get_proposed_title(request: Request, conversation_id: str): """Suggest conversation title""" diff --git a/backend/app/usecases/chat.py b/backend/app/usecases/chat.py index bcd6cf945..febee808f 100644 --- a/backend/app/usecases/chat.py +++ b/backend/app/usecases/chat.py @@ -412,7 +412,7 @@ def chat(user_id: str, chat_input: ChatInput) -> ChatOutput: def propose_conversation_title( user_id: str, conversation_id: str, - language: str = "english", + language: str = "en", model: Literal[ "claude-instant-v1", "claude-v2", @@ -429,7 +429,7 @@ def propose_conversation_title( - Title length must be from 15 to 20 characters. - Prefer more specific title than general. Your title should always be distinct from others. - Return the conversation title only. DO NOT include any strings other than the title. -- Title must be in the {language} language. +- Title must be in {language}. """ # Fetch existing conversation diff --git a/frontend/src/hooks/useConversationApi.ts b/frontend/src/hooks/useConversationApi.ts index e21e3b19f..7e0f0a02f 100644 --- a/frontend/src/hooks/useConversationApi.ts +++ b/frontend/src/hooks/useConversationApi.ts @@ -8,11 +8,18 @@ import { PostMessageResponse, } from '../@types/conversation'; import useHttp from './useHttp'; +import { useTranslation } from 'react-i18next'; +import '../i18n'; + const useConversationApi = () => { const http = useHttp(); const { mutate } = useSWRConfig(); + + const { i18n } = useTranslation(); + const currentLanguage = i18n.language + const updateTitle = (conversationId: string, title: string) => { return http.patch(`conversation/${conversationId}/title`, { newTitle: title, @@ -53,10 +60,11 @@ const useConversationApi = () => { return http.delete('conversations'); }, updateTitle, - updateTitleWithGeneratedTitle: async (conversationId: string) => { + updateTitleWithGeneratedTitle: async (conversationId: string, currentLanguage: string = "en") => { + const res = await http.getOnce<{ title: string; - }>(`conversation/${conversationId}/proposed-title`); + }>(`conversation/${conversationId}/proposed-title/${currentLanguage}`); return updateTitle(conversationId, res.data.title); }, mutateConversations: ( From 250a9bc4a204c8075fd9403121d990789b538e8b Mon Sep 17 00:00:00 2001 From: josephedward <15126922+josephedward@users.noreply.github.com> Date: Mon, 20 May 2024 09:57:40 -0400 Subject: [PATCH 4/4] WIP: update formatting and var name --- backend/app/routes/conversation.py | 3 ++- frontend/src/hooks/useConversationApi.ts | 8 +++++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/backend/app/routes/conversation.py b/backend/app/routes/conversation.py index 60049565f..d65c76c5f 100644 --- a/backend/app/routes/conversation.py +++ b/backend/app/routes/conversation.py @@ -115,7 +115,8 @@ def patch_conversation_title( @router.get( - "/conversation/{conversation_id}/proposed-title/{language}", response_model=ProposedTitle + "/conversation/{conversation_id}/proposed-title/{language}", + response_model=ProposedTitle, ) def get_proposed_title(request: Request, conversation_id: str): """Suggest conversation title""" diff --git a/frontend/src/hooks/useConversationApi.ts b/frontend/src/hooks/useConversationApi.ts index 7e0f0a02f..ff8ee0dbf 100644 --- a/frontend/src/hooks/useConversationApi.ts +++ b/frontend/src/hooks/useConversationApi.ts @@ -60,11 +60,13 @@ const useConversationApi = () => { return http.delete('conversations'); }, updateTitle, - updateTitleWithGeneratedTitle: async (conversationId: string, currentLanguage: string = "en") => { - + updateTitleWithGeneratedTitle: async (conversationId: string, language: string = "en") => { + + language = currentLanguage.toLowerCase(); + const res = await http.getOnce<{ title: string; - }>(`conversation/${conversationId}/proposed-title/${currentLanguage}`); + }>(`conversation/${conversationId}/proposed-title/${language}`); return updateTitle(conversationId, res.data.title); }, mutateConversations: (