mirror of
				https://github.com/ChatGPTNextWeb/ChatGPT-Next-Web.git
				synced 2025-10-31 22:33:45 +08:00 
			
		
		
		
	Compare commits
	
		
			1 Commits
		
	
	
		
			v3
			...
			suggestion
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | f75b238ebe | 
| @@ -475,3 +475,21 @@ | |||||||
|     bottom: 30px; |     bottom: 30px; | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | .chat-suggestions { | ||||||
|  |   display: flex; | ||||||
|  |   flex-direction: column; | ||||||
|  |  | ||||||
|  |   .chat-suggestion { | ||||||
|  |     display: inline; | ||||||
|  |     white-space: nowrap; | ||||||
|  |     border-radius: 20px; | ||||||
|  |     font-size: 12px; | ||||||
|  |     background-color: var(--white); | ||||||
|  |     color: var(--black); | ||||||
|  |     border: var(--border-in-light); | ||||||
|  |     padding: 4px 10px; | ||||||
|  |     animation: slide-in ease 0.3s; | ||||||
|  |     margin-bottom: 5px; | ||||||
|  |   } | ||||||
|  | } | ||||||
|   | |||||||
| @@ -606,6 +606,8 @@ export function Chat() { | |||||||
|     } |     } | ||||||
|   }; |   }; | ||||||
|  |  | ||||||
|  |   const [suggestions, setSuggestions] = useState<string[]>([]); | ||||||
|  |  | ||||||
|   const doSubmit = (userInput: string) => { |   const doSubmit = (userInput: string) => { | ||||||
|     if (userInput.trim() === "") return; |     if (userInput.trim() === "") return; | ||||||
|     const matchCommand = chatCommands.match(userInput); |     const matchCommand = chatCommands.match(userInput); | ||||||
| @@ -616,7 +618,13 @@ export function Chat() { | |||||||
|       return; |       return; | ||||||
|     } |     } | ||||||
|     setIsLoading(true); |     setIsLoading(true); | ||||||
|     chatStore.onUserInput(userInput).then(() => setIsLoading(false)); |     setSuggestions([]); | ||||||
|  |     chatStore.onUserInput(userInput).then(() => { | ||||||
|  |       setIsLoading(false); | ||||||
|  |       chatStore | ||||||
|  |         .getSuggestions() | ||||||
|  |         .then((suggestions) => setSuggestions(suggestions)); | ||||||
|  |     }); | ||||||
|     localStorage.setItem(LAST_INPUT_KEY, userInput); |     localStorage.setItem(LAST_INPUT_KEY, userInput); | ||||||
|     setUserInput(""); |     setUserInput(""); | ||||||
|     setPromptHints([]); |     setPromptHints([]); | ||||||
| @@ -1061,6 +1069,25 @@ export function Chat() { | |||||||
|             onSearch(""); |             onSearch(""); | ||||||
|           }} |           }} | ||||||
|         /> |         /> | ||||||
|  |  | ||||||
|  |         {suggestions.length > 0 && ( | ||||||
|  |           <div className={styles["chat-suggestions"]}> | ||||||
|  |             {suggestions.map((s, i) => { | ||||||
|  |               return ( | ||||||
|  |                 <div | ||||||
|  |                   key={i} | ||||||
|  |                   className={styles["chat-suggestion"] + " clickable"} | ||||||
|  |                   onClick={() => { | ||||||
|  |                     doSubmit(s); | ||||||
|  |                   }} | ||||||
|  |                 > | ||||||
|  |                   {s} | ||||||
|  |                 </div> | ||||||
|  |               ); | ||||||
|  |             })} | ||||||
|  |           </div> | ||||||
|  |         )} | ||||||
|  |  | ||||||
|         <div className={styles["chat-input-panel-inner"]}> |         <div className={styles["chat-input-panel-inner"]}> | ||||||
|           <textarea |           <textarea | ||||||
|             ref={inputRef} |             ref={inputRef} | ||||||
|   | |||||||
| @@ -28,6 +28,7 @@ import { useAppConfig } from "../store/config"; | |||||||
| import { AuthPage } from "./auth"; | import { AuthPage } from "./auth"; | ||||||
| import { getClientConfig } from "../config/client"; | import { getClientConfig } from "../config/client"; | ||||||
| import { api } from "../client/api"; | import { api } from "../client/api"; | ||||||
|  | import { useChatStore } from "../store"; | ||||||
|  |  | ||||||
| export function Loading(props: { noLogo?: boolean }) { | export function Loading(props: { noLogo?: boolean }) { | ||||||
|   return ( |   return ( | ||||||
| @@ -114,6 +115,7 @@ function Screen() { | |||||||
|   const isHome = location.pathname === Path.Home; |   const isHome = location.pathname === Path.Home; | ||||||
|   const isAuth = location.pathname === Path.Auth; |   const isAuth = location.pathname === Path.Auth; | ||||||
|   const isMobileScreen = useMobileScreen(); |   const isMobileScreen = useMobileScreen(); | ||||||
|  |   const chat = useChatStore(); | ||||||
|  |  | ||||||
|   useEffect(() => { |   useEffect(() => { | ||||||
|     loadAsyncGoogleFont(); |     loadAsyncGoogleFont(); | ||||||
|   | |||||||
| @@ -103,6 +103,7 @@ interface ChatStore { | |||||||
|   resetSession: () => void; |   resetSession: () => void; | ||||||
|   getMessagesWithMemory: () => ChatMessage[]; |   getMessagesWithMemory: () => ChatMessage[]; | ||||||
|   getMemoryPrompt: () => ChatMessage; |   getMemoryPrompt: () => ChatMessage; | ||||||
|  |   getSuggestions: () => Promise<string[]>; | ||||||
|  |  | ||||||
|   clearAllData: () => void; |   clearAllData: () => void; | ||||||
| } | } | ||||||
| @@ -278,7 +279,8 @@ export const useChatStore = create<ChatStore>()( | |||||||
|         get().summarizeSession(); |         get().summarizeSession(); | ||||||
|       }, |       }, | ||||||
|  |  | ||||||
|       async onUserInput(content) { |       onUserInput(content) { | ||||||
|  |         return new Promise((resolve) => { | ||||||
|           const session = get().currentSession(); |           const session = get().currentSession(); | ||||||
|           const modelConfig = session.mask.modelConfig; |           const modelConfig = session.mask.modelConfig; | ||||||
|  |  | ||||||
| @@ -333,6 +335,7 @@ export const useChatStore = create<ChatStore>()( | |||||||
|               if (message) { |               if (message) { | ||||||
|                 botMessage.content = message; |                 botMessage.content = message; | ||||||
|                 get().onNewMessage(botMessage); |                 get().onNewMessage(botMessage); | ||||||
|  |                 resolve(); | ||||||
|               } |               } | ||||||
|               ChatControllerPool.remove( |               ChatControllerPool.remove( | ||||||
|                 sessionIndex, |                 sessionIndex, | ||||||
| @@ -369,6 +372,7 @@ export const useChatStore = create<ChatStore>()( | |||||||
|               ); |               ); | ||||||
|             }, |             }, | ||||||
|           }); |           }); | ||||||
|  |         }); | ||||||
|       }, |       }, | ||||||
|  |  | ||||||
|       getMemoryPrompt() { |       getMemoryPrompt() { | ||||||
| @@ -594,6 +598,62 @@ export const useChatStore = create<ChatStore>()( | |||||||
|         localStorage.clear(); |         localStorage.clear(); | ||||||
|         location.reload(); |         location.reload(); | ||||||
|       }, |       }, | ||||||
|  |  | ||||||
|  |       getSuggestions() { | ||||||
|  |         return new Promise((resolve) => { | ||||||
|  |           // get last bot messages | ||||||
|  |           const messages = get().currentSession().messages; | ||||||
|  |           let lastBotMessage: ChatMessage | undefined = undefined; | ||||||
|  |  | ||||||
|  |           for (let i = messages.length - 1; i >= 0; i -= 1) { | ||||||
|  |             if (messages[i].role === "assistant") { | ||||||
|  |               lastBotMessage = messages[i]; | ||||||
|  |               break; | ||||||
|  |             } | ||||||
|  |           } | ||||||
|  |  | ||||||
|  |           const botMsg = lastBotMessage?.content; | ||||||
|  |  | ||||||
|  |           if (!lastBotMessage || !botMsg) return resolve([]); | ||||||
|  |  | ||||||
|  |           const prompt = ` | ||||||
|  | here is bot's reponse: | ||||||
|  | ''' | ||||||
|  | ${botMsg} | ||||||
|  | ''' | ||||||
|  |  | ||||||
|  | according to bot's reponse, | ||||||
|  | - according to the bot's message, generate three short user input suggestions | ||||||
|  | - detect the bot's language and response in detected language  | ||||||
|  | - no other words, just response in pure json format: | ||||||
|  | {questions: string[]}"; | ||||||
|  | `; | ||||||
|  |  | ||||||
|  |           api.llm.chat({ | ||||||
|  |             messages: [ | ||||||
|  |               { | ||||||
|  |                 role: "user", | ||||||
|  |                 content: prompt, | ||||||
|  |               }, | ||||||
|  |             ], | ||||||
|  |             config: { | ||||||
|  |               model: "gpt-3.5-turbo", | ||||||
|  |             }, | ||||||
|  |             onFinish(msg) { | ||||||
|  |               try { | ||||||
|  |                 const msgJson = JSON.parse(msg) as { | ||||||
|  |                   questions: string[]; | ||||||
|  |                 }; | ||||||
|  |                 if (Array.isArray(msgJson.questions)) { | ||||||
|  |                   resolve(msgJson.questions); | ||||||
|  |                 } | ||||||
|  |               } catch { | ||||||
|  |                 console.error("[Suggestions] failed to parse: ", msg); | ||||||
|  |               } | ||||||
|  |             }, | ||||||
|  |           }); | ||||||
|  |         }); | ||||||
|  |       }, | ||||||
|     }), |     }), | ||||||
|     { |     { | ||||||
|       name: StoreKey.Chat, |       name: StoreKey.Chat, | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user