diff --git a/packages/prompt-tuning/__stories__/prompt-tuning.mdx b/packages/prompt-tuning/__stories__/prompt-tuning.mdx
new file mode 100644
index 00000000..4add9266
--- /dev/null
+++ b/packages/prompt-tuning/__stories__/prompt-tuning.mdx
@@ -0,0 +1,53 @@
+import { ArgTypes, Markdown, Meta } from '@storybook/blocks';
+import { cdnJs, cdnCss } from '../../../globals/internal/storybook-cdn';
+import * as PromptTuningStories from './prompt-tuning.stories';
+import packageJson from '../package.json';
+
+
+
+# Prompt Tuning
+
+> 💡 Check our
+> [Stackblitz](https://stackblitz.com/github/carbon-design-system/carbon-labs/tree/main/packages/prompt-tuning/examples/prompt-tuning)
+> example implementation.
+
+[![Edit carbon-labs](https://developer.stackblitz.com/img/open_in_stackblitz.svg)](https://stackblitz.com/github/carbon-design-system/carbon-labs/tree/main/packages/prompt-tuning/examples/prompt-tuning)
+
+## Overview
+
+The prompt-tuning component.
+
+## Getting started
+
+Here's a quick example to get you started.
+
+### JS (via import)
+
+```javascript
+import '@carbon-labs/ai-prompt-tuning/es/index.js';
+```
+
+### Styles
+
+You'll also need to import the theming tokens from `@carbon/styles` either from
+npm or from our CDN helpers. Checkout our Stackblitz example above to see how
+that is implemented.
+
+{/* prettier-ignore */}
+{`${cdnJs({ components: ['prompt-tuning'] },packageJson)}`}
+{`${cdnCss()}`}
+
+### HTML
+
+```html
+
+ PromptTuning text
+
+```
+
+### <clabs-prompt-tuning> attributes and properties
+
+
diff --git a/packages/prompt-tuning/__stories__/prompt-tuning.stories.js b/packages/prompt-tuning/__stories__/prompt-tuning.stories.js
new file mode 100644
index 00000000..3a8d482b
--- /dev/null
+++ b/packages/prompt-tuning/__stories__/prompt-tuning.stories.js
@@ -0,0 +1,211 @@
+/**
+ * @license
+ *
+ * Copyright IBM Corp. 2023
+ *
+ * This source code is licensed under the Apache-2.0 license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+import '../components/prompt-tuning/prompt-tuning';
+import { html } from 'lit';
+import { action } from '@storybook/addon-actions';
+
+import '@carbon/web-components/es/components/button/index.js';
+import semantic_search_view from './semantic_search_view.json';
+
+export default {
+ title: 'Components/Prompt Tuning/Prompt Tuning',
+ component: 'clabs-prompt-tuning',
+};
+
+const defaultArgs = {
+ promptSamples: semantic_search_view.samples,
+ viewList: [
+ 'task_view',
+ 'semantic_search_view',
+ 'collections_view',
+ 'semantic_querying_view',
+ 'table_details_view',
+ 'table_upload_view',
+ 'visualization_view',
+ 'table_expansion_view',
+ 'glossary_view',
+ 'table_comparison_view',
+ 'causal_interference_view',
+ ],
+ currentView: {
+ name: 'semantic_search_view',
+ contextVariables: ['table_ids'],
+ parameters: ['mode', 'question', 'table_ids'],
+ },
+ onSaveRename: action('save-rename'),
+ onCloseTag: action('close-tag'),
+ onAddContextVariable: action('add-context-variable'),
+ onAddParameter: action('add-parameter'),
+ onSavePrompt: action('save-prompt'),
+ onDeletePrompt: action('delete-prompt'),
+ onChangeView: action('change-view'),
+ onAddPrompt: action('add-prompt'),
+ isListModalOpen: true,
+};
+
+/* Default controls */
+const defaultControls = {
+ isListModalOpen: {
+ name: 'open',
+ control: { type: 'boolean' },
+ description: 'Whether the tuning prompts modal is open or not',
+ table: {
+ category: '',
+ defaultValue: { summary: true },
+ },
+ },
+ promptSamples: {
+ control: { type: 'object' },
+ description: 'Current view data',
+ table: {
+ defaultValue: {
+ summary: 'Using a JSON example from semantic search view for storybook',
+ },
+ },
+ },
+ currentView: {
+ control: { type: 'object' },
+ description: 'Name, context variables, and parameters in the current view',
+ table: {
+ defaultValue: {
+ summary: 'Using a JSON example with semantic search view for storybook',
+ },
+ },
+ },
+ viewList: {
+ control: { type: 'object' },
+ description: 'List of views',
+ table: {
+ defaultValue: {
+ summary: 'Using an example of a list of views for storybook',
+ },
+ },
+ },
+ onAddContextVariable: {
+ action: 'add-context-variable',
+ description:
+ 'Fires when user saves new context variable for the current view',
+ table: {
+ category: 'Events',
+ defaultValue: { summary: 'function' },
+ },
+ },
+ onAddParameter: {
+ action: 'add-parameter',
+ description: 'Fires when user saves new parameter for the current view',
+ table: {
+ category: 'Events',
+ defaultValue: { summary: 'function' },
+ },
+ },
+ onChangeView: {
+ action: 'change-view',
+ description:
+ 'Fires when user chooses a different view in the select dropdown',
+ table: {
+ category: 'Events',
+ defaultValue: { summary: 'function' },
+ },
+ },
+ onCloseTag: {
+ action: 'change-view',
+ description:
+ 'Fires when user clicks the X for the current view context variable or parameter',
+ table: {
+ category: 'Events',
+ defaultValue: { summary: 'function' },
+ },
+ },
+ onDeletePrompt: {
+ action: 'delete-prompt',
+ description:
+ 'Fires when user clicks the trash icon next to a prompt table row',
+ table: {
+ category: 'Events',
+ defaultValue: { summary: 'function' },
+ },
+ },
+ onSavePrompt: {
+ action: 'save-prompt',
+ description: 'Fires when user edits a prompt and saves the changes',
+ table: {
+ category: 'Events',
+ defaultValue: { summary: 'function' },
+ },
+ },
+ onSaveRename: {
+ action: 'save-rename',
+ description: 'Fires when user renames the current view and saves changes',
+ table: {
+ category: 'Events',
+ defaultValue: { summary: 'function' },
+ },
+ },
+ onAddPrompt: {
+ action: 'save-rename',
+ description: 'Fires when user adds a new prompt',
+ table: {
+ category: 'Events',
+ defaultValue: { summary: 'function' },
+ },
+ },
+
+ isEditModalOpen: {
+ table: {
+ disable: true,
+ },
+ },
+ text: {
+ table: {
+ disable: true,
+ },
+ },
+};
+
+/**
+ * More on writing stories with args: https://storybook.js.org/docs/web-components/writing-stories/args
+ *
+ * @type {{args: {label: string}, render: (function(*): TemplateResult<1>)}}
+ */
+export const Default = {
+ argTypes: defaultControls,
+ args: defaultArgs,
+ /**
+ * Renders the template for Storybook
+ * @param {string} args.content - content to generate from
+ * @returns {TemplateResult<1>}
+ */
+ render: ({
+ isListModalOpen,
+ promptSamples,
+ viewList,
+ currentView,
+ onSaveRename,
+ onCloseTag,
+ onAddContextVariable,
+ onAddParameter,
+ onSavePrompt,
+ onDeletePrompt,
+ onChangeView,
+ onAddPrompt,
+ }) =>
+ html` `,
+};
diff --git a/packages/prompt-tuning/__stories__/semantic_search_view.json b/packages/prompt-tuning/__stories__/semantic_search_view.json
new file mode 100644
index 00000000..73221895
--- /dev/null
+++ b/packages/prompt-tuning/__stories__/semantic_search_view.json
@@ -0,0 +1,291 @@
+{
+ "samples": [
+ {
+ "id": 20123,
+ "user_id": "demo",
+ "input": {
+ "input": "I'd like to see the quality of this table.",
+ "view_id": "semantic_search_view",
+ "context_variables": {
+ "table_ids": "[BANKDEMO.SAVINGS_ACCOUNTS]"
+ }
+ },
+ "output": {
+ "output": "Alright, here are some important Data Quality metrics for this table.",
+ "view_id": "table_details_view",
+ "parameters": {
+ "mode": "quality",
+ "question": "",
+ "table_ids": "[BANKDEMO.SAVINGS_ACCOUNTS]"
+ }
+ }
+ },
+ {
+ "id": 20124,
+ "user_id": "demo",
+ "input": {
+ "input": "Can you show me the schema for this table?",
+ "view_id": "semantic_search_view",
+ "context_variables": {
+ "table_ids": "[CSTINSIGHT.ORGANIZATION_CST_LOYALTY_FACT]"
+ }
+ },
+ "output": {
+ "output": "No problem, here is the schema of your table.",
+ "view_id": "table_details_view",
+ "parameters": {
+ "mode": "schema",
+ "question": "",
+ "table_ids": "[CSTINSIGHT.ORGANIZATION_CST_LOYALTY_FACT]"
+ }
+ }
+ },
+ {
+ "id": 20125,
+ "user_id": "demo",
+ "input": {
+ "input": "Show me the data of this table.",
+ "view_id": "semantic_search_view",
+ "context_variables": {
+ "table_ids": "[PMT_RISK.BUILDING_TYPE]"
+ }
+ },
+ "output": {
+ "output": "Alright, here you can take a look at data in this table.",
+ "view_id": "table_details_view",
+ "parameters": {
+ "mode": "data",
+ "question": "",
+ "table_ids": "[PMT_RISK.BUILDING_TYPE]"
+ }
+ }
+ },
+ {
+ "id": 20135,
+ "user_id": "demo",
+ "input": {
+ "input": "i'd like to see the quality of this table.",
+ "view_id": "semantic_search_view",
+ "context_variables": {}
+ },
+ "output": {
+ "output": "You did not select a table yet.",
+ "view_id": "semantic_search_view",
+ "parameters": {}
+ }
+ },
+ {
+ "id": 20136,
+ "user_id": "demo",
+ "input": {
+ "input": "What can I join this table with?",
+ "view_id": "semantic_search_view",
+ "context_variables": {
+ "table_ids": "[CSTINSIGHT.CUSTOMER]"
+ }
+ },
+ "output": {
+ "output": "Let's see if we have some joinable tables in the Lakehouse.",
+ "view_id": "table_expansion_view",
+ "parameters": {
+ "keyword": "",
+ "table_ids": "[CSTINSIGHT.CUSTOMER]"
+ }
+ }
+ },
+ {
+ "id": 20142,
+ "user_id": "demo",
+ "input": {
+ "input": "I'd like to add more geographic context to this table.",
+ "view_id": "semantic_search_view",
+ "context_variables": {
+ "table_ids": "[PMT_RISK.BUILDING_TYPE]"
+ }
+ },
+ "output": {
+ "output": "Alright, let's see if we find joinable tables with geographic data.",
+ "view_id": "table_expansion_view",
+ "parameters": {
+ "keyword": "geography",
+ "table_ids": "[PMT_RISK.BUILDING_TYPE]"
+ }
+ }
+ },
+ {
+ "id": 20143,
+ "user_id": "demo",
+ "input": {
+ "input": "I'd like to add residence location data to this.",
+ "view_id": "semantic_search_view",
+ "context_variables": {
+ "table_ids": "[CUSTOM.b1c0f860-b1d7-43c2-a1a2-4807e78ed15b]"
+ }
+ },
+ "output": {
+ "output": "Alright, let's look for compatible tables that contain this kind of data.",
+ "view_id": "table_expansion_view",
+ "parameters": {
+ "keyword": "residence location",
+ "table_ids": "[CUSTOM.b1c0f860-b1d7-43c2-a1a2-4807e78ed15b]"
+ }
+ }
+ },
+ {
+ "id": 20156,
+ "user_id": "demo",
+ "input": {
+ "input": "I would like to see the annotations for this table.",
+ "view_id": "semantic_search_view",
+ "context_variables": {
+ "table_ids": "[CSTINSIGHT.PERSON]"
+ }
+ },
+ "output": {
+ "output": "Sure, here are the annotations and also you can provide your feedback on these.",
+ "view_id": "collection_annotation_view",
+ "parameters": {
+ "table_ids": "[CSTINSIGHT.PERSON]"
+ }
+ }
+ },
+ {
+ "id": 20161,
+ "user_id": "demo",
+ "input": {
+ "input": "Show me the details of table PMT_RISK.BUILDING_TYPE.",
+ "view_id": "semantic_search_view",
+ "context_variables": {
+ "table_ids": "[BANKDEMO.ACCOUNTS]"
+ }
+ },
+ "output": {
+ "output": "Alright, pulling up this table for you.",
+ "view_id": "table_details_view",
+ "parameters": {
+ "question": "",
+ "mode": "schema",
+ "table_ids": "[PMT_RISK.BUILDING_TYPE]"
+ }
+ }
+ },
+ {
+ "id": 20162,
+ "user_id": "demo",
+ "input": {
+ "input": "I would like to review the concept annotations of these tables.",
+ "view_id": "semantic_search_view",
+ "context_variables": {
+ "table_ids": "[CSTINSIGHT.CUSTOMER,BANKDEMO.ACCOUNTS]"
+ }
+ },
+ "output": {
+ "output": "No problem, here you can take a look at how the columns have been mapped to glossary concepts.",
+ "view_id": "collection_annotation_view",
+ "parameters": {
+ "table_ids": "[CSTINSIGHT.CUSTOMER,BANKDEMO.ACCOUNTS]"
+ }
+ }
+ },
+ {
+ "id": 20177,
+ "user_id": "demo",
+ "input": {
+ "input": "Can I improve my sales strategy using this?",
+ "view_id": "semantic_search_view",
+ "context_variables": {
+ "table_ids": "[CSTINSIGHT.PRODUCT]"
+ }
+ },
+ "output": {
+ "output": "Alright, let me try to create a policy based on the customer table.",
+ "view_id": "causal_inference_view",
+ "parameters": {
+ "keyword": "",
+ "question": "I want to improve the sales strategy.",
+ "table_ids": "[CSTINSIGHT.PRODUCT]"
+ }
+ }
+ },
+ {
+ "id": 20185,
+ "user_id": "demo",
+ "input": {
+ "input": "I have a question about this table.",
+ "view_id": "semantic_search_view",
+ "context_variables": {
+ "table_ids": "[CSTINSIGHT.INDIVIDUAL_CST_CHURN_FACT]",
+ "keyword": "customer churn"
+ }
+ },
+ "output": {
+ "output": "Sure, what would you like to know about it?",
+ "view_id": "semantic_search_view",
+ "parameters": {
+ "keyword": "customer churn"
+ }
+ }
+ },
+ {
+ "id": 20186,
+ "user_id": "demo",
+ "input": {
+ "input": "Who is the customer with highest net worth?",
+ "view_id": "semantic_search_view",
+ "context_variables": {
+ "table_ids": "[CSTINSIGHT.CUSTOMER]",
+ "keyword": "customer churn"
+ }
+ },
+ "output": {
+ "output": "Let me check whether if I can find the answer to this by querying the lakehouse for you.",
+ "view_id": "semantic_querying_view",
+ "parameters": {
+ "table_ids": "[CSTINSIGHT.CUSTOMER]",
+ "mode": "sql",
+ "question": "Who is the customer with highest net worth?"
+ }
+ }
+ },
+ {
+ "id": 20190,
+ "user_id": "demo",
+ "input": {
+ "input": "This looks interesting. What kinda products do we gave here?",
+ "view_id": "semantic_search_view",
+ "context_variables": {
+ "table_ids": "[CSTINSIGHT.PRODUCT]"
+ }
+ },
+ "output": {
+ "output": "I'm gonna try to inquire about this in the lakehouse for you.",
+ "view_id": "semantic_querying_view",
+ "parameters": {
+ "keyword": "",
+ "table_ids": "[CSTINSIGHT.PRODUCT]",
+ "mode": "sql",
+ "question": "What kinda products do we gave here?"
+ }
+ }
+ },
+ {
+ "id": 20196,
+ "user_id": "demo",
+ "input": {
+ "input": "I have a question about CSTINSIGHT.INDIVIDUAL_CST_CHURN_FACT.",
+ "view_id": "semantic_search_view",
+ "context_variables": {
+ "table_ids": "",
+ "keyword": "customer churn"
+ }
+ },
+ "output": {
+ "output": "Sure, what would you like to know about it?",
+ "view_id": "semantic_search_view",
+ "parameters": {
+ "keyword": "customer churn"
+ }
+ }
+ }
+ ]
+}
diff --git a/packages/prompt-tuning/components/prompt-tuning/prompt-tuning.ts b/packages/prompt-tuning/components/prompt-tuning/prompt-tuning.ts
new file mode 100644
index 00000000..4dbb9111
--- /dev/null
+++ b/packages/prompt-tuning/components/prompt-tuning/prompt-tuning.ts
@@ -0,0 +1,33 @@
+/**
+ * @license
+ *
+ * Copyright IBM Corp. 2023
+ *
+ * This source code is licensed under the Apache-2.0 license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+import { customElement } from 'lit/decorators.js';
+import { settings } from '@carbon-labs/utilities/es/settings/index.js';
+import { PromptTuning } from './src/prompt-tuning.js';
+import { TemplateResult } from 'lit';
+import { promptTuningTemplate } from './src/prompt-tuning.template.js';
+
+const { stablePrefix: clabsPrefix } = settings;
+
+/**
+ * Component extending the PromptTuning component
+ *
+ * @element clabs-prompt-tuning
+ */
+@customElement(`${clabsPrefix}-prompt-tuning`)
+class CLABSPromptTuning extends PromptTuning {
+ /**
+ * Renders the template while passing in class functionality
+ */
+ render(): TemplateResult<1> {
+ return promptTuningTemplate(this);
+ }
+}
+
+export default CLABSPromptTuning;
diff --git a/packages/prompt-tuning/components/prompt-tuning/src/prompt-tuning.scss b/packages/prompt-tuning/components/prompt-tuning/src/prompt-tuning.scss
new file mode 100644
index 00000000..f36ee12c
--- /dev/null
+++ b/packages/prompt-tuning/components/prompt-tuning/src/prompt-tuning.scss
@@ -0,0 +1,82 @@
+/**
+ * Copyright IBM Corp. 2023, 2024
+ *
+ * This source code is licensed under the Apache-2.0 license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+$css--plex: true !default;
+
+@use '../../../../../globals/scss/vars' as *;
+@use '@carbon/styles/scss/theme' as *;
+@use '@carbon/styles/scss/type' as *;
+
+:host(#{$clabs-prefix}-prompt-tuning) {
+ .#{$clabs-prefix}--heading-container {
+ padding: 0;
+ }
+ .#{$clabs-prefix}--heading,
+ .#{$clabs-prefix}--enter-new {
+ display: flex;
+ }
+ .#{$clabs-prefix}--heading-tune-prompts {
+ min-inline-size: max-content;
+ }
+ .#{$clabs-prefix}--view-dropdown {
+ max-inline-size: min-content;
+ }
+ .#{$clabs-prefix}--rename {
+ flex-grow: 1;
+ }
+ .#{$clabs-prefix}--header-view-info {
+ display: flex;
+ }
+ .#{$clabs-prefix}--header-context-variables {
+ flex: 1 1 50%;
+ }
+ .#{$clabs-prefix}--header-parameters {
+ flex: 1 1 25%;
+ }
+
+ .#{$clabs-prefix}--add-context-variable-tag,
+ .#{$clabs-prefix}--add-parameter-tag {
+ cursor: pointer;
+ }
+
+ .#{$clabs-prefix}--add-context-variable-tag:hover,
+ .#{$clabs-prefix}--add-parameter-tag:hover {
+ background-color: #636363;
+ }
+
+ .#{$clabs-prefix}--table-actions {
+ min-inline-size: 96px;
+ }
+ .#{$clabs-prefix}--prompt-edit-form {
+ display: flex;
+ justify-content: space-between;
+
+ h4 {
+ padding: 0;
+ margin: 1rem 0 0.5rem;
+ font-size: 1.25rem;
+ font-weight: 400;
+ letter-spacing: 0;
+ line-height: 1.4;
+ }
+
+ .#{$clabs-prefix}--edit-form-item {
+ display: inline-block;
+ margin-block-start: 10px;
+ }
+
+ .#{$clabs-prefix}--edit-input {
+ flex: 1 1 50%;
+ margin-inline-end: 24px;
+ }
+
+ .#{$clabs-prefix}--edit-output {
+ flex: 1 1 50%;
+ margin-inline-start: 24px;
+ }
+ }
+}
diff --git a/packages/prompt-tuning/components/prompt-tuning/src/prompt-tuning.template.ts b/packages/prompt-tuning/components/prompt-tuning/src/prompt-tuning.template.ts
new file mode 100644
index 00000000..42476889
--- /dev/null
+++ b/packages/prompt-tuning/components/prompt-tuning/src/prompt-tuning.template.ts
@@ -0,0 +1,537 @@
+/**
+ * @license
+ *
+ * Copyright IBM Corp. 2023
+ *
+ * This source code is licensed under the Apache-2.0 license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+import { html } from 'lit';
+import { settings } from '@carbon-labs/utilities/es/settings/index.js';
+const { stablePrefix: clabsPrefix } = settings;
+import '@carbon/web-components/es/components/modal/index.js';
+import '@carbon/web-components/es/components/data-table/index.js';
+import '@carbon/web-components/es/components/button/index.js';
+import '@carbon/web-components/es/components/form-group/index.js';
+import Edit16 from '@carbon/web-components/es/icons/edit/16.js';
+import TrashCan16 from '@carbon/web-components/es/icons/trash-can/16.js';
+import Add16 from '@carbon/web-components/es/icons/add/16.js';
+import RequestQuote16 from '@carbon/web-components/es/icons/request-quote/16.js';
+import Close16 from '@carbon/web-components/es/icons/close/16.js';
+import Checkmark16 from '@carbon/web-components/es/icons/checkmark/16.js';
+
+import '@carbon/web-components/es/components/tag/index.js';
+
+import '@carbon/web-components/es/components/text-input/index.js';
+import '@carbon/web-components/es/components/select/index.js';
+import '@carbon/web-components/es/components/form/index.js';
+import '@carbon/web-components/es/components/tooltip/index.js';
+
+/**
+ * Render HTML rows
+ *
+ * @param {object} customElementClass Class functionality for the custom element
+ * @returns {TemplateResult<1>} Lit html template
+ */
+function getHTMLRows(customElementClass) {
+ const {
+ promptSamples: promptSamples,
+ _onEditButtonClick: onEditButtonClick,
+ onDeleteButtonClick: onDeleteButtonClick,
+ } = customElementClass;
+
+ return html`
+ ${promptSamples.map(
+ (item) =>
+ html`
+ ${item.input.input}
+ ${Object.keys(item.input.context_variables).length > 0
+ ? html`${Object.entries(item.input.context_variables).map(
+ (item) =>
+ item.length > 0
+ ? html`
+
+
+ ${item[1]}
+
+
+ ${item[0]}: ${item[1]}
+
+
+ `
+ : html``
+ )}`
+ : html``}
+
+ ${item.output.output}
+ ${item.output.view_id}
+ ${Object.keys(item.output.parameters).length > 0
+ ? html`${Object.entries(item.output.parameters).map((item) =>
+ item.length > 0
+ ? html`
+
+
+ ${item[1]}
+
+
+ ${item[0]}: ${item[1]}
+
+
+ `
+ : html``
+ )}`
+ : html``}
+
+
+ ${Edit16()}
+ ${TrashCan16()}
+
+ `
+ )}
+ `;
+}
+
+/**
+ * Render views for select
+ *
+ * @param {object} customElementClass Class functionality for the custom element
+ * @returns {TemplateResult<1>} Lit html template
+ */
+function getSelectViews(customElementClass) {
+ const { viewList: viewList } = customElementClass;
+
+ const views = viewList.map((view) => {
+ return html`${view}`;
+ });
+
+ return views;
+}
+
+/**
+ * Render HTML rows
+ *
+ * @param {object} customElementClass Class functionality for the custom element
+ * @returns {TemplateResult<1>} Lit html template
+ */
+function getEditModal(customElementClass) {
+ const {
+ viewList: viewList,
+ _currentPrompt: currentPrompt,
+ _currentContextVariables: currentContextVariables,
+ _currentResponse: currentResponse,
+ _currentResponseView: currentResponseView,
+ _currentParameters: currentParameters,
+ isEditModalOpen,
+ _onEditModalClose: onEditModalClose,
+ _onEditModalCancel: onEditModalCancel,
+ onSavePrompt: onSavePrompt,
+ triggerSubmit: triggerSubmit,
+ _isNewPrompt: isNewPrompt,
+ currentView: currentView,
+ } = customElementClass;
+
+ let modalHeader, selectedView, contextVariables, parameters;
+
+ if (isNewPrompt) {
+ modalHeader = `Add new prompt for ${currentView.name}`;
+ selectedView = currentView.name;
+ contextVariables =
+ currentView.contextVariables.length <= 0
+ ? html`
+ This intent/view does not provide any context variables.
+
`
+ : currentView.contextVariables.map(
+ (variable) => html`
+ `
+ );
+ parameters =
+ currentView.parameters.length <= 0
+ ? html`This intent/view does not provide any parameters.
`
+ : currentView.parameters.map(
+ (parameter) => html`
+ `
+ );
+ } else {
+ modalHeader = 'Edit prompt';
+ selectedView = currentResponseView;
+ contextVariables =
+ Object.keys(currentContextVariables).length <= 0
+ ? html`
+ This intent/view does not provide any context variables.
+
`
+ : Object.entries(currentContextVariables).map(
+ ([key, value]) => html`
+ `
+ );
+ parameters =
+ Object.keys(currentParameters).length <= 0
+ ? html`This intent/view does not provide any parameters.
`
+ : Object.entries(currentParameters).map(
+ ([key, value]) => html`
+ `
+ );
+ }
+
+ return html`
+
+
+ ${modalHeader}
+
+
+
+
+
+
+
+
+
+ Cancel
+ Save
+
+ `;
+}
+
+/**
+ * Lit template for prompt tuning
+ *
+ * @param {object} customElementClass Class functionality for the custom element
+ * @returns {TemplateResult<1>} Lit html template
+ */
+export function promptTuningTemplate(customElementClass) {
+ const {
+ currentView: currentView,
+ isListModalOpen,
+ _onListModalClose: onListModalClose,
+ _showRename: showRename,
+ _showAddContextVariable: showAddContextVariable,
+ _showAddParameter: showAddParameter,
+ _toggleRename: toggleRename,
+ _toggleAddContextVariable: toggleAddContextVariable,
+ _toggleAddParameter: toggleAddParameter,
+ addContextVariable: addContextVariable,
+ addParameter: addParameter,
+ _handleContextVariableInput: handleContextVariableInput,
+ _handleParameterInput: handleParameterInput,
+ onSaveRename: onSaveRename,
+ _handleNameInput: handleNameInput,
+ onChangeView: onChangeView,
+ _onNewPrompt: onNewPrompt,
+ handleCloseTag: handleCloseTag,
+ } = customElementClass;
+
+ return html`
+
+
+
+
+
+
+ Tune prompts for
+
+ ${!showRename
+ ? html`
+ ${getSelectViews(customElementClass)}
+
+
+
+
+
+ ${RequestQuote16()}
+
+
+
+ Rename intent/view
+ `
+ : html`
+
+
+
+
+
+
+
+
+
+ ${Close16()}
+
+
+
+ Cancel rename
+
+
+
+
+ ${Checkmark16()}
+
+
+
+ Save rename
+
+ `}
+
+
+
+
+
+
+
+
+
+ Prompt
+ Response
+ Intent/View
+ Actions
+
+
+
+ ${getHTMLRows(customElementClass)}
+
+
+
+ Add new prompt
+
+
+
+ ${getEditModal(customElementClass)}
+
`;
+}
diff --git a/packages/prompt-tuning/components/prompt-tuning/src/prompt-tuning.ts b/packages/prompt-tuning/components/prompt-tuning/src/prompt-tuning.ts
new file mode 100644
index 00000000..a795e876
--- /dev/null
+++ b/packages/prompt-tuning/components/prompt-tuning/src/prompt-tuning.ts
@@ -0,0 +1,412 @@
+/**
+ * @license
+ *
+ * Copyright IBM Corp. 2023
+ *
+ * This source code is licensed under the Apache-2.0 license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+import { LitElement } from 'lit';
+import { property } from 'lit/decorators.js';
+import { settings } from '@carbon-labs/utilities/es/settings/index.js';
+const { stablePrefix: clabsPrefix } = settings;
+
+// @ts-ignore
+import styles from './prompt-tuning.scss?inline';
+/**
+ * Input component using search typeahead api
+ */
+export class PromptTuning extends LitElement {
+ static styles = styles;
+
+ /**
+ * Prompt samples data
+ */
+ @property({ attribute: 'promptSamples', type: Array })
+ promptSamples;
+
+ /**
+ * Whether the prompt list modal is open or not
+ */
+ @property({ type: Boolean })
+ isListModalOpen = true;
+
+ /**
+ * Whether the prompt edit modal is open or not
+ */
+ @property({ type: Boolean })
+ isEditModalOpen = false;
+
+ /**
+ * New view name
+ */
+ @property({ type: String })
+ private _newName = '';
+
+ /**
+ * Current prompt
+ */
+ @property({ type: String })
+ // @ts-ignore: Used in template.ts
+ private _currentPrompt = '';
+
+ /**
+ * Current context variables
+ */
+ @property({ type: Object })
+ // @ts-ignore: Used in template.ts
+ private _currentContextVariables = {};
+
+ /**
+ * Current response
+ */
+ @property({ type: String })
+ // @ts-ignore: Used in template.ts
+ private _currentResponse = '';
+
+ /**
+ * Current response view
+ */
+ @property({ type: String })
+ // @ts-ignore: Used in template.ts
+ private _currentResponseView = '';
+
+ /**
+ * Current parameters
+ */
+ @property({ type: Object })
+ // @ts-ignore: Used in template.ts
+ private _currentParameters = {};
+
+ /**
+ * Current response view
+ */
+ @property({ type: Boolean })
+ private _showRename = false;
+
+ /**
+ * Show add context variable
+ */
+ @property({ type: Boolean })
+ private _showAddContextVariable = false;
+
+ /**
+ * Show add parameter
+ */
+ @property({ type: Boolean })
+ private _showAddParameter = false;
+
+ /**
+ * New context variable to add
+ */
+ @property({ type: String })
+ private _newContextVariable = '';
+
+ /**
+ * New parameter to add
+ */
+ @property({ type: String })
+ private _newParameter = '';
+
+ /**
+ * Whether to show new prompt as opposed to edit prompt
+ */
+ @property({ type: Boolean })
+ private _isNewPrompt = false;
+
+ /**
+ * Method for closing the Prompt List Modal
+ */
+ _onListModalClose() {
+ this.isListModalOpen = false;
+ }
+
+ /**
+ * Method for closing the Prompt Edit Modal
+ */
+ _onEditModalClose() {
+ this._currentPrompt = '';
+ this._currentContextVariables = {};
+ this._currentResponse = '';
+ this._currentResponseView = '';
+ this._currentParameters = {};
+ this.isEditModalOpen = false;
+ this._isNewPrompt = false;
+ }
+
+ /**
+ * Method for clicking the Cancel button on the Prompt Edit Modal
+ */
+ _onEditModalCancel() {
+ this._currentPrompt = '';
+ this._currentContextVariables = {};
+ this._currentResponse = '';
+ this._currentResponseView = '';
+ this._currentParameters = {};
+ this.isEditModalOpen = false;
+ this.isListModalOpen = true;
+ this._isNewPrompt = false;
+ }
+
+ /**
+ * Method for clicking a table row Edit button
+ * @param {string} prompt prompt
+ * @param {Object} contextVariables context variables
+ * @param {string} response response
+ * @param {string} responseView response view
+ * @param {Object} parameters parameters
+ */
+ _onEditButtonClick(
+ prompt,
+ contextVariables,
+ response,
+ responseView,
+ parameters
+ ) {
+ this.isListModalOpen = false;
+ this.isEditModalOpen = true;
+ this._currentPrompt = prompt;
+ this._currentContextVariables = contextVariables;
+ this._currentResponse = response;
+ this._currentResponseView = responseView;
+ this._currentParameters = parameters;
+ }
+
+ /**
+ * Method when Add new prompt is clicked
+ */
+ _onNewPrompt() {
+ this.isListModalOpen = false;
+ this.isEditModalOpen = true;
+ this._isNewPrompt = true;
+ }
+
+ /**
+ * Method for clicking a table row Delete button
+ * @param {string} prompt prompt
+ * @param {Object} contextVariables context variables
+ * @param {string} response response
+ * @param {string} responseView response view
+ * @param {Object} parameters parameters
+ */
+ onDeleteButtonClick(
+ prompt,
+ contextVariables,
+ response,
+ responseView,
+ parameters
+ ) {
+ this.dispatchEvent(
+ new CustomEvent('delete-prompt', {
+ detail: {
+ message: `Deleting prompt.`,
+ prompt: {
+ prompt: prompt,
+ contextVariables: contextVariables,
+ response: response,
+ intentView: responseView,
+ parameters: parameters,
+ },
+ },
+ })
+ );
+ }
+
+ /**
+ * Method for toggling view rename
+ */
+ _toggleRename() {
+ this._showRename = !this._showRename;
+ }
+
+ /**
+ * Method for toggling if add context variable is clicked
+ */
+ _toggleAddContextVariable() {
+ this._showAddContextVariable = !this._showAddContextVariable;
+ }
+
+ /**
+ * Method for toggling if add parameter is clicked
+ */
+ _toggleAddParameter() {
+ this._showAddParameter = !this._showAddParameter;
+ }
+
+ /**
+ * Event handler to handle new view name input field updates
+ * @param {event} event event
+ */
+ _handleNameInput(event) {
+ this._newName = event.target.value;
+ }
+
+ /**
+ * fire event when view rename is saved
+ *
+ */
+ onSaveRename() {
+ this.dispatchEvent(
+ new CustomEvent('save-rename', {
+ detail: {
+ message: `Rename saved: ${this._newName}`,
+ newName: this._newName,
+ },
+ })
+ );
+ this._toggleRename();
+ }
+
+ /**
+ * Handle when close button on tag is clicked
+ * @param {event} event event
+ */
+ handleCloseTag(event) {
+ this.dispatchEvent(
+ new CustomEvent('close-tag', {
+ detail: {
+ message: `Tag closed: ${event.target.title}`,
+ closedTag: event.target.title,
+ tagType: event.target.ariaLabel,
+ },
+ })
+ );
+ }
+
+ /**
+ * fire event when new context variable is added to the view
+ *
+ */
+ addContextVariable() {
+ this.dispatchEvent(
+ new CustomEvent('add-context-variable', {
+ detail: {
+ message: `Add context variable: ${this._newContextVariable}`,
+ newContextVariable: this._newContextVariable,
+ },
+ })
+ );
+ this._toggleAddContextVariable();
+ }
+
+ /**
+ * fire event when new parameter is added to the view
+ *
+ */
+ addParameter() {
+ this.dispatchEvent(
+ new CustomEvent('add-parameter', {
+ detail: {
+ message: `Add parameter: ${this._newParameter}`,
+ newParameter: this._newParameter,
+ },
+ })
+ );
+ this._toggleAddParameter();
+ }
+
+ /**
+ * Event handler to handle new context variable name
+ * @param {event} event event
+ */
+ _handleContextVariableInput(event) {
+ this._newContextVariable = event.target.value;
+ }
+
+ /**
+ * Event handler to handle new parameter name
+ * @param {event} event event
+ */
+ _handleParameterInput(event) {
+ this._newParameter = event.target.value;
+ }
+
+ /**
+ * fire event when save button when editing prompt is triggered
+ *
+ */
+ triggerSubmit() {
+ const form = this.shadowRoot?.getElementById(
+ `${clabsPrefix}--edit-prompt-form`
+ );
+ if (form) {
+ form.dispatchEvent(new Event('submit'));
+ }
+ this._onEditModalCancel();
+ }
+
+ /**
+ * Event handler when prompt edit is saved
+ * @param {event} event event
+ */
+ onSavePrompt(event) {
+ event.preventDefault();
+ const form = event.target;
+
+ if (form) {
+ const className = `.${clabsPrefix}--edit-form-item`;
+ const items = form.querySelectorAll(className);
+ const data = {};
+ items.forEach((item) => {
+ let key = '';
+
+ if (item.classList.contains(`${clabsPrefix}--edit-context-variable`)) {
+ key += '(context variable) ';
+ } else if (item.classList.contains(`${clabsPrefix}--edit-parameter`)) {
+ key += '(parameter) ';
+ }
+
+ if (item.tagName === 'CDS-TEXT-INPUT') {
+ key += item.__label;
+ data[key] = item._value;
+ } else if (item.tagName === 'CDS-SELECT') {
+ key += item.__labelText;
+ data[key] = item.__value;
+ } else {
+ key += item.__label;
+ data[key] = item._value;
+ }
+ });
+
+ if (this._isNewPrompt) {
+ this.dispatchEvent(
+ new CustomEvent('add-prompt', {
+ detail: { formData: data },
+ })
+ );
+ } else {
+ this.dispatchEvent(
+ new CustomEvent('save-prompt', {
+ detail: { formData: data },
+ })
+ );
+ }
+ }
+ }
+
+ /**
+ * Event handler to handle user changing current view
+ * @param {event} event event
+ */
+ onChangeView(event) {
+ this.dispatchEvent(
+ new CustomEvent('change-view', {
+ detail: { newView: event.target.value },
+ })
+ );
+ }
+
+ // /**
+ // * updated - check changed properties
+ // * @param {object} changedProperties - LIT object denoting changed attributes
+ // */
+ // updated(changedProperties) {
+ // console.log(`updated`);
+ // super.updated(changedProperties);
+ // if (changedProperties.has('isListModalOpen')) {
+ // console.log(`updated isListModalOpen: ${this.isListModalOpen}`);
+ // // this.isListModalOpen = this.isListModalOpen;
+ // }
+ // }
+}
diff --git a/packages/prompt-tuning/examples/prompt-tuning/.gitignore b/packages/prompt-tuning/examples/prompt-tuning/.gitignore
new file mode 100644
index 00000000..d94d6e13
--- /dev/null
+++ b/packages/prompt-tuning/examples/prompt-tuning/.gitignore
@@ -0,0 +1,22 @@
+# See https://help.github.com/ignore-files/ for more about ignoring files.
+
+# dependencies
+/node_modules
+
+# testing
+/coverage
+
+# production
+/build
+
+# misc
+.DS_Store
+.cache
+.env.local
+.env.development.local
+.env.test.local
+.env.production.local
+
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
diff --git a/packages/prompt-tuning/examples/prompt-tuning/cdn.html b/packages/prompt-tuning/examples/prompt-tuning/cdn.html
new file mode 100644
index 00000000..fe966e04
--- /dev/null
+++ b/packages/prompt-tuning/examples/prompt-tuning/cdn.html
@@ -0,0 +1,41 @@
+
+
+
+
+ @carbon-labs/ai-prompt-tuning example
+
+
+
+
+
+
+
+
+
+ Tag text
+
+
+
diff --git a/packages/prompt-tuning/examples/prompt-tuning/index.html b/packages/prompt-tuning/examples/prompt-tuning/index.html
new file mode 100644
index 00000000..ee440ed3
--- /dev/null
+++ b/packages/prompt-tuning/examples/prompt-tuning/index.html
@@ -0,0 +1,28 @@
+
+
+
+
+ @carbon/ibmdotcom-web-components example
+
+
+
+
+
+
+
+ Tag text
+
+
+
diff --git a/packages/prompt-tuning/examples/prompt-tuning/package.json b/packages/prompt-tuning/examples/prompt-tuning/package.json
new file mode 100644
index 00000000..f4814ae9
--- /dev/null
+++ b/packages/prompt-tuning/examples/prompt-tuning/package.json
@@ -0,0 +1,21 @@
+{
+ "name": "carbon-labs-ai-prompt-tuning-example",
+ "private": true,
+ "version": "0.0.0",
+ "type": "module",
+ "scripts": {
+ "clean": "rimraf node_modules dist .cache",
+ "dev": "vite",
+ "build": "vite build",
+ "preview": "vite preview"
+ },
+ "devDependencies": {
+ "rimraf": "^3.0.2",
+ "sass": "^1.55.0",
+ "vite": "^3.2.2"
+ },
+ "dependencies": {
+ "@carbon/styles": "^1.53.0",
+ "@carbon-labs/ai-prompt-tuning": "latest"
+ }
+}
diff --git a/packages/prompt-tuning/examples/prompt-tuning/src/index.js b/packages/prompt-tuning/examples/prompt-tuning/src/index.js
new file mode 100644
index 00000000..33dc8a31
--- /dev/null
+++ b/packages/prompt-tuning/examples/prompt-tuning/src/index.js
@@ -0,0 +1,10 @@
+/**
+ * @license
+ *
+ * Copyright IBM Corp. 2020, 2023
+ *
+ * This source code is licensed under the Apache-2.0 license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+import '@carbon-labs/ai-prompt-tuning/es/index.js';
diff --git a/packages/prompt-tuning/examples/prompt-tuning/src/styles.scss b/packages/prompt-tuning/examples/prompt-tuning/src/styles.scss
new file mode 100644
index 00000000..29117089
--- /dev/null
+++ b/packages/prompt-tuning/examples/prompt-tuning/src/styles.scss
@@ -0,0 +1,17 @@
+//
+// Copyright IBM Corp. 2024
+//
+// This source code is licensed under the Apache-2.0 license found in the
+// LICENSE file in the root directory of this source tree.
+//
+
+@use '@carbon/styles/scss/reset';
+@use '@carbon/styles/scss/theme';
+@use '@carbon/styles/scss/themes';
+
+:root {
+ @include theme.theme(themes.$white);
+
+ background-color: var(--cds-background);
+ color: var(--cds-text-primary);
+}
diff --git a/packages/prompt-tuning/index.ts b/packages/prompt-tuning/index.ts
new file mode 100644
index 00000000..4f0597a2
--- /dev/null
+++ b/packages/prompt-tuning/index.ts
@@ -0,0 +1,10 @@
+/**
+ * @license
+ *
+ * Copyright IBM Corp. 2023
+ *
+ * This source code is licensed under the Apache-2.0 license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+import './components/prompt-tuning/prompt-tuning.js';
diff --git a/packages/prompt-tuning/package.json b/packages/prompt-tuning/package.json
new file mode 100644
index 00000000..20462f7f
--- /dev/null
+++ b/packages/prompt-tuning/package.json
@@ -0,0 +1,41 @@
+{
+ "name": "@carbon-labs/ai-prompt-tuning",
+ "version": "0.0.1",
+ "publishConfig": {
+ "access": "public",
+ "provenance": true
+ },
+ "type": "module",
+ "description": "Carbon for AI - prompt-tuning component",
+ "license": "Apache-2.0",
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/carbon-design-system/carbon-labs",
+ "directory": "packages/prompt-tuning"
+ },
+ "main": "./src/index.js",
+ "module": "./src/index.js",
+ "exports": {
+ ".": {
+ "default": "./src/index.js"
+ },
+ "./es/": "./es/"
+ },
+ "files": [
+ "es/**/*",
+ "custom-elements.json"
+ ],
+ "types": "./src/index.d.ts",
+ "customElements": "custom-elements.json",
+ "scripts": {
+ "build": "gulp build --option prompt-tuning",
+ "build:dist": "rm -rf dist && rollup --config ../../tools/rollup.config.dist.js",
+ "build:dist:canary": "rm -rf dist && rollup --config ../../tools/rollup.config.dist.js --configCanary"
+ },
+ "dependencies": {
+ "@babel/runtime": "^7.23.2",
+ "@carbon-labs/utilities": "0.8.0",
+ "@carbon/grid": "^11.21.0",
+ "@carbon/web-components": "2.9.0"
+ }
+}
diff --git a/yarn.lock b/yarn.lock
index bee50c43..89b10a86 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2651,6 +2651,17 @@ __metadata:
languageName: unknown
linkType: soft
+"@carbon-labs/ai-prompt-tuning@workspace:packages/prompt-tuning":
+ version: 0.0.0-use.local
+ resolution: "@carbon-labs/ai-prompt-tuning@workspace:packages/prompt-tuning"
+ dependencies:
+ "@babel/runtime": "npm:^7.23.2"
+ "@carbon-labs/utilities": "npm:0.8.0"
+ "@carbon/grid": "npm:^11.21.0"
+ "@carbon/web-components": "npm:2.9.0"
+ languageName: unknown
+ linkType: soft
+
"@carbon-labs/ai-tag@workspace:packages/tag":
version: 0.0.0-use.local
resolution: "@carbon-labs/ai-tag@workspace:packages/tag"