mirror of
				https://github.com/ItzCrazyKns/Perplexica.git
				synced 2025-11-03 20:28:14 +00:00 
			
		
		
		
	feat(app): add suggestion generation
This commit is contained in:
		@@ -9,7 +9,7 @@ class LineListOutputParser extends BaseOutputParser<string[]> {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  constructor(args?: LineListOutputParserArgs) {
 | 
					  constructor(args?: LineListOutputParserArgs) {
 | 
				
			||||||
    super();
 | 
					    super();
 | 
				
			||||||
    this.key = args.key || this.key;
 | 
					    this.key = args.key ?? this.key;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  static lc_name() {
 | 
					  static lc_name() {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -63,6 +63,7 @@ const Chat = ({
 | 
				
			|||||||
              dividerRef={isLast ? dividerRef : undefined}
 | 
					              dividerRef={isLast ? dividerRef : undefined}
 | 
				
			||||||
              isLast={isLast}
 | 
					              isLast={isLast}
 | 
				
			||||||
              rewrite={rewrite}
 | 
					              rewrite={rewrite}
 | 
				
			||||||
 | 
					              sendMessage={sendMessage}
 | 
				
			||||||
            />
 | 
					            />
 | 
				
			||||||
            {!isLast && msg.role === 'assistant' && (
 | 
					            {!isLast && msg.role === 'assistant' && (
 | 
				
			||||||
              <div className="h-px w-full bg-[#1C1C1C]" />
 | 
					              <div className="h-px w-full bg-[#1C1C1C]" />
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,18 +1,20 @@
 | 
				
			|||||||
'use client';
 | 
					'use client';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { useEffect, useState } from 'react';
 | 
					import { useEffect, useRef, useState } from 'react';
 | 
				
			||||||
import { Document } from '@langchain/core/documents';
 | 
					import { Document } from '@langchain/core/documents';
 | 
				
			||||||
import Navbar from './Navbar';
 | 
					import Navbar from './Navbar';
 | 
				
			||||||
import Chat from './Chat';
 | 
					import Chat from './Chat';
 | 
				
			||||||
import EmptyChat from './EmptyChat';
 | 
					import EmptyChat from './EmptyChat';
 | 
				
			||||||
import { toast } from 'sonner';
 | 
					import { toast } from 'sonner';
 | 
				
			||||||
import { useSearchParams } from 'next/navigation';
 | 
					import { useSearchParams } from 'next/navigation';
 | 
				
			||||||
 | 
					import { getSuggestions } from '@/lib/actions';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export type Message = {
 | 
					export type Message = {
 | 
				
			||||||
  id: string;
 | 
					  id: string;
 | 
				
			||||||
  createdAt: Date;
 | 
					  createdAt: Date;
 | 
				
			||||||
  content: string;
 | 
					  content: string;
 | 
				
			||||||
  role: 'user' | 'assistant';
 | 
					  role: 'user' | 'assistant';
 | 
				
			||||||
 | 
					  suggestions?: string[];
 | 
				
			||||||
  sources?: Document[];
 | 
					  sources?: Document[];
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -145,10 +147,15 @@ const ChatWindow = () => {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  const [chatHistory, setChatHistory] = useState<[string, string][]>([]);
 | 
					  const [chatHistory, setChatHistory] = useState<[string, string][]>([]);
 | 
				
			||||||
  const [messages, setMessages] = useState<Message[]>([]);
 | 
					  const [messages, setMessages] = useState<Message[]>([]);
 | 
				
			||||||
 | 
					  const messagesRef = useRef<Message[]>([]);
 | 
				
			||||||
  const [loading, setLoading] = useState(false);
 | 
					  const [loading, setLoading] = useState(false);
 | 
				
			||||||
  const [messageAppeared, setMessageAppeared] = useState(false);
 | 
					  const [messageAppeared, setMessageAppeared] = useState(false);
 | 
				
			||||||
  const [focusMode, setFocusMode] = useState('webSearch');
 | 
					  const [focusMode, setFocusMode] = useState('webSearch');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  useEffect(() => {
 | 
				
			||||||
 | 
					    messagesRef.current = messages;
 | 
				
			||||||
 | 
					  }, [messages]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const sendMessage = async (message: string) => {
 | 
					  const sendMessage = async (message: string) => {
 | 
				
			||||||
    if (loading) return;
 | 
					    if (loading) return;
 | 
				
			||||||
    setLoading(true);
 | 
					    setLoading(true);
 | 
				
			||||||
@@ -177,7 +184,7 @@ const ChatWindow = () => {
 | 
				
			|||||||
      },
 | 
					      },
 | 
				
			||||||
    ]);
 | 
					    ]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const messageHandler = (e: MessageEvent) => {
 | 
					    const messageHandler = async (e: MessageEvent) => {
 | 
				
			||||||
      const data = JSON.parse(e.data);
 | 
					      const data = JSON.parse(e.data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      if (data.type === 'error') {
 | 
					      if (data.type === 'error') {
 | 
				
			||||||
@@ -239,8 +246,28 @@ const ChatWindow = () => {
 | 
				
			|||||||
          ['human', message],
 | 
					          ['human', message],
 | 
				
			||||||
          ['assistant', recievedMessage],
 | 
					          ['assistant', recievedMessage],
 | 
				
			||||||
        ]);
 | 
					        ]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        ws?.removeEventListener('message', messageHandler);
 | 
					        ws?.removeEventListener('message', messageHandler);
 | 
				
			||||||
        setLoading(false);
 | 
					        setLoading(false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const lastMsg = messagesRef.current[messagesRef.current.length - 1];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (
 | 
				
			||||||
 | 
					          lastMsg.role === 'assistant' &&
 | 
				
			||||||
 | 
					          lastMsg.sources &&
 | 
				
			||||||
 | 
					          lastMsg.sources.length > 0 &&
 | 
				
			||||||
 | 
					          !lastMsg.suggestions
 | 
				
			||||||
 | 
					        ) {
 | 
				
			||||||
 | 
					          const suggestions = await getSuggestions(messagesRef.current);
 | 
				
			||||||
 | 
					          setMessages((prev) =>
 | 
				
			||||||
 | 
					            prev.map((msg) => {
 | 
				
			||||||
 | 
					              if (msg.id === lastMsg.id) {
 | 
				
			||||||
 | 
					                return { ...msg, suggestions: suggestions };
 | 
				
			||||||
 | 
					              }
 | 
				
			||||||
 | 
					              return msg;
 | 
				
			||||||
 | 
					            }),
 | 
				
			||||||
 | 
					          );
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										22
									
								
								ui/lib/actions.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								ui/lib/actions.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,22 @@
 | 
				
			|||||||
 | 
					import { Message } from '@/components/ChatWindow';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const getSuggestions = async (chatHisory: Message[]) => {
 | 
				
			||||||
 | 
					  const chatModel = localStorage.getItem('chatModel');
 | 
				
			||||||
 | 
					  const chatModelProvider = localStorage.getItem('chatModelProvider');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const res = await fetch(`${process.env.NEXT_PUBLIC_API_URL}/suggestions`, {
 | 
				
			||||||
 | 
					    method: 'POST',
 | 
				
			||||||
 | 
					    headers: {
 | 
				
			||||||
 | 
					      'Content-Type': 'application/json',
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    body: JSON.stringify({
 | 
				
			||||||
 | 
					      chat_history: chatHisory,
 | 
				
			||||||
 | 
					      chat_model: chatModel,
 | 
				
			||||||
 | 
					      chat_model_provider: chatModelProvider,
 | 
				
			||||||
 | 
					    }),
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const data = (await res.json()) as { suggestions: string[] };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return data.suggestions;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
		Reference in New Issue
	
	Block a user