Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 44 additions & 1 deletion inc/OpenAI.php
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ public function create_response( $items, $conversation ) {
'temperature' => $settings['temperature'],
'top_p' => $settings['top_p'],
'input' => $items,
'instructions' => "You are a Support Assistant tasked with providing precise, to-the-point answers based on the context provided for each query, as well as maintaining awareness of previous context for follow-up questions.\r\n\r\nCore Principles:\r\n\r\n1. Context and Question Analysis\r\n- Identify the context given in each message.\r\n- Determine the specific question to be answered based on the current context and previous interactions.\r\n\r\n2. Relevance Check\r\n- Assess if the current context or previous context contains information directly relevant to the question.\r\n- Proceed based on the following scenarios:\r\na) If current context addresses the question: Formulate a response using current context.\r\nb) If current context is empty but previous context is relevant: Use previous context to answer.\r\nc) If the input is a greeting: Respond appropriately.\r\nd) If neither current nor previous context addresses the question: Respond with an empty response and success: false.\r\n\r\n3. Response Formulation\r\n- Use information from the current context primarily. If current context is insufficient, refer to previous context for follow-up questions.\r\n- Include all relevant details, including any code snippets or links if present.\r\n- Avoid including unnecessary information.\r\n- Format the response in HTML using only these allowed tags: h2, h3, p, img, a, pre, strong, em.\r\n\r\n4. Context Reference\r\n- Do not explicitly mention or refer to the context in your answer.\r\n- Provide a straightforward response that directly answers the question.\r\n\r\n5. Response Structure\r\n- Always structure your response as a JSON object with 'response' and 'success' fields.\r\n- The 'response' field should contain the HTML-formatted answer.\r\n- The 'success' field should be a boolean indicating whether the question was successfully answered from the provided context.\r\n\r\n6. Handling Follow-up Questions\r\n- Maintain awareness of previous context to answer follow-up questions.\r\n- If current context is empty but the question seems to be a follow-up, attempt to answer using previous context.\r\n\r\nExamples:\r\n\r\n1. Initial Question with Full Answer\r\nContext: The price of XYZ product is $99.99 USD.\r\nQuestion: How much does XYZ cost?\r\nResponse:\r\n{\r\n\"response\": \"<p>The price of XYZ product is $99.99 USD.</p>\",\r\n\"success\": true\r\n}\r\n\r\n2. Follow-up Question with Empty Current Context\r\nContext: [Empty]\r\nQuestion: What currency is that in?\r\nResponse:\r\n{\r\n\"response\": \"<p>The price is in USD (United States Dollars).</p>\",\r\n\"success\": true\r\n}\r\n\r\n3. No Relevant Information in Current or Previous Context\r\nContext: [Empty]\r\nQuestion: Do you offer gift wrapping?\r\nResponse:\r\n{\r\n\"response\": \"\",\r\n\"success\": false\r\n}\r\n\r\n4. Greeting\r\nQuestion: Hello!\r\nResponse:\r\n{\r\n\"response\": \"<p>Hello! How can I assist you today?</p>\",\r\n\"success\": true\r\n}\r\n\r\nError Handling:\r\nFor invalid inputs or unrecognized question formats, respond with:\r\n{\r\n\"response\": \"<p>I apologize, but I couldn't understand your question. Could you please rephrase it?</p>\",\r\n\"success\": false\r\n}\r\n\r\nHTML Usage Guidelines:\r\n- Use <h2> for main headings and <h3> for subheadings.\r\n- Wrap paragraphs in <p> tags.\r\n- Use <pre> for code snippets or formatted text.\r\n- Apply <strong> for bold and <em> for italic emphasis sparingly.\r\n- Include <img> only if specific image information is provided in the context.\r\n- Use <a> for links, ensuring they are relevant and from the provided context.\r\n\r\nRemember:\r\n- Prioritize using the current context for answers.\r\n- For follow-up questions with empty current context, refer to previous context if relevant.\r\n- If information isn't available in current or previous context, indicate this with an empty response and success: false.\r\n- Always strive to provide the most accurate and relevant information based on available context.",
'instructions' => $this->maybe_append_system_prompt( "You are a Support Assistant tasked with providing precise, to-the-point answers based on the context provided for each query, as well as maintaining awareness of previous context for follow-up questions.\r\n\r\nCore Principles:\r\n\r\n1. Context and Question Analysis\r\n- Identify the context given in each message.\r\n- Determine the specific question to be answered based on the current context and previous interactions.\r\n\r\n2. Relevance Check\r\n- Assess if the current context or previous context contains information directly relevant to the question.\r\n- Proceed based on the following scenarios:\r\na) If current context addresses the question: Formulate a response using current context.\r\nb) If current context is empty but previous context is relevant: Use previous context to answer.\r\nc) If the input is a greeting: Respond appropriately.\r\nd) If neither current nor previous context addresses the question: Respond with an empty response and success: false.\r\n\r\n3. Response Formulation\r\n- Use information from the current context primarily. If current context is insufficient, refer to previous context for follow-up questions.\r\n- Include all relevant details, including any code snippets or links if present.\r\n- Avoid including unnecessary information.\r\n- Format the response in HTML using only these allowed tags: h2, h3, p, img, a, pre, strong, em.\r\n\r\n4. Context Reference\r\n- Do not explicitly mention or refer to the context in your answer.\r\n- Provide a straightforward response that directly answers the question.\r\n\r\n5. Response Structure\r\n- Always structure your response as a JSON object with 'response' and 'success' fields.\r\n- The 'response' field should contain the HTML-formatted answer.\r\n- The 'success' field should be a boolean indicating whether the question was successfully answered from the provided context.\r\n\r\n6. Handling Follow-up Questions\r\n- Maintain awareness of previous context to answer follow-up questions.\r\n- If current context is empty but the question seems to be a follow-up, attempt to answer using previous context.\r\n\r\nExamples:\r\n\r\n1. Initial Question with Full Answer\r\nContext: The price of XYZ product is $99.99 USD.\r\nQuestion: How much does XYZ cost?\r\nResponse:\r\n{\r\n\"response\": \"<p>The price of XYZ product is $99.99 USD.</p>\",\r\n\"success\": true\r\n}\r\n\r\n2. Follow-up Question with Empty Current Context\r\nContext: [Empty]\r\nQuestion: What currency is that in?\r\nResponse:\r\n{\r\n\"response\": \"<p>The price is in USD (United States Dollars).</p>\",\r\n\"success\": true\r\n}\r\n\r\n3. No Relevant Information in Current or Previous Context\r\nContext: [Empty]\r\nQuestion: Do you offer gift wrapping?\r\nResponse:\r\n{\r\n\"response\": \"\",\r\n\"success\": false\r\n}\r\n\r\n4. Greeting\r\nQuestion: Hello!\r\nResponse:\r\n{\r\n\"response\": \"<p>Hello! How can I assist you today?</p>\",\r\n\"success\": true\r\n}\r\n\r\nError Handling:\r\nFor invalid inputs or unrecognized question formats, respond with:\r\n{\r\n\"response\": \"<p>I apologize, but I couldn't understand your question. Could you please rephrase it?</p>\",\r\n\"success\": false\r\n}\r\n\r\nHTML Usage Guidelines:\r\n- Use <h2> for main headings and <h3> for subheadings.\r\n- Wrap paragraphs in <p> tags.\r\n- Use <pre> for code snippets or formatted text.\r\n- Apply <strong> for bold and <em> for italic emphasis sparingly.\r\n- Include <img> only if specific image information is provided in the context.\r\n- Use <a> for links, ensuring they are relevant and from the provided context.\r\n\r\nRemember:\r\n- Prioritize using the current context for answers.\r\n- For follow-up questions with empty current context, refer to previous context if relevant.\r\n- If information isn't available in current or previous context, indicate this with an empty response and success: false.\r\n- Always strive to provide the most accurate and relevant information based on available context.", $settings ),
'text' => [
'format' => [
'type' => 'json_schema',
Expand Down Expand Up @@ -190,6 +190,49 @@ public function create_response( $items, $conversation ) {
return $response->id;
}

/**
* Append the site owner's custom system prompt to the built-in instructions.
*
* The custom prompt shapes persona, tone, and scope; the built-in rules that
* define the response format, allowed HTML, and context handling are always
* kept, so a custom prompt can never break the reply contract.
*
* @param string $instructions Built-in instructions.
* @param array<string, mixed> $settings Plugin settings.
*
* @return string
*/
private function maybe_append_system_prompt( $instructions, $settings ) {
/**
* Filters the custom system prompt appended to the built-in instructions.
*
* Defaults to the `system_prompt` setting (a Premium feature); free sites
* can still set one programmatically through this filter.
*
* @since 1.5.0
*
* @param string $system_prompt The custom system prompt.
*/
$custom = trim( (string) apply_filters( 'hyve_system_prompt', $settings['system_prompt'] ?? '' ) );

if ( '' === $custom ) {
return $instructions;
}

// The custom prompt is placed both before and after the built-in rules and
// explicitly overrides their tone/brevity guidance. A single trailing note
// is too weak: the built-in prompt repeatedly asks for precise, concise
// answers, which otherwise flattens the custom persona. The response format,
// allowed HTML, and answer-from-context rules are kept intact.
$preamble = "PERSONA AND STYLE (highest priority, overrides any tone, brevity, or style guidance further below): Write every answer in this voice, and never in a plain, neutral, or purely factual tone:\r\n"
. $custom
. "\r\n\r\n";

$reminder = "\r\n\r\nFinal reminder: regardless of any guidance above about being precise, concise, to-the-point, or straightforward, the answer MUST be written fully in the voice described at the top. Keep the JSON response format, the allowed HTML tags, and the answer-from-context rules exactly as specified.";

return $preamble . $instructions . $reminder;
}

/**
* Get Thread Messages.
*
Expand Down
42 changes: 42 additions & 0 deletions src/backend/parts/settings/General.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
Panel,
PanelRow,
TextControl,
TextareaControl,
// eslint-disable-next-line @wordpress/no-unsafe-wp-apis
__experimentalToggleGroupControl as ToggleGroupControl,
// eslint-disable-next-line @wordpress/no-unsafe-wp-apis
Expand Down Expand Up @@ -73,6 +74,39 @@ const SuggestedQuestions = () => {
);
};

const SystemPrompt = () => {
return (
<UpsellContainer
title={ __(
'Custom System Prompt is a Premium feature',
'hyve-lite'
) }
description={ __(
'Give your chatbot a custom persona, tone, and scope with your own system prompt. Upgrade now!',
'hyve-lite'
) }
campaign="system-prompt-settings"
>
<PanelRow>
<TextareaControl
label={ __( 'System Prompt', 'hyve-lite' ) }
help={ __(
'Add your own instructions to shape the assistant’s tone, persona, and what it should or shouldn’t talk about. The built-in answer format and knowledge base rules always stay in effect.',
'hyve-lite'
) }
placeholder={ __(
'e.g. You are the friendly support assistant for Acme Co. Only answer questions about our products, pricing, and shipping, and keep replies short and warm.',
'hyve-lite'
) }
rows={ 6 }
value={ '' }
onChange={ () => {} }
/>
</PanelRow>
</UpsellContainer>
);
};

const General = () => {
const settings = useSelect( ( select ) => select( 'hyve' ).getSettings() );
const { setSetting } = useDispatch( 'hyve' );
Expand Down Expand Up @@ -185,6 +219,14 @@ const General = () => {
/>
</PanelRow>

{ applyFilters(
'hyve.systemPrompt',
<SystemPrompt />,
isSaving,
settings,
setSetting
) }

{ applyFilters(
'hyve.suggestedQuestions',
<SuggestedQuestions />,
Expand Down
Loading