Bladeren bron

feat: support binding context var (#1227)

Co-authored-by: Joel <iamjoel007@gmail.com>
Garfield Dai 1 jaar geleden
bovenliggende
commit
18c710c906
44 gewijzigde bestanden met toevoegingen van 711 en 72 verwijderingen
  1. 71 0
      api/commands.py
  2. 3 1
      api/controllers/console/app/app.py
  3. 2 1
      api/controllers/console/app/model_config.py
  4. 12 3
      api/core/completion.py
  5. 31 0
      api/migrations/versions/ab23c11305d4_add_dataset_query_variable_at_app_model_.py
  6. 4 0
      api/models/model.py
  7. 21 1
      api/services/app_model_config_service.py
  8. 2 1
      api/services/completion_service.py
  9. 0 6
      web/app/components/app/configuration/base/icons/var-icon.tsx
  10. 31 0
      web/app/components/app/configuration/base/warning-mask/cannot-query-dataset.tsx
  11. 4 3
      web/app/components/app/configuration/base/warning-mask/formatting-changed.tsx
  12. 45 9
      web/app/components/app/configuration/config-var/index.tsx
  13. 10 15
      web/app/components/app/configuration/config-var/input-type-icon.tsx
  14. 39 0
      web/app/components/app/configuration/dataset-config/context-var/index.tsx
  15. 3 0
      web/app/components/app/configuration/dataset-config/context-var/style.module.css
  16. 99 0
      web/app/components/app/configuration/dataset-config/context-var/var-picker.tsx
  17. 37 2
      web/app/components/app/configuration/dataset-config/index.tsx
  18. 21 2
      web/app/components/app/configuration/debug/index.tsx
  19. 13 4
      web/app/components/app/configuration/index.tsx
  20. 2 2
      web/app/components/app/configuration/prompt-value-panel/index.tsx
  21. 3 1
      web/app/components/base/confirm/common.tsx
  22. 3 0
      web/app/components/base/icons/assets/vender/line/development/brackets-x.svg
  23. 5 0
      web/app/components/base/icons/assets/vender/solid/editor/paragraph.svg
  24. 3 0
      web/app/components/base/icons/assets/vender/solid/editor/type-square.svg
  25. 4 0
      web/app/components/base/icons/assets/vender/solid/general/check-done-01.svg
  26. 29 0
      web/app/components/base/icons/src/vender/line/development/BracketsX.json
  27. 16 0
      web/app/components/base/icons/src/vender/line/development/BracketsX.tsx
  28. 1 0
      web/app/components/base/icons/src/vender/line/development/index.ts
  29. 44 0
      web/app/components/base/icons/src/vender/solid/editor/Paragraph.json
  30. 16 0
      web/app/components/base/icons/src/vender/solid/editor/Paragraph.tsx
  31. 28 0
      web/app/components/base/icons/src/vender/solid/editor/TypeSquare.json
  32. 16 0
      web/app/components/base/icons/src/vender/solid/editor/TypeSquare.tsx
  33. 2 0
      web/app/components/base/icons/src/vender/solid/editor/index.ts
  34. 37 0
      web/app/components/base/icons/src/vender/solid/general/CheckDone01.json
  35. 16 0
      web/app/components/base/icons/src/vender/solid/general/CheckDone01.tsx
  36. 1 0
      web/app/components/base/icons/src/vender/solid/general/index.ts
  37. 2 0
      web/context/debug-configuration.ts
  38. 13 0
      web/i18n/lang/app-debug.en.ts
  39. 13 0
      web/i18n/lang/app-debug.zh.ts
  40. 1 0
      web/models/debug.ts
  41. 1 0
      web/tailwind.config.js
  42. 1 0
      web/types/app.ts
  43. 6 1
      web/utils/model-config.ts
  44. 0 20
      web/yarn.lock

+ 71 - 0
api/commands.py

@@ -647,6 +647,76 @@ def update_app_model_configs(batch_size):
 
             pbar.update(len(data_batch))
 
+@click.command('migrate_default_input_to_dataset_query_variable')
+@click.option("--batch-size", default=500, help="Number of records to migrate in each batch.")
+def migrate_default_input_to_dataset_query_variable(batch_size):
+
+    click.secho("Starting...", fg='green')
+
+    total_records = db.session.query(AppModelConfig) \
+        .join(App, App.app_model_config_id == AppModelConfig.id) \
+        .filter(App.mode == 'completion') \
+        .filter(AppModelConfig.dataset_query_variable == None) \
+        .count()
+    
+    if total_records == 0:
+        click.secho("No data to migrate.", fg='green')
+        return
+
+    num_batches = (total_records + batch_size - 1) // batch_size
+    
+    with tqdm(total=total_records, desc="Migrating Data") as pbar:
+        for i in range(num_batches):
+            offset = i * batch_size
+            limit = min(batch_size, total_records - offset)
+
+            click.secho(f"Fetching batch {i + 1}/{num_batches} from source database...", fg='green')
+
+            data_batch = db.session.query(AppModelConfig) \
+                .join(App, App.app_model_config_id == AppModelConfig.id) \
+                .filter(App.mode == 'completion') \
+                .filter(AppModelConfig.dataset_query_variable == None) \
+                .order_by(App.created_at) \
+                .offset(offset).limit(limit).all()
+
+            if not data_batch:
+                click.secho("No more data to migrate.", fg='green')
+                break
+
+            try:
+                click.secho(f"Migrating {len(data_batch)} records...", fg='green')
+                for data in data_batch:
+                    config = AppModelConfig.to_dict(data)
+
+                    tools = config["agent_mode"]["tools"]
+                    dataset_exists = "dataset" in str(tools)
+                    if not dataset_exists:
+                        continue
+
+                    user_input_form = config.get("user_input_form", [])
+                    for form in user_input_form:
+                        paragraph = form.get('paragraph')
+                        if paragraph \
+                            and paragraph.get('variable') == 'query':
+                                data.dataset_query_variable = 'query'
+                                break
+                        
+                        if paragraph \
+                            and paragraph.get('variable') == 'default_input':
+                                data.dataset_query_variable = 'default_input'
+                                break
+
+                db.session.commit()
+
+            except Exception as e:
+                click.secho(f"Error while migrating data: {e}, app_id: {data.app_id}, app_model_config_id: {data.id}",
+                            fg='red')
+                continue
+            
+            click.secho(f"Successfully migrated batch {i + 1}/{num_batches}.", fg='green')
+
+            pbar.update(len(data_batch))
+
 
 def register_commands(app):
     app.cli.add_command(reset_password)
@@ -660,3 +730,4 @@ def register_commands(app):
     app.cli.add_command(update_qdrant_indexes)
     app.cli.add_command(update_app_model_configs)
     app.cli.add_command(normalization_collections)
+    app.cli.add_command(migrate_default_input_to_dataset_query_variable)

+ 3 - 1
api/controllers/console/app/app.py

@@ -34,6 +34,7 @@ model_config_fields = {
     'sensitive_word_avoidance': fields.Raw(attribute='sensitive_word_avoidance_dict'),
     'model': fields.Raw(attribute='model_dict'),
     'user_input_form': fields.Raw(attribute='user_input_form_list'),
+    'dataset_query_variable': fields.String,
     'pre_prompt': fields.String,
     'agent_mode': fields.Raw(attribute='agent_mode_dict'),
 }
@@ -162,7 +163,8 @@ class AppListApi(Resource):
             model_configuration = AppModelConfigService.validate_configuration(
                 tenant_id=current_user.current_tenant_id,
                 account=current_user,
-                config=model_config_dict
+                config=model_config_dict,
+                mode=args['mode']
             )
 
             app = App(

+ 2 - 1
api/controllers/console/app/model_config.py

@@ -31,7 +31,8 @@ class ModelConfigResource(Resource):
         model_configuration = AppModelConfigService.validate_configuration(
             tenant_id=current_user.current_tenant_id,
             account=current_user,
-            config=request.json
+            config=request.json,
+            mode=app_model.mode
         )
 
         new_app_model_config = AppModelConfig(

+ 12 - 3
api/core/completion.py

@@ -108,12 +108,14 @@ class Completion:
                 retriever_from=retriever_from
             )
 
+            query_for_agent = cls.get_query_for_agent(app, app_model_config, query, inputs)
+
             # run agent executor
             agent_execute_result = None
-            if agent_executor:
-                should_use_agent = agent_executor.should_use_agent(query)
+            if query_for_agent and agent_executor:
+                should_use_agent = agent_executor.should_use_agent(query_for_agent)
                 if should_use_agent:
-                    agent_execute_result = agent_executor.run(query)
+                    agent_execute_result = agent_executor.run(query_for_agent)
 
             # When no extra pre prompt is specified,
             # the output of the agent can be used directly as the main output content without calling LLM again
@@ -142,6 +144,13 @@ class Completion:
             logging.warning(f'ChunkedEncodingError: {e}')
             conversation_message_task.end()
             return
+        
+    @classmethod
+    def get_query_for_agent(cls, app: App, app_model_config: AppModelConfig, query: str, inputs: dict) -> str:
+        if app.mode != 'completion':
+            return query
+        
+        return inputs.get(app_model_config.dataset_query_variable, "")
 
     @classmethod
     def run_final_llm(cls, model_instance: BaseLLM, mode: str, app_model_config: AppModelConfig, query: str,

+ 31 - 0
api/migrations/versions/ab23c11305d4_add_dataset_query_variable_at_app_model_.py

@@ -0,0 +1,31 @@
+"""add dataset query variable at app model configs.
+
+Revision ID: ab23c11305d4
+Revises: 6e2cfb077b04
+Create Date: 2023-09-26 12:22:59.044088
+
+"""
+from alembic import op
+import sqlalchemy as sa
+
+# revision identifiers, used by Alembic.
+revision = 'ab23c11305d4'
+down_revision = '6e2cfb077b04'
+branch_labels = None
+depends_on = None
+
+
+def upgrade():
+    # ### commands auto generated by Alembic - please adjust! ###
+    with op.batch_alter_table('app_model_configs', schema=None) as batch_op:
+        batch_op.add_column(sa.Column('dataset_query_variable', sa.String(length=255), nullable=True))
+
+    # ### end Alembic commands ###
+
+
+def downgrade():
+    # ### commands auto generated by Alembic - please adjust! ###
+    with op.batch_alter_table('app_model_configs', schema=None) as batch_op:
+        batch_op.drop_column('dataset_query_variable')
+
+    # ### end Alembic commands ###

+ 4 - 0
api/models/model.py

@@ -88,6 +88,7 @@ class AppModelConfig(db.Model):
     more_like_this = db.Column(db.Text)
     model = db.Column(db.Text)
     user_input_form = db.Column(db.Text)
+    dataset_query_variable = db.Column(db.String(255))
     pre_prompt = db.Column(db.Text)
     agent_mode = db.Column(db.Text)
     sensitive_word_avoidance = db.Column(db.Text)
@@ -152,6 +153,7 @@ class AppModelConfig(db.Model):
             "sensitive_word_avoidance": self.sensitive_word_avoidance_dict,
             "model": self.model_dict,
             "user_input_form": self.user_input_form_list,
+            "dataset_query_variable": self.dataset_query_variable,
             "pre_prompt": self.pre_prompt,
             "agent_mode": self.agent_mode_dict
         }
@@ -170,6 +172,7 @@ class AppModelConfig(db.Model):
             if model_config.get('sensitive_word_avoidance') else None
         self.model = json.dumps(model_config['model'])
         self.user_input_form = json.dumps(model_config['user_input_form'])
+        self.dataset_query_variable = model_config['dataset_query_variable']
         self.pre_prompt = model_config['pre_prompt']
         self.agent_mode = json.dumps(model_config['agent_mode'])
         self.retriever_resource = json.dumps(model_config['retriever_resource']) \
@@ -191,6 +194,7 @@ class AppModelConfig(db.Model):
             sensitive_word_avoidance=self.sensitive_word_avoidance,
             model=self.model,
             user_input_form=self.user_input_form,
+            dataset_query_variable=self.dataset_query_variable,
             pre_prompt=self.pre_prompt,
             agent_mode=self.agent_mode
         )

+ 21 - 1
api/services/app_model_config_service.py

@@ -81,7 +81,7 @@ class AppModelConfigService:
         return filtered_cp
 
     @staticmethod
-    def validate_configuration(tenant_id: str, account: Account, config: dict) -> dict:
+    def validate_configuration(tenant_id: str, account: Account, config: dict, mode: str) -> dict:
         # opening_statement
         if 'opening_statement' not in config or not config["opening_statement"]:
             config["opening_statement"] = ""
@@ -335,6 +335,9 @@ class AppModelConfigService:
 
                 if not AppModelConfigService.is_dataset_exists(account, tool_item["id"]):
                     raise ValueError("Dataset ID does not exist, please check your permission.")
+        
+        # dataset_query_variable
+        AppModelConfigService.is_dataset_query_variable_valid(config, mode)
 
         # Filter out extra parameters
         filtered_config = {
@@ -351,8 +354,25 @@ class AppModelConfigService:
                 "completion_params": config["model"]["completion_params"]
             },
             "user_input_form": config["user_input_form"],
+            "dataset_query_variable": config["dataset_query_variable"],
             "pre_prompt": config["pre_prompt"],
             "agent_mode": config["agent_mode"]
         }
 
         return filtered_config
