Procházet zdrojové kódy

support summary mode

Yuki Takei před 1 rokem
rodič
revize
f298decb62

+ 41 - 26
apps/app/src/features/openai/chat/components/AiChatModal/AiChatModal.tsx

@@ -34,6 +34,7 @@ type Message = {
 
 
 type FormData = {
 type FormData = {
   input: string;
   input: string;
+  summaryMode?: boolean;
 };
 };
 
 
 const AiChatModalSubstance = (): JSX.Element => {
 const AiChatModalSubstance = (): JSX.Element => {
@@ -97,7 +98,7 @@ const AiChatModalSubstance = (): JSX.Element => {
     setMessageLogs(msgs => [...msgs, newUserMessage]);
     setMessageLogs(msgs => [...msgs, newUserMessage]);
 
 
     // reset form
     // reset form
-    form.reset();
+    form.reset({ input: '', summaryMode: data.summaryMode });
     setErrorMessage(undefined);
     setErrorMessage(undefined);
 
 
     // add an empty assistant message
     // add an empty assistant message
@@ -109,7 +110,7 @@ const AiChatModalSubstance = (): JSX.Element => {
       const response = await fetch('/_api/v3/openai/message', {
       const response = await fetch('/_api/v3/openai/message', {
         method: 'POST',
         method: 'POST',
         headers: { 'Content-Type': 'application/json' },
         headers: { 'Content-Type': 'application/json' },
-        body: JSON.stringify({ userMessage: data.input, threadId }),
+        body: JSON.stringify({ userMessage: data.input, threadId, summaryMode: data.summaryMode }),
       });
       });
 
 
       if (!response.ok) {
       if (!response.ok) {
@@ -215,32 +216,46 @@ const AiChatModalSubstance = (): JSX.Element => {
       </ModalBody>
       </ModalBody>
 
 
       <ModalFooter className="flex-column align-items-start pt-0 pb-3 pb-lg-4 px-3 px-lg-4">
       <ModalFooter className="flex-column align-items-start pt-0 pb-3 pb-lg-4 px-3 px-lg-4">
-        <form onSubmit={form.handleSubmit(submit)} className="flex-fill hstack gap-2 align-items-end m-0">
-          <Controller
-            name="input"
-            control={form.control}
-            render={({ field }) => (
-              <ResizableTextarea
-                {...field}
-                required
-                className="form-control textarea-ask"
-                style={{ resize: 'none' }}
-                rows={1}
-                placeholder={!form.formState.isSubmitting ? t('modal_aichat.placeholder') : ''}
-                onKeyDown={keyDownHandler}
-                disabled={form.formState.isSubmitting}
-              />
-            )}
-          />
-          <button
-            type="submit"
-            className="btn btn-submit no-border"
-            disabled={form.formState.isSubmitting || isGenerating}
-          >
-            <span className="material-symbols-outlined">send</span>
-          </button>
+        <form onSubmit={form.handleSubmit(submit)} className="flex-fill vstack gap-3">
+          <div className="flex-fill hstack gap-2 align-items-end m-0">
+            <Controller
+              name="input"
+              control={form.control}
+              render={({ field }) => (
+                <ResizableTextarea
+                  {...field}
+                  required
+                  className="form-control textarea-ask"
+                  style={{ resize: 'none' }}
+                  rows={1}
+                  placeholder={!form.formState.isSubmitting ? t('modal_aichat.placeholder') : ''}
+                  onKeyDown={keyDownHandler}
+                  disabled={form.formState.isSubmitting}
+                />
+              )}
+            />
+            <button
+              type="submit"
+              className="btn btn-submit no-border"
+              disabled={form.formState.isSubmitting || isGenerating}
+            >
+              <span className="material-symbols-outlined">send</span>
+            </button>
+          </div>
+          <div className="form-check form-switch">
+            <input
+              id="swSummaryMode"
+              type="checkbox"
+              role="switch"
+              className="form-check-input"
+              {...form.register('summaryMode')}
+              disabled={form.formState.isSubmitting || isGenerating}
+            />
+            <label className="form-check-label" htmlFor="swSummaryMode">Summary Mode</label>
+          </div>
         </form>
         </form>
 
 
+
         {form.formState.errors.input != null && (
         {form.formState.errors.input != null && (
           <div className="mt-4 bg-danger bg-opacity-10 rounded-3 p-2 w-100">
           <div className="mt-4 bg-danger bg-opacity-10 rounded-3 p-2 w-100">
             <div>
             <div>

+ 10 - 1
apps/app/src/features/openai/server/routes/message.ts

@@ -24,6 +24,7 @@ const logger = loggerFactory('growi:routes:apiv3:openai:message');
 type ReqBody = {
 type ReqBody = {
   userMessage: string,
   userMessage: string,
   threadId?: string,
   threadId?: string,
+  summaryMode?: boolean,
 }
 }
 
 
 type Req = Request<undefined, Response, ReqBody>
 type Req = Request<undefined, Response, ReqBody>
@@ -61,7 +62,15 @@ export const postMessageHandlersFactory: PostMessageHandlersFactory = (crowi) =>
 
 
         stream = openaiClient.beta.threads.runs.stream(thread.id, {
         stream = openaiClient.beta.threads.runs.stream(thread.id, {
           assistant_id: assistant.id,
           assistant_id: assistant.id,
-          additional_messages: [{ role: 'user', content: req.body.userMessage }],
+          additional_messages: [
+            {
+              role: 'assistant',
+              content: req.body.summaryMode
+                ? 'Turn on summary mode: I will try to answer concisely, aiming for 1-3 sentences.'
+                : 'I will turn off summary mode and answer.',
+            },
+            { role: 'user', content: req.body.userMessage },
+          ],
         });
         });
 
 
       }
       }