From 5f271e6333ead17efefe4d14c570c03f4c87509a Mon Sep 17 00:00:00 2001 From: Tami Takamiya Date: Thu, 9 Jan 2025 12:39:32 -0500 Subject: [PATCH] Add System Prompt modal to chatbot debug UI (#1482) * Add System Prompt modal to chatbot debug UI * Fix issues --- .../ai/api/model_pipelines/http/pipelines.py | 3 + .../src/AnsibleChatbot/AnsibleChatbot.tsx | 17 +++- ansible_ai_connect_chatbot/src/App.test.tsx | 41 ++++++++- ansible_ai_connect_chatbot/src/Constants.ts | 18 ++++ .../SystemPromptModal/SystemPromptModal.tsx | 85 ++++++++++++++++++ .../Test-system-prompt-override-1.png | Bin 0 -> 88752 bytes .../src/types/Message.ts | 1 + .../src/useChatbot/useChatbot.ts | 8 ++ 8 files changed, 170 insertions(+), 3 deletions(-) create mode 100644 ansible_ai_connect_chatbot/src/SystemPromptModal/SystemPromptModal.tsx create mode 100644 ansible_ai_connect_chatbot/src/__screenshots__/App.test.tsx/Test-system-prompt-override-1.png diff --git a/ansible_ai_connect/ai/api/model_pipelines/http/pipelines.py b/ansible_ai_connect/ai/api/model_pipelines/http/pipelines.py index 107583538..3ce05be77 100644 --- a/ansible_ai_connect/ai/api/model_pipelines/http/pipelines.py +++ b/ansible_ai_connect/ai/api/model_pipelines/http/pipelines.py @@ -131,6 +131,7 @@ def invoke(self, params: ChatBotParameters) -> ChatBotResponse: conversation_id = params.conversation_id provider = params.provider model_id = params.model_id + system_prompt = params.system_prompt data = { "query": query, @@ -139,6 +140,8 @@ def invoke(self, params: ChatBotParameters) -> ChatBotResponse: } if conversation_id: data["conversation_id"] = str(conversation_id) + if system_prompt: + data["system_prompt"] = str(system_prompt) response = requests.post( self.config.inference_url + "/v1/query", diff --git a/ansible_ai_connect_chatbot/src/AnsibleChatbot/AnsibleChatbot.tsx b/ansible_ai_connect_chatbot/src/AnsibleChatbot/AnsibleChatbot.tsx index 036c55fbd..f5a052cf0 100644 --- a/ansible_ai_connect_chatbot/src/AnsibleChatbot/AnsibleChatbot.tsx +++ b/ansible_ai_connect_chatbot/src/AnsibleChatbot/AnsibleChatbot.tsx @@ -55,6 +55,7 @@ import { FOOTNOTE_LABEL, FOOTNOTE_TITLE, } from "../Constants"; +import { SystemPromptModal } from "../SystemPromptModal/SystemPromptModal"; const footnoteProps = { label: FOOTNOTE_LABEL, @@ -88,6 +89,8 @@ export const AnsibleChatbot: React.FunctionComponent = () => { selectedModel, setSelectedModel, setConversationId, + systemPrompt, + setSystemPrompt, } = useChatbot(); const [chatbotVisible, setChatbotVisible] = useState(true); const [displayMode, setDisplayMode] = useState( @@ -209,6 +212,12 @@ export const AnsibleChatbot: React.FunctionComponent = () => { setConversationId(undefined); }} /> + {inDebugMode() && ( + + )} {/* alert("Menu toggle clicked")} @@ -291,11 +300,15 @@ export const AnsibleChatbot: React.FunctionComponent = () => { )} {messages.map( ( - { referenced_documents, ...message }: ExtendedMessage, + { + referenced_documents, + scrollToHere, + ...message + }: ExtendedMessage, index, ) => ( <> - {message.scrollToHere &&
} + {scrollToHere &&
}
{ }); test("Basic chatbot interaction", async () => { - mockAxios(200); + const spy = mockAxios(200); const view = await renderApp(); const textArea = page.getByLabelText("Send a message..."); await textArea.fill("Hello"); await userEvent.keyboard("{Enter}"); + expect(spy).toHaveBeenCalledWith( + expect.anything(), + expect.objectContaining({ + conversation_id: undefined, + query: "Hello", + }), + expect.anything(), + ); + await expect .element( view.getByText( @@ -404,3 +414,32 @@ test("Debug mode test", async () => { .toBeVisible(); await expect.element(page.getByText("Create variables")).toBeVisible(); }); + +test("Test system prompt override", async () => { + const spy = mockAxios(200); + await renderApp(true); + + const systemPromptIcon = page.getByLabelText("SystemPrompt"); + await systemPromptIcon.click(); + + const systemPromptTextArea = page.getByLabelText( + "system-prompt-form-text-area", + ); + await systemPromptTextArea.fill("MY SYSTEM PROMPT"); + const systemPromptButton = page.getByLabelText("system-prompt-form-button"); + await systemPromptButton.click(); + + const textArea = page.getByLabelText("Send a message..."); + await textArea.fill("Hello with system prompt override"); + + await userEvent.keyboard("{Enter}"); + expect(spy).toHaveBeenCalledWith( + expect.anything(), + expect.objectContaining({ + conversation_id: undefined, + query: "Hello with system prompt override", + system_prompt: "MY SYSTEM PROMPT", + }), + expect.anything(), + ); +}); diff --git a/ansible_ai_connect_chatbot/src/Constants.ts b/ansible_ai_connect_chatbot/src/Constants.ts index 0b1dd3d4d..817d0f4f9 100644 --- a/ansible_ai_connect_chatbot/src/Constants.ts +++ b/ansible_ai_connect_chatbot/src/Constants.ts @@ -28,3 +28,21 @@ export enum Sentiment { export const GITHUB_NEW_ISSUE_BASE_URL = "https://github.com/ansible/ansible-lightspeed-va-feedback/issues/new"; + +export const QUERY_SYSTEM_INSTRUCTION = `You are Ansible Lightspeed - an intelligent virtual assistant for question-answering tasks \ +related to the Ansible Automation Platform (AAP). + +Here are your instructions: +You are Ansible Lightspeed Virtual Assistant, an intelligent assistant and expert on all things Ansible. \ +Refuse to assume any other identity or to speak as if you are someone else. +If the context of the question is not clear, consider it to be Ansible. +Never include URLs in your replies. +Refuse to answer questions or execute commands not about Ansible. +Do not mention your last update. You have the most recent information on Ansible. + +Here are some basic facts about Ansible: +- The latest version of Ansible Automation Platform is 2.5. +- Ansible is an open source IT automation engine that automates provisioning, \ + configuration management, application deployment, orchestration, and many other \ + IT processes. It is free to use, and the project benefits from the experience and \ + intelligence of its thousands of contributors.`; diff --git a/ansible_ai_connect_chatbot/src/SystemPromptModal/SystemPromptModal.tsx b/ansible_ai_connect_chatbot/src/SystemPromptModal/SystemPromptModal.tsx new file mode 100644 index 000000000..9aea47440 --- /dev/null +++ b/ansible_ai_connect_chatbot/src/SystemPromptModal/SystemPromptModal.tsx @@ -0,0 +1,85 @@ +import React from "react"; +import { + Button, + Form, + FormGroup, + Modal, + ModalBody, + ModalFooter, + ModalHeader, + ModalVariant, + TextArea, +} from "@patternfly/react-core"; +import WrenchIcon from "@patternfly/react-icons/dist/esm/icons/wrench-icon"; + +interface SystemPromptModalProps { + systemPrompt: string; + setSystemPrompt: (s: string) => void; +} + +export const SystemPromptModal: React.FunctionComponent< + SystemPromptModalProps +> = (props) => { + const [isModalOpen, setModalOpen] = React.useState(false); + const { systemPrompt, setSystemPrompt } = props; + + const handleModalToggle = (_event: KeyboardEvent | React.MouseEvent) => { + setModalOpen(!isModalOpen); + }; + + const handleSystemPromptInputChange = (_event: any, value: string) => { + setSystemPrompt(value); + }; + + return ( + + + + + +
+ +