From 9692c19dcba5dcef0e2ff261f67f91374b0d5fc8 Mon Sep 17 00:00:00 2001 From: koji Date: Mon, 20 May 2024 16:09:14 -0400 Subject: [PATCH 1/9] feat(opentrons-ai-client): sned chat history to the backend instead only user prompt sned chat history to the backend instead only user prompt close AUTH-407 --- .../src/molecules/InputPrompt/index.tsx | 20 ++++++++++++++++--- opentrons-ai-client/src/resources/atoms.ts | 4 +++- opentrons-ai-client/src/resources/types.ts | 11 +++++++++- 3 files changed, 30 insertions(+), 5 deletions(-) diff --git a/opentrons-ai-client/src/molecules/InputPrompt/index.tsx b/opentrons-ai-client/src/molecules/InputPrompt/index.tsx index 3b5254a799c..d6c9fa5b2df 100644 --- a/opentrons-ai-client/src/molecules/InputPrompt/index.tsx +++ b/opentrons-ai-client/src/molecules/InputPrompt/index.tsx @@ -17,9 +17,13 @@ import { TYPOGRAPHY, } from '@opentrons/components' import { SendButton } from '../../atoms/SendButton' -import { preparedPromptAtom, chatDataAtom } from '../../resources/atoms' +import { + preparedPromptAtom, + chatDataAtom, + chatHistoryAtom, +} from '../../resources/atoms' -import type { ChatData } from '../../resources/types' +import type { Chat, ChatData } from '../../resources/types' const url = 'https://fk0py9eu3e.execute-api.us-east-2.amazonaws.com/sandbox/chat/completion' @@ -37,6 +41,7 @@ export function InputPrompt(): JSX.Element { }) const [preparedPrompt] = useAtom(preparedPromptAtom) const [, setChatData] = useAtom(chatDataAtom) + const [chatHistory, setChatHistory] = useAtom(chatHistoryAtom) const [submitted, setSubmitted] = React.useState(false) const [data, setData] = React.useState(null) @@ -63,8 +68,12 @@ export function InputPrompt(): JSX.Element { audience: 'sandbox-ai-api', }, }) + const message: Chat = { + role: 'user', + content: prompt, + } const postData = { - message: prompt, + messages: [...chatHistory, message], fake: false, } const headers = { @@ -87,6 +96,10 @@ export function InputPrompt(): JSX.Element { role: 'user', reply: userPrompt, } + setChatHistory(chatHistory => [ + ...chatHistory, + { role: 'user', content: userPrompt }, + ]) setChatData(chatData => [...chatData, userInput]) void fetchData(userPrompt) setSubmitted(true) @@ -104,6 +117,7 @@ export function InputPrompt(): JSX.Element { role, reply, } + setChatHistory(chatHistory => [...chatHistory, { role, content: reply }]) setChatData(chatData => [...chatData, assistantResponse]) setSubmitted(false) } diff --git a/opentrons-ai-client/src/resources/atoms.ts b/opentrons-ai-client/src/resources/atoms.ts index 98ebd7df6f1..bce42eb978b 100644 --- a/opentrons-ai-client/src/resources/atoms.ts +++ b/opentrons-ai-client/src/resources/atoms.ts @@ -1,9 +1,11 @@ // jotai's atoms import { atom } from 'jotai' -import type { ChatData } from './types' +import type { Chat, ChatData } from './types' /** preparedPromptAtom is for PromptButton */ export const preparedPromptAtom = atom('') /** ChatDataAtom is for chat data (user prompt and response from OpenAI API) */ export const chatDataAtom = atom([]) + +export const chatHistoryAtom = atom([]) diff --git a/opentrons-ai-client/src/resources/types.ts b/opentrons-ai-client/src/resources/types.ts index 16d9239ec68..600c9687043 100644 --- a/opentrons-ai-client/src/resources/types.ts +++ b/opentrons-ai-client/src/resources/types.ts @@ -1,8 +1,17 @@ +/** assistant: ChatGPT API, user: user */ +type Role = 'assistant' | 'user' export interface ChatData { /** assistant: ChatGPT API, user: user */ - role: 'assistant' | 'user' + role: Role /** content ChatGPT API return or user prompt */ reply: string /** for testing purpose will be removed and this is not used in the app */ fake?: boolean } + +export interface Chat { + /** assistant: ChatGPT API, user: user */ + role: Role + /** content ChatGPT API return or user prompt */ + content: string +} From 66636f6dd804794951623a536ca4576ec496ce00 Mon Sep 17 00:00:00 2001 From: koji Date: Mon, 20 May 2024 16:17:26 -0400 Subject: [PATCH 2/9] sorted items in i18n json --- .../src/assets/localization/en/protocol_generator.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opentrons-ai-client/src/assets/localization/en/protocol_generator.json b/opentrons-ai-client/src/assets/localization/en/protocol_generator.json index dea672fb39a..e38678eadf5 100644 --- a/opentrons-ai-client/src/assets/localization/en/protocol_generator.json +++ b/opentrons-ai-client/src/assets/localization/en/protocol_generator.json @@ -27,8 +27,8 @@ "share_your_thoughts": "Share your thoughts here", "side_panel_body": "Write a prompt in natural language to generate a Reagent Transfer or a PCR protocol for the OT-2 or Opentrons Flex using the Opentrons Python Protocol API.", "side_panel_header": "Use natural language to generate protocols with OpentronsAI powered by OpenAI", - "try_example_prompts": "Stuck? Try these example prompts to get started.", "simulate_description": "Once OpentronsAI has written your protocol, type `simulate` in the prompt box to try it out.", + "try_example_prompts": "Stuck? Try these example prompts to get started.", "type_your_prompt": "Type your prompt...", "well_allocations": "Well allocations: Describe where liquids should go in labware.", "what_if_you": "What if you don’t provide all of those pieces of information? OpentronsAI asks you to provide it!", From 8c881c6e5a3b74d4ae5b0da432d159a670e40062 Mon Sep 17 00:00:00 2001 From: koji Date: Tue, 21 May 2024 18:17:44 -0400 Subject: [PATCH 3/9] update backend payload type --- opentrons-ai-server/api/domain/openai_predict.py | 6 +++--- opentrons-ai-server/api/handler/function.py | 2 +- opentrons-ai-server/api/models/chat_request.py | 7 ++++++- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/opentrons-ai-server/api/domain/openai_predict.py b/opentrons-ai-server/api/domain/openai_predict.py index d6a0d7706c9..eae5f01e348 100644 --- a/opentrons-ai-server/api/domain/openai_predict.py +++ b/opentrons-ai-server/api/domain/openai_predict.py @@ -94,15 +94,15 @@ class atomic_descr(BaseModel): descriptions.append(x) return descriptions - def refine_response(self, assitant_message: str) -> str: - if assitant_message is None: + def refine_response(self, assistant_message: str) -> str: + if assistant_message is None: return "" system_message: ChatCompletionMessageParam = { "role": "system", "content": f"{general_rules_1}\n Please leave useful comments for each command.", } - user_message: ChatCompletionMessageParam = {"role": "user", "content": assitant_message} + user_message: ChatCompletionMessageParam = {"role": "user", "content": assistant_message} response = self.client.chat.completions.create( model=self.settings.OPENAI_MODEL_NAME, diff --git a/opentrons-ai-server/api/handler/function.py b/opentrons-ai-server/api/handler/function.py index 8bc0113c698..b9439ea99b1 100644 --- a/opentrons-ai-server/api/handler/function.py +++ b/opentrons-ai-server/api/handler/function.py @@ -29,7 +29,7 @@ def create_chat_completion(event: Dict[str, Any]) -> Dict[str, Any]: settings: Settings = Settings.build() openai: OpenAIPredict = OpenAIPredict(settings=settings) - response: Union[str, None] = openai.predict(prompt=body.message) + response: Union[str, None] = openai.predict(prompt=body.messag, chat_completion_message_params=body.chat_history) if response is None or response == "": return create_response(HTTPStatus.NO_CONTENT, ChatResponse(reply="No response was generated", fake=body.fake).model_dump()) diff --git a/opentrons-ai-server/api/models/chat_request.py b/opentrons-ai-server/api/models/chat_request.py index 77d714b234d..8d10631b366 100644 --- a/opentrons-ai-server/api/models/chat_request.py +++ b/opentrons-ai-server/api/models/chat_request.py @@ -1,6 +1,11 @@ from pydantic import BaseModel +from typing import List +class Chat(BaseModel): + role: str + content: str class ChatRequest(BaseModel): message: str - fake: bool + chat_history: List[Chat] + fake: bool \ No newline at end of file From c22af36e38e6c319ee01cc1b0cf3e4c3d7531d38 Mon Sep 17 00:00:00 2001 From: koji Date: Tue, 21 May 2024 19:19:10 -0400 Subject: [PATCH 4/9] chnage type name and fix test errors --- opentrons-ai-server/api/handler/function.py | 2 +- opentrons-ai-server/api/models/chat_request.py | 2 +- opentrons-ai-server/tests/test_chat_models.py | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/opentrons-ai-server/api/handler/function.py b/opentrons-ai-server/api/handler/function.py index b9439ea99b1..e9abebb00ee 100644 --- a/opentrons-ai-server/api/handler/function.py +++ b/opentrons-ai-server/api/handler/function.py @@ -29,7 +29,7 @@ def create_chat_completion(event: Dict[str, Any]) -> Dict[str, Any]: settings: Settings = Settings.build() openai: OpenAIPredict = OpenAIPredict(settings=settings) - response: Union[str, None] = openai.predict(prompt=body.messag, chat_completion_message_params=body.chat_history) + response: Union[str, None] = openai.predict(prompt=body.messag, chat_completion_message_params=body.history) if response is None or response == "": return create_response(HTTPStatus.NO_CONTENT, ChatResponse(reply="No response was generated", fake=body.fake).model_dump()) diff --git a/opentrons-ai-server/api/models/chat_request.py b/opentrons-ai-server/api/models/chat_request.py index 8d10631b366..85d20dc466f 100644 --- a/opentrons-ai-server/api/models/chat_request.py +++ b/opentrons-ai-server/api/models/chat_request.py @@ -7,5 +7,5 @@ class Chat(BaseModel): class ChatRequest(BaseModel): message: str - chat_history: List[Chat] + history: Optional[List[Chat]] = None fake: bool \ No newline at end of file diff --git a/opentrons-ai-server/tests/test_chat_models.py b/opentrons-ai-server/tests/test_chat_models.py index 4c5141cf13e..261da6def20 100644 --- a/opentrons-ai-server/tests/test_chat_models.py +++ b/opentrons-ai-server/tests/test_chat_models.py @@ -7,7 +7,7 @@ @pytest.mark.unit def test_chat_request_model() -> None: # Test valid data - request_data = {"message": "Hello", "fake": False} + request_data = {"message": "Hello", "chat_history":[] , "fake": False} request = ChatRequest(**request_data) assert request.message == "Hello" assert request.fake is False @@ -28,5 +28,5 @@ def test_chat_response_model() -> None: # Test invalid data with pytest.raises(ValidationError): - invalid_response_data = {"reply": 123, "fake": "false"} + invalid_response_data = {"reply": 123, "history": "history", "fake": "false"} ChatResponse(**invalid_response_data) From 7eb1a69f3a63e0c0a1b5fba775818b307f7913a8 Mon Sep 17 00:00:00 2001 From: koji Date: Tue, 21 May 2024 19:23:59 -0400 Subject: [PATCH 5/9] add Optional --- opentrons-ai-server/api/models/chat_request.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opentrons-ai-server/api/models/chat_request.py b/opentrons-ai-server/api/models/chat_request.py index 85d20dc466f..1eb1fab680d 100644 --- a/opentrons-ai-server/api/models/chat_request.py +++ b/opentrons-ai-server/api/models/chat_request.py @@ -1,5 +1,5 @@ from pydantic import BaseModel -from typing import List +from typing import List, Optional class Chat(BaseModel): role: str From 48bcf5285e14dcdee87faaa9c06f565dcd333469 Mon Sep 17 00:00:00 2001 From: koji Date: Tue, 21 May 2024 19:31:03 -0400 Subject: [PATCH 6/9] update Chat type --- opentrons-ai-server/api/models/chat_request.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/opentrons-ai-server/api/models/chat_request.py b/opentrons-ai-server/api/models/chat_request.py index 1eb1fab680d..a211157146b 100644 --- a/opentrons-ai-server/api/models/chat_request.py +++ b/opentrons-ai-server/api/models/chat_request.py @@ -1,4 +1,6 @@ from pydantic import BaseModel +from openai.types.chat import ChatCompletionMessageParam + from typing import List, Optional class Chat(BaseModel): @@ -7,5 +9,5 @@ class Chat(BaseModel): class ChatRequest(BaseModel): message: str - history: Optional[List[Chat]] = None + history: Optional[List[ChatCompletionMessageParam]] = None fake: bool \ No newline at end of file From 013d52453fb16852ed0396ca8000ec990c32f9f0 Mon Sep 17 00:00:00 2001 From: koji Date: Wed, 22 May 2024 15:25:46 -0400 Subject: [PATCH 7/9] fix body parsing part's typo --- opentrons-ai-server/api/handler/function.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opentrons-ai-server/api/handler/function.py b/opentrons-ai-server/api/handler/function.py index e9abebb00ee..a043e49ef08 100644 --- a/opentrons-ai-server/api/handler/function.py +++ b/opentrons-ai-server/api/handler/function.py @@ -29,7 +29,7 @@ def create_chat_completion(event: Dict[str, Any]) -> Dict[str, Any]: settings: Settings = Settings.build() openai: OpenAIPredict = OpenAIPredict(settings=settings) - response: Union[str, None] = openai.predict(prompt=body.messag, chat_completion_message_params=body.history) + response: Union[str, None] = openai.predict(prompt=body.message, chat_completion_message_params=body.history) if response is None or response == "": return create_response(HTTPStatus.NO_CONTENT, ChatResponse(reply="No response was generated", fake=body.fake).model_dump()) From e6d98b35abdd11c8604c6d69ffb4d10cfbb40ca3 Mon Sep 17 00:00:00 2001 From: koji Date: Wed, 22 May 2024 15:37:10 -0400 Subject: [PATCH 8/9] fix: updated files' format via format command --- opentrons-ai-server/api/models/chat_request.py | 8 +++++--- opentrons-ai-server/tests/test_chat_models.py | 2 +- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/opentrons-ai-server/api/models/chat_request.py b/opentrons-ai-server/api/models/chat_request.py index a211157146b..42bd7be40ee 100644 --- a/opentrons-ai-server/api/models/chat_request.py +++ b/opentrons-ai-server/api/models/chat_request.py @@ -1,13 +1,15 @@ -from pydantic import BaseModel +from typing import List, Optional + from openai.types.chat import ChatCompletionMessageParam +from pydantic import BaseModel -from typing import List, Optional class Chat(BaseModel): role: str content: str + class ChatRequest(BaseModel): message: str history: Optional[List[ChatCompletionMessageParam]] = None - fake: bool \ No newline at end of file + fake: bool diff --git a/opentrons-ai-server/tests/test_chat_models.py b/opentrons-ai-server/tests/test_chat_models.py index 261da6def20..aa18f113a49 100644 --- a/opentrons-ai-server/tests/test_chat_models.py +++ b/opentrons-ai-server/tests/test_chat_models.py @@ -7,7 +7,7 @@ @pytest.mark.unit def test_chat_request_model() -> None: # Test valid data - request_data = {"message": "Hello", "chat_history":[] , "fake": False} + request_data = {"message": "Hello", "chat_history": [], "fake": False} request = ChatRequest(**request_data) assert request.message == "Hello" assert request.fake is False From f790fa14506c62c02e52f956def5e02919fefed1 Mon Sep 17 00:00:00 2001 From: koji Date: Thu, 23 May 2024 10:11:00 -0400 Subject: [PATCH 9/9] remove unused lines --- opentrons-ai-client/src/molecules/ChatFooter/index.tsx | 3 --- opentrons-ai-client/src/organisms/ChatContainer/index.tsx | 2 +- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/opentrons-ai-client/src/molecules/ChatFooter/index.tsx b/opentrons-ai-client/src/molecules/ChatFooter/index.tsx index e28e758bb02..e33fa8772cd 100644 --- a/opentrons-ai-client/src/molecules/ChatFooter/index.tsx +++ b/opentrons-ai-client/src/molecules/ChatFooter/index.tsx @@ -5,7 +5,6 @@ import { COLORS, DIRECTION_COLUMN, Flex, - // POSITION_STICKY, SPACING, StyledText, TYPOGRAPHY, @@ -17,8 +16,6 @@ export function ChatFooter(): JSX.Element { return ( - +