File size: 14,211 Bytes
ccbdf6f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
import openai
from openai import OpenAI
from scraper import *
from dotenv import load_dotenv
import  streamlit as st
import math
USE_CLI = False
USE_HISTORY_LEN = 20

load_dotenv()


openai.api_key = os.getenv("OAI_KEY")
brave_key = os.getenv("BRAVE_KEY")
client = OpenAI()


chat_hist = []

def display_imgs(urls):
    grid = st.columns(3)
    col = 0    
    ctr = 0
    for url in urls[:min(len(urls), 9)]:
        ctr += 1
        with grid[col]:
            st.image(url)
        col = ctr % 3


def update_query(raw_query, context):
    context_str ="\n".join(context) 
    updated_query = f"""
                {raw_query}
                
                Context: {context_str}
                """
                
    return updated_query

def openAI_api_call(mode, query, raw_query = None):
    print("="*50)
    print(f"Using mode {mode}")
    print("="*50)
    if mode == "router":
        curr_msgs = [
            {"role": "system", "content": """You are a helpful assistant with access to the chat history, user query and following tools and their descriptions:

                                        TOOL NAME: get_relevant_context
                                        TOOL_DESCRIPTION: Given user query, present relevant text information about the query.

                                        TOOL NAME: get_relevant_images
                                        TOOL_DESCRIPTION: Given user query, present relevant image URLs about the query.

                                        The use of tools is optional. If based on user query and chat history, you feel that no tools are required, answer saying no_tools. Otherwise,
                                        mention the tool name(s). Note, including relevant images whenever possible is highly encouraged to enhance user experience. The answer has to be one or more from [get_relevant_context, get_relevant_images, no_tools]. Think through this step by step and come up with the answer.
                                        
                                        Here are some examples:
                                         
                                        User: What is the name of a Tom Cruise Movie?
                                        Assistant: get_relevant_context 
                                        
                                        User: Suggest some books by Enid Blyton
                                        Assistant: get_relevant_context, get_relevant_images
                                        
                                        User: Suggest some movies by Steven Speilberg
                                        Assistant: get_relevant_context, get_relevant_images

                                        User: Suggest a comedy movie
                                        Assistant: get_relevant_context, get_relevant_images
                                        
                                        User: Suggest a book for a seven year old
                                        Assistant: get_relevant_context, get_relevant_images
                                        
                                        User: Can you show me a poster of the movie Space Jam?
                                        Assistant: get_relevant_images
                                        
                                        User: Tell me a joke
                                        Assistant: no_tools
                                        
                                        User: Who are you?
                                        Assistant: no_tools
                                        
                                        User: Can you give me a summary of the third one?
                                        Assistant: get_relevant_context
                                        
                                        User: Can you give me a photo of this person?
                                        Assistant: get_relevant_images                                                                                   
                                        """},
        ]
    
    elif mode == "images":
        curr_msgs = [
            {"role": "system", "content": """
                                        "Given a user query and chat history, use the chat history and user query to give key words such as title, names, etc. Consider incorporating terms, phrases, or topics discussed in the chat history that may provide additional context or refine the search. Ensure the query return keywords separated by commas. Avoid ambiguity or overly broad queries that may result in irrelevant images. If no relevant chat history is available, focus on refining the query based on the user's input alone. Think through this step by step and come up with the answer."
                                        Example:
                                            Chat History:
                                                User: Suggest a book for a 5 year old
                                                Assistant: A recommended book for a 5-year-old is "Where the Wild Things Are" by Maurice Sendak
                                            
                                            User: Can you give a picture of the author?
                                            Assistant: Maurice Sendak
                                        
                                        Example:
                                            Chat History:
                                                User: Suggest a book for a 5 year old
                                                Assistant: I recommend the book "The Very Hungry Caterpillar" by Eric Carle for a 5-year-old
                                            
                                            User: Can you give a picture of the book?
                                            Assistant: The Very Hungry Caterpillar                                            
                                        """},
                    ]
        
    elif mode == "text":

        curr_msgs = [{"role": "system", "content": """You are a knowledgeable assistant with access to user queries and chat history. Your task is to revise user queries using the user query and chat history for web search to retrieve relevant information.  Below are examples of user queries and optimized responses:

            Example 1:
            User: "I'm in the mood for a thriller novel. Any recommendations?"
            Assistant: "Best thriller novels of all time"

            Example 2:
            User: "Who directed the movie Inception?"
            Assistant: "Director of Inception"

            Example 3:
            User: "Can you tell me about the cast of The Godfather?"
            Assistant: "Cast of The Godfather"

            Example 4:
            User: "What genre does The Great Gatsby belong to?"
            Assistant: "Genre of The Great Gatsby"

            Example 5:
            User: "Suggest a book for a 5 year old"
            Assistant: "Recommended book for a 5 year old"
            
            Please provide brief and concise responses by revising the user queries accordingly. Think through this step by step and come up with the answer."
            """
        }]
    
    elif mode == "direct":
        curr_msgs = [{"role": "system", "content": """Your task is to provide a random fun fact about children's books or movies. Be concise with the response.
            """
        }]
        curr_msgs.append({"role": "user", "content": query})
        response = client.chat.completions.create(
        model="gpt-3.5-turbo-0125",
        # response_format={ "type": "json_object" },
        messages=curr_msgs
        )
        
        return response.choices[0].message.content                    
    
    else:
        curr_msgs = [{"role": "system", "content":"""You are a knowledgeable chat assistant specialized in answering questions related to books, movies, and related topics such as authors, genres, target age groups, summaries, titles, cast, directors, producers, and plot genres. Your responses should be based on the provided chat history and/or context.
                        Your task is to provide accurate and relevant information to users' queries within the scope of books and movies.Remember to provide accurate and contextually relevant responses based on the user's queries and the information available from previous interactions. Think through this step by step and come up with the answer."""
                    }
                    ]
        
    n = 5
    
    for msg in st.session_state.messages[-min(len(st.session_state.messages), USE_HISTORY_LEN):-1]:
        curr_msgs.append(msg)    
    curr_msgs.append({"role": "user", "content": query})
    print("~"*50)
    print(curr_msgs)
    print("~"*50)
    response = client.chat.completions.create(
    model="gpt-3.5-turbo-0125",
    # response_format={ "type": "json_object" },
    messages=curr_msgs
    )
    
    return response.choices[0].message.content