+    
+    @staticmethod
+    def is_dataset_query_variable_valid(config: dict, mode: str) -> None:
+        # Only check when mode is completion
+        if mode != 'completion':
+            return
+        
+        agent_mode = config.get("agent_mode", {})
+        tools = agent_mode.get("tools", [])
+        dataset_exists = "dataset" in str(tools)
+        
+        dataset_query_variable = config.get("dataset_query_variable")
+
+        if dataset_exists and not dataset_query_variable:
+            raise ValueError("Dataset query variable is required when dataset is exist")
+

+ 2 - 1
api/services/completion_service.py

@@ -117,7 +117,8 @@ class CompletionService:
                 model_config = AppModelConfigService.validate_configuration(
                     tenant_id=app_model.tenant_id,
                     account=user,
-                    config=args['model_config']
+                    config=args['model_config'],
+                    mode=app_model.mode
                 )
 
                 app_model_config = AppModelConfig(

File diff suppressed because it is too large
+ 0 - 6
web/app/components/app/configuration/base/icons/var-icon.tsx


+ 31 - 0
web/app/components/app/configuration/base/warning-mask/cannot-query-dataset.tsx

@@ -0,0 +1,31 @@
+'use client'
+import type { FC } from 'react'
+import React from 'react'
+import { useTranslation } from 'react-i18next'
+import WarningMask from '.'
+import Button from '@/app/components/base/button'
+
+export type IFormattingChangedProps = {
+  onConfirm: () => void
+}
+
+const FormattingChanged: FC<IFormattingChangedProps> = ({
+  onConfirm,
+}) => {
+  const { t } = useTranslation()
+
+  return (
+    <WarningMask
+      title={t('appDebug.feature.dataSet.queryVariable.unableToQueryDataSet')}
+      description={t('appDebug.feature.dataSet.queryVariable.unableToQueryDataSetTip')}
+      footer={
+        <div className='flex space-x-2'>
+          <Button type='primary' className='flex items-center justify-start !h-8 !w-[96px]' onClick={onConfirm}>
+            <span className='text-[13px] font-medium'>{t('appDebug.feature.dataSet.queryVariable.ok')}</span>
+          </Button>
+        </div>
+      }
+    />
+  )
+}
+export default React.memo(FormattingChanged)

+ 4 - 3
web/app/components/app/configuration/base/warning-mask/formatting-changed.tsx

@@ -1,10 +1,11 @@
 'use client'
-import React, { FC } from 'react'
+import type { FC } from 'react'
+import React from 'react'
 import { useTranslation } from 'react-i18next'
 import WarningMask from '.'
 import Button from '@/app/components/base/button'
 
-export interface IFormattingChangedProps {
+export type IFormattingChangedProps = {
   onConfirm: () => void
   onCancel: () => void
 }
@@ -17,7 +18,7 @@ const icon = (
 
 const FormattingChanged: FC<IFormattingChangedProps> = ({
   onConfirm,
-  onCancel
+  onCancel,
 }) => {
   const { t } = useTranslation()
 

+ 45 - 9
web/app/components/app/configuration/config-var/index.tsx

@@ -5,19 +5,24 @@ import { useTranslation } from 'react-i18next'
 import { Cog8ToothIcon, TrashIcon } from '@heroicons/react/24/outline'
 import { useBoolean } from 'ahooks'
 import type { Timeout } from 'ahooks/lib/useRequest/src/types'
+import { useContext } from 'use-context-selector'
 import Panel from '../base/feature-panel'
 import OperationBtn from '../base/operation-btn'
-import VarIcon from '../base/icons/var-icon'
 import EditModal from './config-modal'
 import IconTypeIcon from './input-type-icon'
 import type { IInputTypeIconProps } from './input-type-icon'
 import s from './style.module.css'
+import { BracketsX as VarIcon } from '@/app/components/base/icons/src/vender/line/development'
 import Tooltip from '@/app/components/base/tooltip'
 import type { PromptVariable } from '@/models/debug'
 import { DEFAULT_VALUE_MAX_LEN, getMaxVarNameLength } from '@/config'
 import { checkKeys, getNewVar } from '@/utils/var'
 import Switch from '@/app/components/base/switch'
 import Toast from '@/app/components/base/toast'
+import { HelpCircle } from '@/app/components/base/icons/src/vender/line/general'
+import ConfirmModal from '@/app/components/base/confirm/common'
+import ConfigContext from '@/context/debug-configuration'
+import { AppType } from '@/types/app'
 
 export type IConfigVarProps = {
   promptVariables: PromptVariable[]
@@ -29,6 +34,11 @@ let conflictTimer: Timeout
 
 const ConfigVar: FC<IConfigVarProps> = ({ promptVariables, readonly, onPromptVariablesChange }) => {
   const { t } = useTranslation()
+  const {
+    mode,
+    dataSets,
+  } = useContext(ConfigContext)
+
   const hasVar = promptVariables.length > 0
   const promptVariableObj = (() => {
     const obj: Record<string, boolean> = {}
@@ -127,10 +137,23 @@ const ConfigVar: FC<IConfigVarProps> = ({ promptVariables, readonly, onPromptVar
     onPromptVariablesChange?.([...promptVariables, newVar])
   }
 
-  const handleRemoveVar = (index: number) => {
+  const [isShowDeleteContextVarModal, { setTrue: showDeleteContextVarModal, setFalse: hideDeleteContextVarModal }] = useBoolean(false)
+  const [removeIndex, setRemoveIndex] = useState<number | null>(null)
+  const didRemoveVar = (index: number) => {
     onPromptVariablesChange?.(promptVariables.filter((_, i) => i !== index))
   }
 
+  const handleRemoveVar = (index: number) => {
+    const removeVar = promptVariables[index]
+
+    if (mode === AppType.completion && dataSets.length > 0 && removeVar.is_context_var) {
+      showDeleteContextVarModal()
+      setRemoveIndex(index)
+      return
+    }
+    didRemoveVar(index)
+  }
+
   const [currKey, setCurrKey] = useState<string | null>(null)
   const currItem = currKey ? promptVariables.find(item => item.key === currKey) : null
   const [isShowEditModal, { setTrue: showEditModal, setFalse: hideEditModal }] = useBoolean(false)
@@ -143,18 +166,17 @@ const ConfigVar: FC<IConfigVarProps> = ({ promptVariables, readonly, onPromptVar
     <Panel
       className="mt-4"
       headerIcon={
-        <VarIcon />
+        <VarIcon className='w-4 h-4 text-primary-500'/>
       }
       title={
-        <div className='flex items-center gap-2'>
-          <div>{t('appDebug.variableTitle')}</div>
+        <div className='flex items-center'>
+          <div className='ml-1 mr-1'>{t('appDebug.variableTitle')}</div>
           {!readonly && (
             <Tooltip htmlContent={<div className='w-[180px]'>
               {t('appDebug.variableTip')}
             </div>} selector='config-var-tooltip'>
-              <svg width="16" height="17" viewBox="0 0 16 17" fill="none" xmlns="http://www.w3.org/2000/svg">
-                <path d="M8.66667 11.1667H8V8.5H7.33333M8 5.83333H8.00667M14 8.5C14 9.28793 13.8448 10.0681 13.5433 10.7961C13.2417 11.5241 12.7998 12.1855 12.2426 12.7426C11.6855 13.2998 11.0241 13.7417 10.2961 14.0433C9.56815 14.3448 8.78793 14.5 8 14.5C7.21207 14.5 6.43185 14.3448 5.7039 14.0433C4.97595 13.7417 4.31451 13.2998 3.75736 12.7426C3.20021 12.1855 2.75825 11.5241 2.45672 10.7961C2.15519 10.0681 2 9.28793 2 8.5C2 6.9087 2.63214 5.38258 3.75736 4.25736C4.88258 3.13214 6.4087 2.5 8 2.5C9.5913 2.5 11.1174 3.13214 12.2426 4.25736C13.3679 5.38258 14 6.9087 14 8.5Z" stroke="#9CA3AF" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" />
-              </svg>
+              <HelpCircle className='w-3.5 h-3.5 text-gray-400'/>
+
             </Tooltip>
           )}
         </div>
@@ -185,7 +207,7 @@ const ConfigVar: FC<IConfigVarProps> = ({ promptVariables, readonly, onPromptVar
                 <tr key={index} className="h-9 leading-9">
                   <td className="w-[160px] border-b border-gray-100 pl-3">
                     <div className='flex items-center space-x-1'>
-                      <IconTypeIcon type={type as IInputTypeIconProps['type']} />
+                      <IconTypeIcon type={type as IInputTypeIconProps['type']} className='text-gray-400' />
                       {!readonly
                         ? (
                           <input
@@ -260,6 +282,20 @@ const ConfigVar: FC<IConfigVarProps> = ({ promptVariables, readonly, onPromptVar
         />
       )}
 
+      {isShowDeleteContextVarModal && (
+        <ConfirmModal
+          isShow={isShowDeleteContextVarModal}
+          title={t('appDebug.feature.dataSet.queryVariable.deleteContextVarTitle', { varName: promptVariables[removeIndex as number]?.name })}
+          desc={t('appDebug.feature.dataSet.queryVariable.deleteContextVarTip') as string}
+          confirmBtnClassName='bg-[#B42318] hover:bg-[#B42318]'
+          onConfirm={() => {
+            didRemoveVar(removeIndex as number)
+            hideDeleteContextVarModal()
+          }}
+          onCancel={hideDeleteContextVarModal}
+        />
+      )}
+
     </Panel>
   )
 }

+ 10 - 15
web/app/components/app/configuration/config-var/input-type-icon.tsx

@@ -1,31 +1,25 @@
 'use client'
 import React from 'react'
 import type { FC } from 'react'
+import { Paragraph, TypeSquare } from '@/app/components/base/icons/src/vender/solid/editor'
+import { CheckDone01 } from '@/app/components/base/icons/src/vender/solid/general'
 
 export type IInputTypeIconProps = {
   type: 'string' | 'select'
+  className: string
 }
 
-const IconMap = (type: IInputTypeIconProps['type']) => {
+const IconMap = (type: IInputTypeIconProps['type'], className: string) => {
+  const classNames = `w-3.5 h-3.5 ${className}`
   const icons = {
     string: (
-      <svg width="12" height="12" viewBox="0 0 12 12" fill="none" xmlns="http://www.w3.org/2000/svg">
-        <path fillRule="evenodd" clipRule="evenodd" d="M3.52593 0.166672H8.47411C8.94367 0.166665 9.33123 0.166659 9.64692 0.192452C9.97481 0.219242 10.2762 0.276738 10.5593 0.420991C10.9984 0.644695 11.3553 1.00165 11.579 1.44069C11.7233 1.72381 11.7808 2.02522 11.8076 2.35311C11.8334 2.6688 11.8334 3.05634 11.8334 3.5259V8.47411C11.8334 8.94367 11.8334 9.33121 11.8076 9.6469C11.7808 9.97479 11.7233 10.2762 11.579 10.5593C11.3553 10.9984 10.9984 11.3553 10.5593 11.579C10.2762 11.7233 9.97481 11.7808 9.64692 11.8076C9.33123 11.8334 8.94369 11.8333 8.47413 11.8333H3.52592C3.05636 11.8333 2.66882 11.8334 2.35312 11.8076C2.02523 11.7808 1.72382 11.7233 1.44071 11.579C1.00167 11.3553 0.644711 10.9984 0.421006 10.5593C0.276753 10.2762 0.219257 9.97479 0.192468 9.6469C0.166674 9.33121 0.16668 8.94366 0.166687 8.4741V3.52591C0.16668 3.05635 0.166674 2.6688 0.192468 2.35311C0.219257 2.02522 0.276753 1.72381 0.421006 1.44069C0.644711 1.00165 1.00167 0.644695 1.44071 0.420991C1.72382 0.276738 2.02523 0.219242 2.35312 0.192452C2.66882 0.166659 3.05637 0.166665 3.52593 0.166672ZM3.08335 3.08334C3.08335 2.76117 3.34452 2.50001 3.66669 2.50001H8.33335C8.65552 2.50001 8.91669 2.76117 8.91669 3.08334C8.91669 3.4055 8.65552 3.66667 8.33335 3.66667H6.58335V8.91667C6.58335 9.23884 6.32219 9.5 6.00002 9.5C5.67785 9.5 5.41669 9.23884 5.41669 8.91667V3.66667H3.66669C3.34452 3.66667 3.08335 3.4055 3.08335 3.08334Z" fill="#98A2B3" />
-      </svg>
+      <TypeSquare className={classNames} />
     ),
     paragraph: (
-      <svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
-        <path fillRule="evenodd" clipRule="evenodd" d="M1.16669 5.83329C1.16669 5.51113 1.42785 5.24996 1.75002 5.24996H9.33335C9.65552 5.24996 9.91669 5.51113 9.91669 5.83329C9.91669 6.15546 9.65552 6.41663 9.33335 6.41663H1.75002C1.42785 6.41663 1.16669 6.15546 1.16669 5.83329Z" fill="#98A2B3"/>
-        <path fillRule="evenodd" clipRule="evenodd" d="M1.16669 3.49996C1.16669 3.17779 1.42785 2.91663 1.75002 2.91663H11.6667C11.9889 2.91663 12.25 3.17779 12.25 3.49996C12.25 3.82213 11.9889 4.08329 11.6667 4.08329H1.75002C1.42785 4.08329 1.16669 3.82213 1.16669 3.49996Z" fill="#98A2B3"/>
-        <path fillRule="evenodd" clipRule="evenodd" d="M1.16669 8.16663C1.16669 7.84446 1.42785 7.58329 1.75002 7.58329H11.6667C11.9889 7.58329 12.25 7.84446 12.25 8.16663C12.25 8.48879 11.9889 8.74996 11.6667 8.74996H1.75002C1.42785 8.74996 1.16669 8.48879 1.16669 8.16663Z" fill="#98A2B3"/>
-        <path fillRule="evenodd" clipRule="evenodd" d="M1.16669 10.5C1.16669 10.1778 1.42785 9.91663 1.75002 9.91663H9.33335C9.65552 9.91663 9.91669 10.1778 9.91669 10.5C9.91669 10.8221 9.65552 11.0833 9.33335 11.0833H1.75002C1.42785 11.0833 1.16669 10.8221 1.16669 10.5Z" fill="#98A2B3"/>
-      </svg>
+      <Paragraph className={classNames} />
     ),
     select: (
-      <svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
-        <path fillRule="evenodd" clipRule="evenodd" d="M7.48913 4.08334H3.01083C2.70334 4.08333 2.43804 4.08333 2.21955 4.10118C1.98893 4.12002 1.75955 4.16162 1.53883 4.27408C1.20955 4.44186 0.941831 4.70958 0.774053 5.03886C0.66159 5.25958 0.619989 5.48896 0.601147 5.71958C0.583295 5.93807 0.583304 6.20334 0.583313 6.51084V10.9892C0.583304 11.2967 0.583295 11.5619 0.601147 11.7804C0.619989 12.0111 0.66159 12.2404 0.774053 12.4612C0.941831 12.7904 1.20955 13.0582 1.53883 13.2259C1.75955 13.3384 1.98893 13.38 2.21955 13.3988C2.43803 13.4167 2.70329 13.4167 3.01077 13.4167H7.48912C7.7966 13.4167 8.06193 13.4167 8.28041 13.3988C8.51103 13.38 8.74041 13.3384 8.96113 13.2259C9.29041 13.0582 9.55813 12.7904 9.72591 12.4612C9.83837 12.2404 9.87997 12.0111 9.89882 11.7804C9.91667 11.5619 9.91666 11.2967 9.91665 10.9892V6.51087C9.91666 6.20336 9.91667 5.93808 9.89882 5.71958C9.87997 5.48896 9.83837 5.25958 9.72591 5.03886C9.55813 4.70958 9.29041 4.44186 8.96113 4.27408C8.74041 4.16162 8.51103 4.12002 8.28041 4.10118C8.06192 4.08333 7.79663 4.08333 7.48913 4.08334ZM7.70413 7.70416C7.93193 7.47635 7.93193 7.107 7.70413 6.8792C7.47632 6.65139 7.10697 6.65139 6.87917 6.8792L4.66665 9.09172L3.91246 8.33753C3.68465 8.10973 3.31531 8.10973 3.0875 8.33753C2.8597 8.56534 2.8597 8.93468 3.0875 9.16249L4.25417 10.3292C4.48197 10.557 4.85132 10.557 5.07913 10.3292L7.70413 7.70416Z" fill="#98A2B3" />
-        <path d="M10.9891 0.583344H6.51083C6.20334 0.583334 5.93804 0.583326 5.71955 0.601177C5.48893 0.620019 5.25955 0.66162 5.03883 0.774084C4.70955 0.941862 4.44183 1.20958 4.27405 1.53886C4.16159 1.75958 4.11999 1.98896 4.10115 2.21958C4.08514 2.41545 4.08349 2.64892 4.08333 2.91669L7.51382 2.91668C7.79886 2.91662 8.10791 2.91654 8.37541 2.9384C8.67818 2.96314 9.07818 3.02436 9.49078 3.23459C10.0396 3.51422 10.4858 3.96041 10.7654 4.50922C10.9756 4.92182 11.0369 5.32182 11.0616 5.62459C11.0835 5.8921 11.0834 6.20115 11.0833 6.48619L11.0833 9.91666C11.3511 9.9165 11.5845 9.91485 11.7804 9.89885C12.011 9.88 12.2404 9.8384 12.4611 9.72594C12.7904 9.55816 13.0581 9.29045 13.2259 8.96116C13.3384 8.74044 13.38 8.51106 13.3988 8.28044C13.4167 8.06196 13.4167 7.7967 13.4166 7.48922V3.01087C13.4167 2.70339 13.4167 2.43807 13.3988 2.21958C13.38 1.98896 13.3384 1.75958 13.2259 1.53886C13.0581 1.20958 12.7904 0.941862 12.4611 0.774084C12.2404 0.66162 12.011 0.620019 11.7804 0.601177C11.5619 0.583326 11.2966 0.583334 10.9891 0.583344Z" fill="#98A2B3" />
-      </svg>
+      <CheckDone01 className={classNames} />
     ),
   }
 
@@ -34,8 +28,9 @@ const IconMap = (type: IInputTypeIconProps['type']) => {
 
 const InputTypeIcon: FC<IInputTypeIconProps> = ({
   type,
+  className,
 }) => {
-  const Icon = IconMap(type)
+  const Icon = IconMap(type, className)
   return Icon
 }
 

+ 39 - 0
web/app/components/app/configuration/dataset-config/context-var/index.tsx

@@ -0,0 +1,39 @@
+'use client'
+import type { FC } from 'react'
+import React from 'react'
+import { useTranslation } from 'react-i18next'
+import cn from 'classnames'
+import type { Props } from './var-picker'
+import VarPicker from './var-picker'
+import { BracketsX } from '@/app/components/base/icons/src/vender/line/development'
+import Tooltip from '@/app/components/base/tooltip'
+import { HelpCircle } from '@/app/components/base/icons/src/vender/line/general'
+
+const ContextVar: FC<Props> = (props) => {
+  const { t } = useTranslation()
+  const { value, options } = props
+  const currItem = options.find(item => item.value === value)
+  const notSetVar = !currItem
+  return (
+    <div className={cn(notSetVar ? 'rounded-bl-xl rounded-br-xl bg-[#FEF0C7] border-[#FEF0C7]' : 'border-gray-200', 'flex justify-between items-center h-12 px-3 border-t ')}>
+      <div className='flex items-center space-x-1 shrink-0'>
+        <div className='p-1'>
+          <BracketsX className='w-4 h-4 text-primary-500'/>
+        </div>
+        <div className='mr-1 text-sm font-medium text-gray-800'>{t('appDebug.feature.dataSet.queryVariable.title')}</div>
+        <Tooltip
+          htmlContent={<div className='w-[180px]'>
+            {t('appDebug.feature.dataSet.queryVariable.tip')}
+          </div>}
+          selector='context-var-tooltip'
+        >
+          <HelpCircle className='w-3.5 h-3.5 text-gray-400'/>
+        </Tooltip>
+      </div>
+
+      <VarPicker {...props} />
+    </div>
+  )
+}
+
+export default React.memo(ContextVar)

+ 3 - 0
web/app/components/app/configuration/dataset-config/context-var/style.module.css

@@ -0,0 +1,3 @@
+.trigger:hover .dropdownIcon {
+  color: #98A2B3;
+}

+ 99 - 0
web/app/components/app/configuration/dataset-config/context-var/var-picker.tsx

@@ -0,0 +1,99 @@
+'use client'
+import type { FC } from 'react'
+import React, { useState } from 'react'
+import { useTranslation } from 'react-i18next'
+import { ChevronDownIcon } from '@heroicons/react/24/outline'
+import cn from 'classnames'
+import s from './style.module.css'
+import {
+  PortalToFollowElem,
+  PortalToFollowElemContent,
+  PortalToFollowElemTrigger,
+} from '@/app/components/base/portal-to-follow-elem'
+import type { IInputTypeIconProps } from '@/app/components/app/configuration/config-var/input-type-icon'
+import IconTypeIcon from '@/app/components/app/configuration/config-var/input-type-icon'
+
+type Option = { name: string; value: string; type: string }
+export type Props = {
+  value: string | undefined
+  options: Option[]
+  onChange: (value: string) => void
+}
+
+const VarItem: FC<{ item: Option }> = ({ item }) => (
+  <div className='flex items-center h-[18px] px-1 bg-[#EFF8FF] rounded space-x-1'>
+    <IconTypeIcon type={item.type as IInputTypeIconProps['type']} className='text-[#1570EF]' />
+    <div className='flex text-xs font-medium text-[#1570EF]'>
+      <span className='opacity-60'>{'{{'}</span>
+      <span className='max-w-[150px] truncate'>{item.value}</span>
+      <span className='opacity-60'>{'}}'}</span>
+    </div>
+  </div>
+)
+const VarPicker: FC<Props> = ({
+  value,
+  options,
+  onChange,
+}) => {
+  const { t } = useTranslation()
+  const [open, setOpen] = useState(false)
+  const currItem = options.find(item => item.value === value)
+  const notSetVar = !currItem
+  return (
+    <PortalToFollowElem
+      open={open}
+      onOpenChange={setOpen}
+      placement='bottom-end'
+      offset={{
+        mainAxis: 8,
+      }}
+    >
+      <PortalToFollowElemTrigger onClick={() => setOpen(v => !v)}>
+        <div className={cn(
+          s.trigger,
+          notSetVar ? 'bg-[#FFFCF5] border-[#FEDF89] text-[#DC6803]' : ' hover:bg-gray-50 border-gray-200 text-primary-600',
+          open ? 'bg-gray-50' : 'bg-white',
+          `
+          flex items-center h-8 justify-center px-2 space-x-1 rounded-lg border  shadow-xs cursor-pointer
+          text-[13px]  font-medium
+          `)}>
+          <div>
+            {value
+              ? (
+                <VarItem item={currItem as Option} />
+              )
+              : (<div>
+                {t('appDebug.feature.dataSet.queryVariable.choosePlaceholder')}
+              </div>)}
+          </div>
+          <ChevronDownIcon className={cn(s.dropdownIcon, open && 'rotate-180 text-[#98A2B3]', 'w-3.5 h-3.5')} />
+        </div>
+      </PortalToFollowElemTrigger>
+      <PortalToFollowElemContent style={{ zIndex: 1000 }}>
+        {options.length > 0
+          ? (<div className='w-[240px] max-h-[50vh] overflow-y-auto p-1  border bg-white border-gray-200 rounded-lg shadow-lg'>
+            {options.map(({ name, value, type }, index) => (
+              <div
+                key={index}
+                className='px-3 py-1 flex rounded-lg hover:bg-gray-50 cursor-pointer'
+                onClick={() => {
+                  onChange(value)
+                  setOpen(false)
+                }}
+              >
+                <VarItem item={{ name, value, type }} />
+              </div>
+            ))}
+          </div>)
+          : (
+            <div className='w-[240px] p-6 bg-white border border-gray-200 rounded-lg shadow-lg'>
+              <div className='mb-1 text-sm font-medium text-gray-700'>{t('appDebug.feature.dataSet.queryVariable.noVar')}</div>
+              <div className='text-xs leading-normal text-gray-500'>{t('appDebug.feature.dataSet.queryVariable.noVarTip')}</div>
+            </div>
+          )}
+
+      </PortalToFollowElemContent>
+    </PortalToFollowElem>
+  )
+}
+export default React.memo(VarPicker)

+ 37 - 2
web/app/components/app/configuration/dataset-config/index.tsx

@@ -10,8 +10,10 @@ import FeaturePanel from '../base/feature-panel'
 import OperationBtn from '../base/operation-btn'
 import CardItem from './card-item'
 import SelectDataSet from './select-dataset'
+import ContextVar from './context-var'
 import ConfigContext from '@/context/debug-configuration'
 import type { DataSet } from '@/models/datasets'
+import { AppType } from '@/types/app'
 
 const Icon = (
   <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
@@ -23,9 +25,12 @@ const Icon = (
 const DatasetConfig: FC = () => {
   const { t } = useTranslation()
   const {
+    mode,
     dataSets: dataSet,
     setDataSets: setDataSet,
     setFormattingChanged,
+    modelConfig,
+    setModelConfig,
   } = useContext(ConfigContext)
   const selectedIds = dataSet.map(item => item.id)
 
@@ -60,6 +65,25 @@ const DatasetConfig: FC = () => {
     setFormattingChanged(true)
   }
 
+  const promptVariables = modelConfig.configs.prompt_variables
+  const promptVariablesToSelect = promptVariables.map(item => ({
+    name: item.name,
+    type: item.type,
+    value: item.key,
+  }))
+  const selectedContextVar = promptVariables?.find(item => item.is_context_var)
+  const handleSelectContextVar = (selectedValue: string) => {
+    const newModelConfig = produce(modelConfig, (draft) => {
+      draft.configs.prompt_variables = modelConfig.configs.prompt_variables.map((item) => {
+        return ({
+          ...item,
+          is_context_var: item.key === selectedValue,
+        })
+      })
+    })
+    setModelConfig(newModelConfig)
+  }
+
   return (
     <FeaturePanel
       className='mt-3'
@@ -67,10 +91,11 @@ const DatasetConfig: FC = () => {
       title={t('appDebug.feature.dataSet.title')}
       headerRight={<OperationBtn type="add" onClick={showSelectDataSet} />}
       hasHeaderBottomBorder={!hasData}
+      noBodySpacing
     >
       {hasData
         ? (
-          <div className='flex flex-wrap justify-between'>
+          <div className='flex flex-wrap mt-1 px-3 justify-between'>
             {dataSet.map(item => (
               <CardItem
                 className="mb-2"
@@ -82,9 +107,19 @@ const DatasetConfig: FC = () => {
           </div>
         )
         : (
-          <div className='pt-2 pb-1 text-xs text-gray-500'>{t('appDebug.feature.dataSet.noData')}</div>
+          <div className='mt-1 px-3 pb-3'>
+            <div className='pt-2 pb-1 text-xs text-gray-500'>{t('appDebug.feature.dataSet.noData')}</div>
+          </div>
         )}
 
+      {mode === AppType.completion && dataSet.length > 0 && (
+        <ContextVar
+          value={selectedContextVar?.key}
+          options={promptVariablesToSelect}
+          onChange={handleSelectContextVar}
+        />
+      )}
+
       {isShowSelectDataSet && (
         <SelectDataSet
           isShow={isShowSelectDataSet}

+ 21 - 2
web/app/components/app/configuration/debug/index.tsx

@@ -10,6 +10,7 @@ import dayjs from 'dayjs'
 import HasNotSetAPIKEY from '../base/warning-mask/has-not-set-api'
 import FormattingChanged from '../base/warning-mask/formatting-changed'
 import GroupName from '../base/group-name'
+import CannotQueryDataset from '../base/warning-mask/cannot-query-dataset'
 import { AppType } from '@/types/app'
 import PromptValuePanel, { replaceStringWithValues } from '@/app/components/app/configuration/prompt-value-panel'
 import type { IChatItem } from '@/app/components/app/chat/type'
@@ -23,7 +24,6 @@ import { promptVariablesToUserInputsForm } from '@/utils/model-config'
 import TextGeneration from '@/app/components/app/text-generate/item'
 import { IS_CE_EDITION } from '@/config'
 import { useProviderContext } from '@/context/provider-context'
-
 type IDebug = {
   hasSetAPIKEY: boolean
   onSetting: () => void
@@ -52,6 +52,7 @@ const Debug: FC<IDebug> = ({
     dataSets,
     modelConfig,
     completionParams,
+    hasSetContextVar,
   } = useContext(ConfigContext)
   const { speech2textDefaultModel } = useProviderContext()
   const [chatList, setChatList, getChatList] = useGetState<IChatItem[]>([])
@@ -77,6 +78,7 @@ const Debug: FC<IDebug> = ({
   const [isResponsing, { setTrue: setResponsingTrue, setFalse: setResponsingFalse }] = useBoolean(false)
   const [abortController, setAbortController] = useState<AbortController | null>(null)
   const [isShowFormattingChangeConfirm, setIsShowFormattingChangeConfirm] = useState(false)
+  const [isShowCannotQueryDataset, setShowCannotQueryDataset] = useState(false)
   const [isShowSuggestion, setIsShowSuggestion] = useState(false)
   const [messageTaskId, setMessageTaskId] = useState('')
   const [hasStopResponded, setHasStopResponded, getHasStopResponded] = useGetState(false)
@@ -157,6 +159,7 @@ const Debug: FC<IDebug> = ({
     const postModelConfig: BackendModelConfig = {
       pre_prompt: modelConfig.configs.prompt_template,
       user_input_form: promptVariablesToUserInputsForm(modelConfig.configs.prompt_variables),
+      dataset_query_variable: '',
       opening_statement: introduction,
       more_like_this: {
         enabled: false,
@@ -298,6 +301,7 @@ const Debug: FC<IDebug> = ({
   }, [controlClearChatMessage])
 
   const [completionRes, setCompletionRes] = useState('')
+  const [messageId, setMessageId] = useState<string | null>(null)
 
   const sendTextCompletion = async () => {
     if (isResponsing) {
@@ -305,6 +309,11 @@ const Debug: FC<IDebug> = ({
       return false
     }
 
+    if (dataSets.length > 0 && !hasSetContextVar) {
+      setShowCannotQueryDataset(true)
+      return true
+    }
+
     if (!checkCanSend())
       return
 
@@ -314,10 +323,12 @@ const Debug: FC<IDebug> = ({
         id,
       },
     }))
+    const contextVar = modelConfig.configs.prompt_variables.find(item => item.is_context_var)?.key
 
     const postModelConfig: BackendModelConfig = {
       pre_prompt: modelConfig.configs.prompt_template,
       user_input_form: promptVariablesToUserInputsForm(modelConfig.configs.prompt_variables),
+      dataset_query_variable: contextVar || '',
       opening_statement: introduction,
       suggested_questions_after_answer: suggestedQuestionsAfterAnswerConfig,
       speech_to_text: speechToTextConfig,
@@ -340,13 +351,15 @@ const Debug: FC<IDebug> = ({
     }
 
     setCompletionRes('')
+    setMessageId('')
     const res: string[] = []
 
     setResponsingTrue()
     sendCompletionMessage(appId, data, {
-      onData: (data: string) => {
+      onData: (data: string, _isFirstMessage: boolean, { messageId }) => {
         res.push(data)
         setCompletionRes(res.join(''))
+        setMessageId(messageId)
       },
       onCompleted() {
         setResponsingFalse()
@@ -415,6 +428,7 @@ const Debug: FC<IDebug> = ({
                 content={completionRes}
                 isLoading={!completionRes && isResponsing}
                 isInstalledApp={false}
+                messageId={messageId}
               />
             )}
           </div>
@@ -425,6 +439,11 @@ const Debug: FC<IDebug> = ({
             onCancel={handleCancel}
           />
         )}
+        {isShowCannotQueryDataset && (
+          <CannotQueryDataset
+            onConfirm={() => setShowCannotQueryDataset(false)}
+          />
+        )}
       </div>
 
       {!hasSetAPIKEY && (<HasNotSetAPIKEY isTrailFinished={!IS_CE_EDITION} onSetting={onSetting} />)}

+ 13 - 4
web/app/components/app/configuration/index.tsx

@@ -100,7 +100,8 @@ const Configuration: FC = () => {
   }
 
   const [dataSets, setDataSets] = useState<DataSet[]>([])
-
+  const contextVar = modelConfig.configs.prompt_variables.find(item => item.is_context_var)?.key
+  const hasSetContextVar = !!contextVar
   const syncToPublishedConfig = (_publishedConfig: PublichConfig) => {
     const modelConfig = _publishedConfig.modelConfig
     setModelConfig(_publishedConfig.modelConfig)
@@ -178,7 +179,7 @@ const Configuration: FC = () => {
           model_id: model.name,
           configs: {
             prompt_template: modelConfig.pre_prompt,
-            prompt_variables: userInputsFormToPromptVariables(modelConfig.user_input_form),
+            prompt_variables: userInputsFormToPromptVariables(modelConfig.user_input_form, modelConfig.dataset_query_variable),
           },
           opening_statement: modelConfig.opening_statement,
           more_like_this: modelConfig.more_like_this,
@@ -196,16 +197,22 @@ const Configuration: FC = () => {
     })
   }, [appId])
 
-  const cannotPublish = mode === AppType.completion && !modelConfig.configs.prompt_template
+  const promptEmpty = mode === AppType.completion && !modelConfig.configs.prompt_template
+  const contextVarEmpty = mode === AppType.completion && dataSets.length > 0 && !hasSetContextVar
+  const cannotPublish = promptEmpty || contextVarEmpty
   const saveAppConfig = async () => {
     const modelId = modelConfig.model_id
     const promptTemplate = modelConfig.configs.prompt_template
     const promptVariables = modelConfig.configs.prompt_variables
 
-    if (cannotPublish) {
+    if (promptEmpty) {
       notify({ type: 'error', message: t('appDebug.otherError.promptNoBeEmpty'), duration: 3000 })
       return
     }
+    if (contextVarEmpty) {
+      notify({ type: 'error', message: t('appDebug.feature.dataSet.queryVariable.contextVarNotEmpty'), duration: 3000 })
+      return
+    }
     const postDatasets = dataSets.map(({ id }) => ({
       dataset: {
         enabled: true,
@@ -217,6 +224,7 @@ const Configuration: FC = () => {
     const data: BackendModelConfig = {
       pre_prompt: promptTemplate,
       user_input_form: promptVariablesToUserInputsForm(promptVariables),
+      dataset_query_variable: contextVar || '',
       opening_statement: introduction || '',
       more_like_this: moreLikeThisConfig,
       suggested_questions_after_answer: suggestedQuestionsAfterAnswerConfig,
@@ -298,6 +306,7 @@ const Configuration: FC = () => {
       setModelConfig,
       dataSets,
       setDataSets,
+      hasSetContextVar,
     }}
     >
       <>

+ 2 - 2
web/app/components/app/configuration/prompt-value-panel/index.tsx

@@ -6,7 +6,7 @@ import { useContext } from 'use-context-selector'
 import {
   PlayIcon,
 } from '@heroicons/react/24/solid'
-import VarIcon from '../base/icons/var-icon'
+import { BracketsX as VarIcon } from '@/app/components/base/icons/src/vender/line/development'
 import ConfigContext from '@/context/debug-configuration'
 import type { PromptVariable } from '@/models/debug'
 import { AppType } from '@/types/app'
@@ -131,7 +131,7 @@ const PromptValuePanel: FC<IPromptValuePanelProps> = ({
           `${!userInputFieldCollapse && 'mb-2'}`
         }>
           <div className='flex items-center space-x-1 cursor-pointer' onClick={() => setUserInputFieldCollapse(!userInputFieldCollapse)}>
-            <div className='flex items-center justify-center w-4 h-4'><VarIcon /></div>
+            <div className='flex items-center justify-center w-4 h-4'><VarIcon className='w-4 h-4 text-primary-500'/></div>
             <div className='text-xs font-medium text-gray-800'>{t('appDebug.inputs.userInputField')}</div>
             {
               userInputFieldCollapse

+ 3 - 1
web/app/components/base/confirm/common.tsx

@@ -17,6 +17,7 @@ export type ConfirmCommonProps = {
   onConfirm?: () => void
   showOperate?: boolean
   showOperateCancel?: boolean
+  confirmBtnClassName?: string
   confirmText?: string
 }
 
@@ -29,6 +30,7 @@ const ConfirmCommon: FC<ConfirmCommonProps> = ({
   onConfirm,
   showOperate = true,
   showOperateCancel = true,
+  confirmBtnClassName,
   confirmText,
 }) => {
   const { t } = useTranslation()
@@ -72,7 +74,7 @@ const ConfirmCommon: FC<ConfirmCommonProps> = ({
               }
               <Button
                 type='primary'
-                className=''
+                className={confirmBtnClassName || ''}
                 onClick={onConfirm}
               >
                 {confirmText || CONFIRM_MAP[type].confirmText}

+ 3 - 0
web/app/components/base/icons/assets/vender/line/development/brackets-x.svg

@@ -0,0 +1,3 @@
+<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M18.5708 20C19.8328 20 20.8568 18.977 20.8568 17.714V13.143L21.9998 12L20.8568 10.857V6.286C20.8568 5.023 19.8338 4 18.5708 4M5.429 4C4.166 4 3.143 5.023 3.143 6.286V10.857L2 12L3.143 13.143V17.714C3.143 18.977 4.166 20 5.429 20M15 9L9 15M9 9L15 15" stroke="black" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
+</svg>

+ 5 - 0
web/app/components/base/icons/assets/vender/solid/editor/paragraph.svg

@@ -0,0 +1,5 @@
+<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M2 6.5C2 5.67157 2.67157 5 3.5 5H20.5C21.3284 5 22 5.67157 22 6.5C22 7.32843 21.3284 8 20.5 8H3.5C2.67157 8 2 7.32843 2 6.5Z" fill="black"/>
+<path d="M2 12.5C2 11.6716 2.67157 11 3.5 11H20.5C21.3284 11 22 11.6716 22 12.5C22 13.3284 21.3284 14 20.5 14H3.5C2.67157 14 2 13.3284 2 12.5Z" fill="black"/>
+<path d="M2 18.5C2 17.6716 2.67157 17 3.5 17H12.5C13.3284 17 14 17.6716 14 18.5C14 19.3284 13.3284 20 12.5 20H3.5C2.67157 20 2 19.3284 2 18.5Z" fill="black"/>
+</svg>

+ 3 - 0
web/app/components/base/icons/assets/vender/solid/editor/type-square.svg

@@ -0,0 +1,3 @@
+<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path fill-rule="evenodd" clip-rule="evenodd" d="M7.7587 2H16.2413C17.0463 1.99999 17.7106 1.99998 18.2518 2.0442C18.8139 2.09012 19.3306 2.18868 19.816 2.43598C20.5686 2.81947 21.1805 3.43139 21.564 4.18404C21.8113 4.66938 21.9099 5.18608 21.9558 5.74818C22 6.28937 22 6.95372 22 7.75868V16.2413C22 17.0463 22 17.7106 21.9558 18.2518C21.9099 18.8139 21.8113 19.3306 21.564 19.816C21.1805 20.5686 20.5686 21.1805 19.816 21.564C19.3306 21.8113 18.8139 21.9099 18.2518 21.9558C17.7106 22 17.0463 22 16.2413 22H7.75868C6.95372 22 6.28937 22 5.74818 21.9558C5.18608 21.9099 4.66938 21.8113 4.18404 21.564C3.43139 21.1805 2.81947 20.5686 2.43598 19.816C2.18868 19.3306 2.09012 18.8139 2.0442 18.2518C1.99998 17.7106 1.99999 17.0463 2 16.2413V7.75869C1.99999 6.95373 1.99998 6.28936 2.0442 5.74818C2.09012 5.18608 2.18868 4.66938 2.43598 4.18404C2.81947 3.43139 3.43139 2.81947 4.18404 2.43598C4.66938 2.18868 5.18608 2.09012 5.74818 2.0442C6.28936 1.99998 6.95375 1.99999 7.7587 2ZM7 7C7 6.44772 7.44772 6 8 6H16C16.5523 6 17 6.44772 17 7C17 7.55229 16.5523 8 16 8H13V17C13 17.5523 12.5523 18 12 18C11.4477 18 11 17.5523 11 17V8H8C7.44772 8 7 7.55229 7 7Z" fill="black"/>
+</svg>

+ 4 - 0
web/app/components/base/icons/assets/vender/solid/general/check-done-01.svg

@@ -0,0 +1,4 @@
+<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path fill-rule="evenodd" clip-rule="evenodd" d="M12.8385 7H5.16146C4.63433 6.99998 4.17954 6.99997 3.80497 7.03057C3.40963 7.06287 3.01641 7.13419 2.63803 7.32698C2.07354 7.6146 1.6146 8.07354 1.32698 8.63803C1.13419 9.01641 1.06287 9.40963 1.03057 9.80497C0.999969 10.1795 0.999984 10.6343 1 11.1614V18.8385C0.999984 19.3657 0.999969 19.8205 1.03057 20.195C1.06287 20.5904 1.13419 20.9836 1.32698 21.362C1.6146 21.9265 2.07354 22.3854 2.63803 22.673C3.01641 22.8658 3.40963 22.9371 3.80497 22.9694C4.17952 23 4.63425 23 5.16136 23H12.8385C13.3656 23 13.8205 23 14.195 22.9694C14.5904 22.9371 14.9836 22.8658 15.362 22.673C15.9265 22.3854 16.3854 21.9265 16.673 21.362C16.8658 20.9836 16.9371 20.5904 16.9694 20.195C17 19.8205 17 19.3657 17 18.8385V11.1615C17 10.6343 17 10.1796 16.9694 9.80497C16.9371 9.40963 16.8658 9.01641 16.673 8.63803C16.3854 8.07354 15.9265 7.6146 15.362 7.32698C14.9836 7.13419 14.5904 7.06287 14.195 7.03057C13.8205 6.99997 13.3657 6.99998 12.8385 7ZM13.2071 13.2071C13.5976 12.8166 13.5976 12.1834 13.2071 11.7929C12.8166 11.4024 12.1834 11.4024 11.7929 11.7929L8 15.5858L6.70711 14.2929C6.31658 13.9024 5.68342 13.9024 5.29289 14.2929C4.90237 14.6834 4.90237 15.3166 5.29289 15.7071L7.29289 17.7071C7.68342 18.0976 8.31658 18.0976 8.70711 17.7071L13.2071 13.2071Z" fill="black"/>
+<path d="M18.8385 1H11.1615C10.6343 0.999984 10.1795 0.999969 9.80497 1.03057C9.40963 1.06287 9.01641 1.13419 8.63803 1.32698C8.07354 1.6146 7.6146 2.07354 7.32698 2.63803C7.13419 3.01641 7.06287 3.40963 7.03057 3.80497C7.00314 4.14076 7.00031 4.54098 7.00003 5.00003L12.8809 5.00001C13.3695 4.9999 13.8993 4.99977 14.3579 5.03724C14.8769 5.07964 15.5626 5.1846 16.2699 5.54499C17.2108 6.02436 17.9757 6.78926 18.455 7.73007C18.8154 8.43739 18.9204 9.12311 18.9628 9.64213C19.0003 10.1007 19.0001 10.6305 19 11.1192L19 17C19.459 16.9997 19.8593 16.9969 20.195 16.9694C20.5904 16.9371 20.9836 16.8658 21.362 16.673C21.9265 16.3854 22.3854 15.9265 22.673 15.362C22.8658 14.9836 22.9371 14.5904 22.9694 14.195C23 13.8205 23 13.3658 23 12.8386V5.16148C23 4.63437 23 4.17952 22.9694 3.80497C22.9371 3.40963 22.8658 3.01641 22.673 2.63803C22.3854 2.07354 21.9265 1.6146 21.362 1.32698C20.9836 1.13419 20.5904 1.06287 20.195 1.03057C19.8205 0.999969 19.3657 0.999984 18.8385 1Z" fill="black"/>
+</svg>

+ 29 - 0
web/app/components/base/icons/src/vender/line/development/BracketsX.json

@@ -0,0 +1,29 @@
+{
+	"icon": {
+		"type": "element",
+		"isRootNode": true,
+		"name": "svg",
+		"attributes": {
+			"width": "24",
+			"height": "24",
+			"viewBox": "0 0 24 24",
+			"fill": "none",
+			"xmlns": "http://www.w3.org/2000/svg"
+		},
+		"children": [
+			{
+				"type": "element",
+				"name": "path",
+				"attributes": {
+					"d": "M18.5708 20C19.8328 20 20.8568 18.977 20.8568 17.714V13.143L21.9998 12L20.8568 10.857V6.286C20.8568 5.023 19.8338 4 18.5708 4M5.429 4C4.166 4 3.143 5.023 3.143 6.286V10.857L2 12L3.143 13.143V17.714C3.143 18.977 4.166 20 5.429 20M15 9L9 15M9 9L15 15",
+					"stroke": "currentColor",
+					"stroke-width": "2",
+					"stroke-linecap": "round",
+					"stroke-linejoin": "round"
+				},
+				"children": []
+			}
+		]
+	},
+	"name": "BracketsX"
+}

+ 16 - 0
web/app/components/base/icons/src/vender/line/development/BracketsX.tsx

@@ -0,0 +1,16 @@
+// GENERATE BY script
+// DON NOT EDIT IT MANUALLY
+
+import * as React from 'react'
+import data from './BracketsX.json'
+import IconBase from '@/app/components/base/icons/IconBase'
+import type { IconBaseProps, IconData } from '@/app/components/base/icons/IconBase'
+
+const Icon = React.forwardRef<React.MutableRefObject<SVGElement>, Omit<IconBaseProps, 'data'>>((
+  props,
+  ref,
+) => <IconBase {...props} ref={ref} data={data as IconData} />)
+
+Icon.displayName = 'BracketsX'
+
+export default Icon

+ 1 - 0
web/app/components/base/icons/src/vender/line/development/index.ts

@@ -1,3 +1,4 @@
+export { default as BracketsX } from './BracketsX'
 export { default as Container } from './Container'
 export { default as Database01 } from './Database01'
 export { default as Database03 } from './Database03'

+ 44 - 0
web/app/components/base/icons/src/vender/solid/editor/Paragraph.json

@@ -0,0 +1,44 @@
+{
+	"icon": {
+		"type": "element",
+		"isRootNode": true,
+		"name": "svg",
+		"attributes": {
+			"width": "24",
+			"height": "24",
+			"viewBox": "0 0 24 24",
+			"fill": "none",
+			"xmlns": "http://www.w3.org/2000/svg"
+		},
+		"children": [
+			{
+				"type": "element",
+				"name": "path",
+				"attributes": {
+					"d": "M2 6.5C2 5.67157 2.67157 5 3.5 5H20.5C21.3284 5 22 5.67157 22 6.5C22 7.32843 21.3284 8 20.5 8H3.5C2.67157 8 2 7.32843 2 6.5Z",
+					"fill": "currentColor"
+				},
+				"children": []
+			},
+			{
+				"type": "element",
+				"name": "path",
+				"attributes": {
+					"d": "M2 12.5C2 11.6716 2.67157 11 3.5 11H20.5C21.3284 11 22 11.6716 22 12.5C22 13.3284 21.3284 14 20.5 14H3.5C2.67157 14 2 13.3284 2 12.5Z",
+					"fill": "currentColor"
+				},
+				"children": []
+			},
+			{
+				"type": "element",
+				"name": "path",
+				"attributes": {
+					"d": "M2 18.5C2 17.6716 2.67157 17 3.5 17H12.5C13.3284 17 14 17.6716 14 18.5C14 19.3284 13.3284 20 12.5 20H3.5C2.67157 20 2 19.3284 2 18.5Z",
+					"fill": "currentColor"
+				},
+				"children": []
+			}
+		]
+	},
+	"name": "Paragraph"
+}

+ 16 - 0
web/app/components/base/icons/src/vender/solid/editor/Paragraph.tsx

@@ -0,0 +1,16 @@
+// GENERATE BY script
+// DON NOT EDIT IT MANUALLY
+
+import * as React from 'react'
+import data from './Paragraph.json'
+import IconBase from '@/app/components/base/icons/IconBase'
+import type { IconBaseProps, IconData } from '@/app/components/base/icons/IconBase'
+
+const Icon = React.forwardRef<React.MutableRefObject<SVGElement>, Omit<IconBaseProps, 'data'>>((
+  props,
+  ref,
+) => <IconBase {...props} ref={ref} data={data as IconData} />)
+
+Icon.displayName = 'Paragraph'
+
+export default Icon

+ 28 - 0
web/app/components/base/icons/src/vender/solid/editor/TypeSquare.json

@@ -0,0 +1,28 @@
+{
+	"icon": {
+		"type": "element",
+		"isRootNode": true,
+		"name": "svg",
+		"attributes": {
+			"width": "24",
+			"height": "24",
+			"viewBox": "0 0 24 24",
+			"fill": "none",
+			"xmlns": "http://www.w3.org/2000/svg"
+		},
+		"children": [
+			{
+				"type": "element",
+				"name": "path",
+				"attributes": {
+					"fill-rule": "evenodd",
+					"clip-rule": "evenodd",
+					"d": "M7.7587 2H16.2413C17.0463 1.99999 17.7106 1.99998 18.2518 2.0442C18.8139 2.09012 19.3306 2.18868 19.816 2.43598C20.5686 2.81947 21.1805 3.43139 21.564 4.18404C21.8113 4.66938 21.9099 5.18608 21.9558 5.74818C22 6.28937 22 6.95372 22 7.75868V16.2413C22 17.0463 22 17.7106 21.9558 18.2518C21.9099 18.8139 21.8113 19.3306 21.564 19.816C21.1805 20.5686 20.5686 21.1805 19.816 21.564C19.3306 21.8113 18.8139 21.9099 18.2518 21.9558C17.7106 22 17.0463 22 16.2413 22H7.75868C6.95372 22 6.28937 22 5.74818 21.9558C5.18608 21.9099 4.66938 21.8113 4.18404 21.564C3.43139 21.1805 2.81947 20.5686 2.43598 19.816C2.18868 19.3306 2.09012 18.8139 2.0442 18.2518C1.99998 17.7106 1.99999 17.0463 2 16.2413V7.75869C1.99999 6.95373 1.99998 6.28936 2.0442 5.74818C2.09012 5.18608 2.18868 4.66938 2.43598 4.18404C2.81947 3.43139 3.43139 2.81947 4.18404 2.43598C4.66938 2.18868 5.18608 2.09012 5.74818 2.0442C6.28936 1.99998 6.95375 1.99999 7.7587 2ZM7 7C7 6.44772 7.44772 6 8 6H16C16.5523 6 17 6.44772 17 7C17 7.55229 16.5523 8 16 8H13V17C13 17.5523 12.5523 18 12 18C11.4477 18 11 17.5523 11 17V8H8C7.44772 8 7 7.55229 7 7Z",
+					"fill": "currentColor"
+				},
+				"children": []
+			}
+		]
+	},
+	"name": "TypeSquare"
+}

+ 16 - 0
web/app/components/base/icons/src/vender/solid/editor/TypeSquare.tsx

@@ -0,0 +1,16 @@
+// GENERATE BY script
+// DON NOT EDIT IT MANUALLY
+
+import * as React from 'react'
+import data from './TypeSquare.json'
+import IconBase from '@/app/components/base/icons/IconBase'
+import type { IconBaseProps, IconData } from '@/app/components/base/icons/IconBase'
+
+const Icon = React.forwardRef<React.MutableRefObject<SVGElement>, Omit<IconBaseProps, 'data'>>((
+  props,
+  ref,
+) => <IconBase {...props} ref={ref} data={data as IconData} />)
+
+Icon.displayName = 'TypeSquare'
+
+export default Icon

+ 2 - 0
web/app/components/base/icons/src/vender/solid/editor/index.ts

@@ -1,2 +1,4 @@
 export { default as Brush01 } from './Brush01'
 export { default as Citations } from './Citations'
+export { default as Paragraph } from './Paragraph'
+export { default as TypeSquare } from './TypeSquare'

+ 37 - 0
web/app/components/base/icons/src/vender/solid/general/CheckDone01.json

@@ -0,0 +1,37 @@
+{
+	"icon": {
+		"type": "element",
+		"isRootNode": true,
+		"name": "svg",
+		"attributes": {
+			"width": "24",
+			"height": "24",
+			"viewBox": "0 0 24 24",
+			"fill": "none",
+			"xmlns": "http://www.w3.org/2000/svg"
+		},
+		"children": [
+			{
+				"type": "element",
+				"name": "path",
+				"attributes": {
+					"fill-rule": "evenodd",
+					"clip-rule": "evenodd",
+					"d": "M12.8385 7H5.16146C4.63433 6.99998 4.17954 6.99997 3.80497 7.03057C3.40963 7.06287 3.01641 7.13419 2.63803 7.32698C2.07354 7.6146 1.6146 8.07354 1.32698 8.63803C1.13419 9.01641 1.06287 9.40963 1.03057 9.80497C0.999969 10.1795 0.999984 10.6343 1 11.1614V18.8385C0.999984 19.3657 0.999969 19.8205 1.03057 20.195C1.06287 20.5904 1.13419 20.9836 1.32698 21.362C1.6146 21.9265 2.07354 22.3854 2.63803 22.673C3.01641 22.8658 3.40963 22.9371 3.80497 22.9694C4.17952 23 4.63425 23 5.16136 23H12.8385C13.3656 23 13.8205 23 14.195 22.9694C14.5904 22.9371 14.9836 22.8658 15.362 22.673C15.9265 22.3854 16.3854 21.9265 16.673 21.362C16.8658 20.9836 16.9371 20.5904 16.9694 20.195C17 19.8205 17 19.3657 17 18.8385V11.1615C17 10.6343 17 10.1796 16.9694 9.80497C16.9371 9.40963 16.8658 9.01641 16.673 8.63803C16.3854 8.07354 15.9265 7.6146 15.362 7.32698C14.9836 7.13419 14.5904 7.06287 14.195 7.03057C13.8205 6.99997 13.3657 6.99998 12.8385 7ZM13.2071 13.2071C13.5976 12.8166 13.5976 12.1834 13.2071 11.7929C12.8166 11.4024 12.1834 11.4024 11.7929 11.7929L8 15.5858L6.70711 14.2929C6.31658 13.9024 5.68342 13.9024 5.29289 14.2929C4.90237 14.6834 4.90237 15.3166 5.29289 15.7071L7.29289 17.7071C7.68342 18.0976 8.31658 18.0976 8.70711 17.7071L13.2071 13.2071Z",
+					"fill": "currentColor"
+				},
+				"children": []
+			},
+			{
+				"type": "element",
+				"name": "path",
+				"attributes": {
+					"d": "M18.8385 1H11.1615C10.6343 0.999984 10.1795 0.999969 9.80497 1.03057C9.40963 1.06287 9.01641 1.13419 8.63803 1.32698C8.07354 1.6146 7.6146 2.07354 7.32698 2.63803C7.13419 3.01641 7.06287 3.40963 7.03057 3.80497C7.00314 4.14076 7.00031 4.54098 7.00003 5.00003L12.8809 5.00001C13.3695 4.9999 13.8993 4.99977 14.3579 5.03724C14.8769 5.07964 15.5626 5.1846 16.2699 5.54499C17.2108 6.02436 17.9757 6.78926 18.455 7.73007C18.8154 8.43739 18.9204 9.12311 18.9628 9.64213C19.0003 10.1007 19.0001 10.6305 19 11.1192L19 17C19.459 16.9997 19.8593 16.9969 20.195 16.9694C20.5904 16.9371 20.9836 16.8658 21.362 16.673C21.9265 16.3854 22.3854 15.9265 22.673 15.362C22.8658 14.9836 22.9371 14.5904 22.9694 14.195C23 13.8205 23 13.3658 23 12.8386V5.16148C23 4.63437 23 4.17952 22.9694 3.80497C22.9371 3.40963 22.8658 3.01641 22.673 2.63803C22.3854 2.07354 21.9265 1.6146 21.362 1.32698C20.9836 1.13419 20.5904 1.06287 20.195 1.03057C19.8205 0.999969 19.3657 0.999984 18.8385 1Z",
+					"fill": "currentColor"
+				},
+				"children": []
+			}
+		]
+	},
+	"name": "CheckDone01"
+}

+ 16 - 0
web/app/components/base/icons/src/vender/solid/general/CheckDone01.tsx

@@ -0,0 +1,16 @@
+// GENERATE BY script
+// DON NOT EDIT IT MANUALLY
+
+import * as React from 'react'
+import data from './CheckDone01.json'
+import IconBase from '@/app/components/base/icons/IconBase'
+import type { IconBaseProps, IconData } from '@/app/components/base/icons/IconBase'
+
+const Icon = React.forwardRef<React.MutableRefObject<SVGElement>, Omit<IconBaseProps, 'data'>>((
+  props,
+  ref,
+) => <IconBase {...props} ref={ref} data={data as IconData} />)
+
+Icon.displayName = 'CheckDone01'
+
+export default Icon

+ 1 - 0
web/app/components/base/icons/src/vender/solid/general/index.ts

@@ -1,4 +1,5 @@
 export { default as CheckCircle } from './CheckCircle'
+export { default as CheckDone01 } from './CheckDone01'
 export { default as Download02 } from './Download02'
 export { default as Target04 } from './Target04'
 export { default as XCircle } from './XCircle'

+ 2 - 0
web/context/debug-configuration.ts

@@ -37,6 +37,7 @@ type IDebugConfiguration = {
   setModelConfig: (modelConfig: ModelConfig) => void
   dataSets: DataSet[]
   setDataSets: (dataSet: DataSet[]) => void
+  hasSetContextVar: boolean
 }
 
 const DebugConfigurationContext = createContext<IDebugConfiguration>({
@@ -102,6 +103,7 @@ const DebugConfigurationContext = createContext<IDebugConfiguration>({
   setModelConfig: () => { },
   dataSets: [],
   setDataSets: () => { },
+  hasSetContextVar: false,
 })
 
 export default DebugConfigurationContext

+ 13 - 0
web/i18n/lang/app-debug.en.ts

@@ -66,6 +66,19 @@ const translation = {
       noDataSet: 'No dataset found',
       toCreate: 'Go to create',
       notSupportSelectMulti: 'Currently only support one dataset',
+      queryVariable: {
+        title: 'Query variable',
+        tip: 'This variable will be used as the query input for context retrieval, obtaining context information related to the input of this variable.',
+        choosePlaceholder: 'Choose query variable',
+        noVar: 'No variables',
+        noVarTip: 'please create a variable under the Variables section',
+        unableToQueryDataSet: 'Unable to query the dataset',
+        unableToQueryDataSetTip: 'Unable to query the dataset successfully, please choose a context query variable in the context section.',
+        ok: 'OK',
+        contextVarNotEmpty: 'context query variable can not be empty',
+        deleteContextVarTitle: 'Delete variable “{{varName}}”?',
+        deleteContextVarTip: 'This variable has been set as a context query variable, and removing it will impact the normal use of the dataset. If you still need to delete it, please reselect it in the context section.',
+      },
     },
   },
   automatic: {

+ 13 - 0
web/i18n/lang/app-debug.zh.ts

@@ -66,6 +66,19 @@ const translation = {
       noDataSet: '未找到数据集',
       toCreate: '去创建',
       notSupportSelectMulti: '目前只支持引用一个数据集',
+      queryVariable: {
+        title: '查询变量',
+        tip: '该变量将用作上下文检索的查询输入,获取与该变量的输入相关的上下文信息。',
+        choosePlaceholder: '请选择变量',
+        noVar: '没有变量',
+        noVarTip: '请创建变量',
+        unableToQueryDataSet: '无法查询数据集',
+        unableToQueryDataSetTip: '无法成功查询数据集,请在上下文部分选择一个上下文查询变量。',
+        ok: '好的',
+        contextVarNotEmpty: '上下文查询变量不能为空',
+        deleteContextVarTitle: '删除变量“{{varName}}”?',
+        deleteContextVarTip: '该变量已被设置为上下文查询变量,删除该变量将影响数据集的正常使用。 如果您仍需要删除它,请在上下文部分中重新选择它。',
+      },
     },
   },
   automatic: {

+ 1 - 0
web/models/debug.ts

@@ -8,6 +8,7 @@ export type PromptVariable = {
   required: boolean
   options?: string[]
   max_length?: number
+  is_context_var?: boolean
 }
 
 export type CompletionParams = {

+ 1 - 0
web/tailwind.config.js

@@ -27,6 +27,7 @@ module.exports = {
           200: '#C3DDFD',
           300: '#A4CAFE',
           400: '#528BFF',
+          500: '#2970FF',
           600: '#1C64F2',
           700: '#1A56DB',
         },

+ 1 - 0
web/types/app.ts

@@ -90,6 +90,7 @@ export type ModelConfig = {
   opening_statement: string
   pre_prompt: string
   user_input_form: UserInputFormItem[]
+  dataset_query_variable?: string
   more_like_this: {
     enabled: boolean
   }

+ 6 - 1
web/utils/model-config.ts

@@ -1,12 +1,13 @@
 import type { UserInputFormItem } from '@/types/app'
 import type { PromptVariable } from '@/models/debug'
 
-export const userInputsFormToPromptVariables = (useInputs: UserInputFormItem[] | null) => {
+export const userInputsFormToPromptVariables = (useInputs: UserInputFormItem[] | null, dataset_query_variable?: string) => {
   if (!useInputs)
     return []
   const promptVariables: PromptVariable[] = []
   useInputs.forEach((item: any) => {
     const isParagraph = !!item.paragraph
+
     const [type, content] = (() => {
       if (isParagraph)
         return ['paragraph', item.paragraph]
@@ -16,6 +17,8 @@ export const userInputsFormToPromptVariables = (useInputs: UserInputFormItem[] |
 
       return ['select', item.select]
     })()
+    const is_context_var = dataset_query_variable === content.variable
+
     if (type === 'string' || type === 'paragraph') {
       promptVariables.push({
         key: content.variable,
@@ -24,6 +27,7 @@ export const userInputsFormToPromptVariables = (useInputs: UserInputFormItem[] |
         type,
         max_length: content.max_length,
         options: [],
+        is_context_var,
       })
     }
     else {
@@ -33,6 +37,7 @@ export const userInputsFormToPromptVariables = (useInputs: UserInputFormItem[] |
         required: content.required,
         type: 'select',
         options: content.options,
+        is_context_var,
       })
     }
   })

+ 0 - 20
web/yarn.lock

@@ -3752,11 +3752,7 @@ mdast-util-from-markdown@^0.8.5:
     parse-entities "^2.0.0"
     unist-util-stringify-position "^2.0.0"
 
-<<<<<<< Updated upstream
-mdast-util-from-markdown@^1.0.0, mdast-util-from-markdown@^1.1.0, mdast-util-from-markdown@^1.3.0:
-=======
 mdast-util-from-markdown@^1.0.0, mdast-util-from-markdown@^1.1.0:
->>>>>>> Stashed changes
   version "1.3.1"
   resolved "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-1.3.1.tgz"
   integrity sha512-4xTO/M8c82qBcnQc1tgpNtubGUW/Y1tBQ1B0i5CtSoelOLKFYlElIr3bvgREYYO5iRqbMY1YuqZng0GVOI8Qww==
@@ -5372,14 +5368,6 @@ safe-regex@^2.1.1:
   dependencies:
     regexp-tree "~0.1.1"
 
-<<<<<<< Updated upstream
-"safer-buffer@>= 2.1.2 < 3.0.0":
-  version "2.1.2"
-  resolved "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz"
-  integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
-
-=======
->>>>>>> Stashed changes
 sass@^1.61.0:
   version "1.62.1"
   resolved "https://registry.npmjs.org/sass/-/sass-1.62.1.tgz"
@@ -6127,14 +6115,6 @@ web-namespaces@^2.0.0:
   resolved "https://registry.npmjs.org/web-namespaces/-/web-namespaces-2.0.1.tgz"
   integrity sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ==
 
-<<<<<<< Updated upstream
-web-worker@^1.2.0:
-  version "1.2.0"
-  resolved "https://registry.npmjs.org/web-worker/-/web-worker-1.2.0.tgz"
-  integrity sha512-PgF341avzqyx60neE9DD+XS26MMNMoUQRz9NOZwW32nPQrF6p77f1htcnjBSEV8BGMKZ16choqUG4hyI0Hx7mA==
-
-=======
->>>>>>> Stashed changes
 which-boxed-primitive@^1.0.2:
   version "1.0.2"
   resolved "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz"

Some files were not shown because too many files changed in this diff