diff --git a/apex/select-ai-chat/f101.sql b/apex/select-ai-chat/f101.sql index d0fa1a4..b4fe47c 100644 --- a/apex/select-ai-chat/f101.sql +++ b/apex/select-ai-chat/f101.sql @@ -33,7 +33,7 @@ prompt APPLICATION 101 - ADB Chat -- Application Export: -- Application: 101 -- Name: ADB Chat --- Date and Time: 23:34 Thursday February 13, 2025 +-- Date and Time: 19:45 Thursday February 20, 2025 -- Exported By: ADBCHAT -- Flashback: 0 -- Export Type: Application Export @@ -242524,6 +242524,7 @@ wwv_flow_imp_page.create_page_process( ' l_has_summary number;', ' l_prompt varchar2(4000);', ' v_profile_name varchar2(100);', +' v_summary_profile_name varchar2(100);', ' l_profile_names user_cloud_ai_profiles.profile_name%type := lower(APEX_UTIL.GET_PREFERENCE( ', ' p_preference => ''CLOUD_AI_PROFILE'',', ' p_user => :APP_USER));', @@ -242532,9 +242533,18 @@ wwv_flow_imp_page.create_page_process( ' -- Is this a chat or ask database?', ' b_is_chat := case when upper(:P1_ASK_ADB) = ''Y'' then false else true end;', '', +' -- Get the AI profile for this prompt. It will choose from the list of profiles that were selected by the user', +' v_profile_name:= ADB_CHAT.get_profile(', +' profile_names => JSON(l_profile_names),', +' prompt => :P1_PROMPT,', +' is_chat => b_is_chat', +' );', +'', +' v_profile_name := UPPER(v_profile_name);', +'', ' -- Generate response using prompt and profiles', ' j_response:= ADB_CHAT.generate(', -' profile_names => JSON(l_profile_names),', +' profile_name => v_profile_name,', ' prompt => :P1_PROMPT,', ' is_chat => b_is_chat', ' );', @@ -242553,8 +242563,8 @@ wwv_flow_imp_page.create_page_process( '', ' if l_has_summary = 0 then', ' -- Yes! Generate the summary b/c one does not exist.', -' -- get a profile to generate the response:', -' v_profile_name:= ADB_CHAT.get_profile(', +' -- get a profile to generate the response. ', +' v_summary_profile_name:= ADB_CHAT.get_profile(', ' profile_names => JSON(l_profile_names),', ' prompt => :P1_PROMPT,', ' is_chat => true', @@ -242563,7 +242573,7 @@ wwv_flow_imp_page.create_page_process( ' l_prompt := dbms_cloud_ai.generate(', ' prompt => ''Rewrite as a short title : ''||:P1_PROMPT,', ' action => ''chat'',', -' profile_name => v_profile_name', +' profile_name => v_summary_profile_name', ' );', '', ' ', @@ -242572,8 +242582,8 @@ wwv_flow_imp_page.create_page_process( ' ', ' end if;', '', -' insert into ADB_CHAT_PROMPTS (conv_id, prompt, response, asked_on, showsql) ', -' values (:p1_conv_id, :p1_prompt, c_response, systimestamp, c_sql);', +' insert into ADB_CHAT_PROMPTS (conv_id, profile_name, prompt, response, asked_on, showsql) ', +' values (:p1_conv_id, v_profile_name, :p1_prompt, c_response, systimestamp, c_sql);', '', 'end;')) ,p_process_clob_language=>'PLSQL' @@ -243663,6 +243673,9 @@ wwv_flow_imp_page.create_page( ' word-wrap: break-word;', ' font-family: inherit;', ' font-size: inherit;', +'}', +'.CodeMirror{', +'height : 45vh!important', '}')) ,p_page_template_options=>'#DEFAULT#' ,p_protection_level=>'C' @@ -243716,8 +243729,9 @@ wwv_flow_imp_page.create_page_plug( 'begin', '', '', -' SELECT SHOWSQL into l_showsql FROM ADB_CHAT_PROMPTS WHERE ID = :P3_CURRENT_ID;', -' SELECT PROMPT into l_prompt FROM ADB_CHAT_PROMPTS WHERE ID = :P3_CURRENT_ID;', +' SELECT SHOWSQL INTO l_showsql FROM ADB_CHAT_PROMPTS WHERE ID = :P3_CURRENT_ID;', +' SELECT PROMPT INTO l_prompt FROM ADB_CHAT_PROMPTS WHERE ID = :P3_CURRENT_ID;', +' SELECT PROFILE_NAME INTO l_profile_name FROM ADB_CHAT_PROMPTS WHERE ID = :P3_CURRENT_ID;', '', ' -- You can''t get an explanation if the current model was changed to Vector Search', ' SELECT count(*) ', @@ -244460,6 +244474,10 @@ wwv_flow_imp_shared.create_install_script( ,p_sequence=>10 ,p_script_type=>'INSTALL' ,p_script_clob=>wwv_flow_string.join(wwv_flow_t_varchar2( +'drop table if EXISTS ADB_CHAT_PROMPTS;', +'drop table if EXISTS ADB_CHAT_CONVERSATIONS;', +'', +'', ' CREATE TABLE "ADB_CHAT_CONVERSATIONS" ', ' ( "ID" NUMBER GENERATED BY DEFAULT ON NULL AS IDENTITY MINVALUE 1 MAXVALUE 9999999999999999999999999999 INCREMENT BY 1 START WITH 1 CACHE 20 NOORDER NOCYCLE NOKEEP NOSCALE NOT NULL ENABLE, ', ' "SUMMARY" VARCHAR2(4000 CHAR), ', @@ -244472,6 +244490,7 @@ wwv_flow_imp_shared.create_install_script( ' CREATE TABLE "ADB_CHAT_PROMPTS" ', ' ( "ID" NUMBER GENERATED BY DEFAULT ON NULL AS IDENTITY MINVALUE 1 MAXVALUE 9999999999999999999999999999 INCREMENT BY 1 START WITH 1 CACHE 20 NOORDER NOCYCLE NOKEEP NOSCALE NOT NULL ENABLE, ', ' "CONV_ID" NUMBER NOT NULL ENABLE, ', +' "PROFILE_NAME" VARCHAR2(400), ', ' "PROMPT" VARCHAR2(4000 CHAR), ', ' "RESPONSE" CLOB, ', ' "ASKED_ON" TIMESTAMP (6), ', @@ -244485,6 +244504,7 @@ wwv_flow_imp_shared.create_install_script( '', ' CREATE INDEX "ADB_CHAT_PROMPTS_I1" ON "ADB_CHAT_PROMPTS" ("CONV_ID") ', ' ;', +'', 'create or replace PACKAGE adb_chat AS', ' /**', ' * Generate SQL or return a response from the given prompt. Pass multiple profile names to if you want to search across multiple domains.', @@ -244499,6 +244519,18 @@ wwv_flow_imp_shared.create_install_script( ' FUNCTION generate(profile_names JSON, prompt clob, is_chat boolean default false) RETURN JSON;', '', ' /**', +' * Generate SQL or return a response from the given prompt. Pass a single profile name.', +' * If you do pass multiple profile names, you will need to provide a description when define the profile using dbms_cloud_ai.create_profile(description => ''xx'')', +' * @param profile_name : A single profile name that will be used to generate the response', +' * @param prompt : The question you would like to get an answer to', +' * @return : A JSON object with the fillowing attributes: ', +' sql : the generated SQL for a natural language query', +' response : the narrated response to a question. ', +' error : true | false. There was an error processing the request.', +' */', +' FUNCTION generate(profile_name VARCHAR2, prompt clob, is_chat boolean default false) RETURN JSON;', +'', +' /**', ' * Returns the profile name that will be used to process the prompt. See above for details', ' * This can be called independently. It is called by the generate function.', ' * @param profile_names : List of profile names in a JSON array ["profile1", "profile2"]', @@ -244520,8 +244552,11 @@ wwv_flow_imp_shared.create_install_script( '/', '', '', +'', +'', +'', 'create or replace PACKAGE BODY adb_chat AS', -' /**', +' /**', ' * Generate SQL or return a response from the given prompt. Pass multiple profile names to if you want to search across multiple domains.', ' * If you do pass multiple profile names, you will need to provide a description when define the profile using dbms_cloud_ai.create_profile(description => ''xx'')', ' * @param profile_names : List of profile names in a JSON array ["profile1", "profile2"]', @@ -244541,8 +244576,45 @@ wwv_flow_imp_shared.create_install_script( ' -- Get the profile', ' v_profile_name := get_profile(profile_names, prompt, is_chat);', '', +' -- Get the response', +' j_response := generate(v_profile_name, prompt, is_chat);', +'', +' -- Return the JSON doc', +' RETURN j_response; ', +' END;', +'', +'', +' /**', +' * Generate SQL or return a response from the given prompt. Pass a single profile name.', +' * If you do pass multiple profile names, you will need to provide a description when define the profile using dbms_cloud_ai.create_profile(description => ''xx'')', +' * @param profile_name : A single profile name that will be used to generate the response', +' * @param prompt : The question you would like to get an answer to', +' * @return : A JSON object with the fillowing attributes: ', +' sql : the generated SQL for a natural language query', +' response : the narrated response to a question. ', +' error : true | false. There was an error processing the request.', +' */', +' FUNCTION generate(profile_name VARCHAR2, prompt clob, is_chat boolean default false) RETURN JSON IS', +' v_profile_name varchar2(100);', +' v_action VARCHAR2(100);', +' j_response JSON;', +' c_response CLOB;', +' i_uses_vector_index NUMBER;', +' i_num_profiles NUMBER;', +' c_sql clob;', +' i_cursor NUMBER := dbms_sql.open_cursor;', +'', +' BEGIN', +' -- Ensure the profile is valid', +' v_profile_name := upper(profile_name);', +'', +' SELECT COUNT(profile_name)', +' INTO i_num_profiles', +' FROM user_cloud_ai_profiles', +' WHERE profile_name = v_profile_name;', +'', ' -- If CHAT, then simply call the model to get an answer', -' IF is_chat and v_profile_name is not null THEN', +' IF is_chat and v_profile_name is not null AND i_num_profiles !=0 THEN', ' c_response := dbms_cloud_ai.generate(', ' prompt => prompt,', ' action => ''chat'',', @@ -244555,7 +244627,7 @@ wwv_flow_imp_shared.create_install_script( ' ''error'' VALUE false', ' RETURNING JSON);', '', -' ELSIF v_profile_name IS NULL THEN', +' ELSIF v_profile_name IS NULL OR i_num_profiles = 0 THEN', ' -- There''s no AI profile, so error out.', ' j_response := JSON_OBJECT(', ' ''sql'' VALUE null,', @@ -244590,7 +244662,7 @@ wwv_flow_imp_shared.create_install_script( ' ELSE', ' -- NL2SQL: generate the sql and then execute it', ' c_sql := dbms_cloud_ai.generate(', -' prompt => prompt || '' format column headings using camel case with spaces.'',', +' prompt => prompt,', ' action => ''showsql'',', ' profile_name => v_profile_name', ' );', @@ -244766,6 +244838,9 @@ wwv_flow_imp_shared.create_install_script( 'END adb_chat;', '/', '', +'', +'', +'', ' ')) ); wwv_flow_imp_shared.create_install_object(