-
Notifications
You must be signed in to change notification settings - Fork 2
/
server.py
151 lines (125 loc) · 7.04 KB
/
server.py
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
import os
from flask import Flask, request, jsonify, Response
from dotenv import load_dotenv
from openai import OpenAI
import sys
sys.path.append('./')
from data_collection import data_manager
import ast
import logging
load_dotenv("keys.env")
app = Flask(__name__)
app.config['DEBUG'] = os.environ["DEBUG_FLASK"]
from flask_cors import CORS
CORS(app, origins=["http://localhost:3000", "https://drexelai.github.io"])
client = OpenAI(api_key=os.environ["OPENAI_API_KEY"])
def check_rag_with_openai_api(RAG, query):
check_prompt = f"Does the following context answer the query?\n\nContext: {RAG}\n\nQuery: {query}\n\nAnswer with 'yes' or 'no' in lowercase only please."
check_response = client.chat.completions.create(
model="gpt-4o-mini",
messages=[
{"role": "system", "content": "You are a helpful assistant that answers questions about Drexel University using the latest and most up to date information"},
{"role": "user", "content":check_prompt}
]
)
return check_response.choices[0].message.content
def parse_urls_from_rag(RAG):
return [metadata['URL'] for metadata in [ast.literal_eval(d) for d in RAG.split("\n")] if 'URL' in metadata]
# Improve the RAG by adding more information from the web if the initial RAG does not answer the query
def improve_rag(RAG, query):
check_answer = check_rag_with_openai_api(RAG, query)
if check_answer.lower() != 'yes':
urls = parse_urls_from_rag(RAG)
# RAG += data_manager.fetch_content_from_urls(urls)
search_results = data_manager.duckduckgo_search(query + " at Drexel University 2024")
# print(search_results)
for result in search_results:
# print("fetching info")
RAG += result["body"]
moreinfo = data_manager.fetch_content_from_urls(result["href"])
if result["href"] not in urls:
RAG += moreinfo + result["href"]
# print(result["href"])
# print(moreinfo)
if len(RAG) > 128000:
RAG = RAG[:128000]
return RAG
@app.route("/")
def test():
return "Server is running"
def reformat_chat_data(chat_data):
reformatted_data = []
if not chat_data:
return ""
for entry in chat_data:
speaker = "User" if entry['isUser'] else "Bot"
reformatted_data.append(f"{speaker}: {entry['text']}\n")
return "".join(reformatted_data)
@app.route("/query", methods=["POST"])
def query_llm():
try:
data = request.get_json()
query = data.get("query")
priorConversation = data.get("priorConversation")
reformatted_chat = reformat_chat_data(priorConversation)
if not query:
return jsonify({"detail": "Query is required"}), 400
RAG = data_manager.query_from_index(query)
RAG = improve_rag(RAG, query)
system_prompt = open(os.path.join("prompts", "system.txt"), 'r').read()
instructions = open(os.path.join("prompts", "instructions.txt"), 'r').read()
output_format = "\nPlease answer only in a couple sentences and render the entire response in markdown but organize the code using level 2 headings and paragraphs. Feel free to use lists and other markdown features"
user_prompt = f'Use any information from the current conversation history where needed:\n{reformatted_chat}\n\n{RAG}\n\n {instructions} \n\n{query} + {output_format}'
def generate():
full_content = ""
stream = client.chat.completions.create(
model="gpt-4o-mini",
messages=[
{"role": "system", "content": system_prompt},
{"role": "user", "content": user_prompt}
],
stream=True
)
for chunk in stream:
if chunk.choices[0].delta.content is not None:
content = chunk.choices[0].delta.content
if content : #Error handling for missing data
full_content += content
#print(content) # Print the content for debugging purposes
yield content
# print(f"Response to question \"{query}\" has been generated")
return Response(generate(), content_type="text/plain-text")
except Exception as e:
print(e)
return jsonify({"answer": str(e)}), 500
@app.route("/summarize-convo", methods=["POST"])
def summarize_convo():
firstMessage = request.get_json()["message"]
chatrename = client.chat.completions.create(
model="gpt-4o-mini",
messages=[
{"role": "system", "content": "You are a message summarizer who summarizes a given message into 2-3 words"},
{"role": "user", "content": firstMessage + "\n\nSummarize this message into 2-3 words and just return the message"}
]
).choices[0].message.content
return {"messageSummary": chatrename}
@app.route("/blackboard", methods=["POST"])
def query_blackboard():
response2 = "Your assignments this week: ENTP 205 Ready, Set, Fail: Discussion board post on business idea due Friday 11:59PM. ENTP 325 Early Stage Venture Funding: Cap table assignment due Wednesday 11:59PM. MATH 121: Problem Set 4 pages 79-81 textbook due Thursday before class. Suggested Time Budgeting Plan: Monday (Today) – Focus: Start and finish Cap Table Assignment for ENTP 325. Time Required: 2-3 hours (including research and calculations). Goal: Complete most, if not all, of this assignment since it’s due soonest. Tuesday – Focus: Finish up the Cap Table Assignment if any parts remain. Time Required: 1 hour (if needed for final touch-ups). Begin: MATH 121 Problem Set 4 to avoid rushing before class on Thursday. Time Required: 1-2 hours. Goal: Get at least halfway through the problem set. Wednesday – Focus: Complete the remaining part of MATH 121 Problem Set 4. Time Required: 1-2 hours. Goal: Finish the problem set and review answers if time allows. Thursday – Focus: Write the Discussion Board Post for ENTP 205. Time Required: 1-2 hours for writing and revising. Goal: Complete the post in time for submission on Friday. This plan ensures you’re prioritizing based on due dates and spreading out your workload for a balanced approach."
def generateblackboard():
stream = client.chat.completions.create(
model="gpt-4o-mini",
messages=[
{"role": "system", "content": "you will repeat back to me what I say"},
{"role": "user", "content": response2 + "\n\n\norganize this more nicely"}
],
stream=True
)
for chunk in stream:
if chunk.choices[0].delta.content is not None:
content = chunk.choices[0].delta.content
#print(content) # Print the content for debugging purposes
yield content
return Response(generateblackboard(), content_type="text/plain-text")
if __name__ == "__main__":
app.run(debug=os.getenv("DEBUG_FLASK", True), host="0.0.0.0", port=int(os.environ.get("PORT", 8080)))