def make_router_call(query: str):
    
    router_answer = openAI_api_call("router", query)
    print("="*50)
    print(f"Router answer is:  {router_answer}")
    print("="*50)
    
    return router_answer

def make_context_call(query: str, is_chat=True):
    print("="*50)
    print(f"get_relevant_context")
    print("="*50)

    opt_query = openAI_api_call("text", query)
    print("="*50)
    print(f"opt_query {opt_query}")
    print("="*50)

    context = fetch_context(opt_query)
    print("="*50)
    print(f"context {context}")
    print("="*50)
    updated_query = update_query(opt_query, context)
    print("="*50)
    print(f"updated_query {updated_query}")
    print("="*50)
    answer = openAI_api_call("",updated_query)

    if is_chat:
        chat_hist.append({"role": "user", "content": query})
        chat_hist.append({"role": "assistant", "content": answer})
    print("@"*50)
    print(f"Answer: {answer}")
    print("@"*50)
    skip = True


    return answer


def make_img_search_call(query, answer):
    print("="*50)
    print(f"get_relevant_images")
    print("="*50)
    if answer:
        opt_query = openAI_api_call("images", query + ", " + answer)
    else:
        opt_query = openAI_api_call("images", query)
    st.session_state.messages.append({"role": "assistant", "content": ""})
    
    print("="*50)
    print(f"opt_query: {opt_query}")
    print("="*50)    
    images_urls = fetch_images(opt_query)
    print("@"*50)
    print(f"Found images: {images_urls}")
    print("@"*50)
    skip = True
    
    return images_urls

def make_default_call(query):    
    print("="*50)
    print(f"Answering from past")
    print("="*50)
    opt_query = openAI_api_call("text", query)
    print("="*50)
    print(f"opt_query: {opt_query}")
    print("="*50)
    answer = openAI_api_call("",opt_query)
    chat_hist.append({"role": "user", "content": query})
    chat_hist.append({"role": "assistant", "content": answer})
    print("@"*50)
    print(f"Answer: {answer}")
    print("@"*50)

    return answer

if USE_CLI:
    while True:
        
        query = input("prompt: ")
        router_answer = make_router_call(query)
        skip = False
        answer = None
        
        if "get_relevant_context" in router_answer:
            answer = make_context_call(query)
            skip = True
        
        if "get_relevant_images" in router_answer: 
            images_urls = make_img_search_call(query, answer)
            skip = True
        
        if (not skip):
            answer = make_default_call(query)
        
        print("!"*50)
        print("ONE TURN FINISHED")
        print("!"*50)
        
else:
    if "facts" not in st.session_state:
        st.session_state.facts = [openAI_api_call("direct", "Give one random fun fact about a childrens book or movie")]
    st.set_page_config(page_title="Project BookWorm: Your own Librarian!", layout="centered", initial_sidebar_state="auto", menu_items=None)
    st.title("Project BookWorm: Your own Librarian!")
    st.markdown(f"""> ###### _{st.session_state.facts[0]}_""")
    st.info("Use this app to get recommendations for books and movies")

    # Initialize chat history
    if "messages" not in st.session_state:
        st.session_state.messages = []
    # Display chat messages from history on app rerun
    for message in st.session_state.messages:
        with st.chat_message(message["role"]):
            st.markdown(message["content"])










    # Accept user input
    if query := st.chat_input("What would you like to know today?"):
        # Add user message to chat history
        
        # Display user message in chat message container
        with st.chat_message("user"):
            st.markdown(query)     

        router_answer = make_router_call(query)
        skip = False
        answer = None
        images_urls = None
        
        if "get_relevant_context" in router_answer:
            st.session_state.messages.append({"role": "user", "content": query})
            answer = make_context_call(query)
            skip = True
            st.session_state.messages.append({"role": "assistant", "content": answer})
        
        if "get_relevant_images" in router_answer: 
            st.session_state.messages.append({"role": "user", "content": query})
            images_urls = make_img_search_call(query, answer)
            skip = True
        
        if (not skip):
            st.session_state.messages.append({"role": "user", "content": query})
            answer = make_default_call(query)
            st.session_state.messages.append({"role": "assistant", "content": answer})
        
        print("!"*50)
        print("ONE TURN FINISHED")
        print("!"*50)
   

        # Display assistant response in chat message container
        with st.chat_message("assistant"):
            # response = st.write_stream(response_generator(answer))
            if answer: st.markdown(answer)
            if images_urls: display_imgs(images_urls)
            
        # Add assistant response to chat history