File size: 8,640 Bytes
d52c9ce b3bb424 d52c9ce 5a8ed59 d52c9ce 78050e9 5a8ed59 ca84c57 066fef8 5a8ed59 d52c9ce 78050e9 a4a2a07 78050e9 fb16688 d52c9ce 5a8ed59 78050e9 5a8ed59 c432b97 fb16688 c432b97 fb16688 78050e9 5a8ed59 4363711 3969302 c432b97 ac041d3 c432b97 d52c9ce 5a8ed59 2d2bfa2 78050e9 5a8ed59 78050e9 5a8ed59 78050e9 5a8ed59 d52c9ce 78050e9 5a8ed59 d52c9ce be1f678 c432b97 2d2bfa2 5a8ed59 d52c9ce 78050e9 d52c9ce 440f4cc 78050e9 440f4cc d52c9ce 440f4cc d52c9ce 440f4cc d52c9ce 440f4cc d52c9ce 440f4cc b3bb424 4363711 78050e9 f23fbcc 2c07b09 e334bb1 78050e9 e334bb1 78050e9 f23fbcc 4363711 f23fbcc c3b08ec f23fbcc c3b08ec 440f4cc f23fbcc e334bb1 2c07b09 440f4cc f23fbcc 2c07b09 f23fbcc 2c07b09 440f4cc f23fbcc 2c07b09 440f4cc 4b47cff 125d9fe 4b47cff f23fbcc 4b47cff 6d7ea2e 125d9fe c3b08ec e334bb1 125d9fe e334bb1 c3b08ec e334bb1 125d9fe 78050e9 4363711 78050e9 4363711 440f4cc 2c07b09 ed6f8c1 2c07b09 440f4cc ed6f8c1 b3bb424 4363711 440f4cc 4363711 440f4cc 78050e9 066fef8 |
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 |
import os
import gradio as gr
from anthropic import Anthropic
from pypdf import PdfReader
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.metrics.pairwise import cosine_similarity
# Set up Anthropic API key in HF secrets
ANTHROPIC_API_KEY = os.getenv('ANTHROPIC_API_KEY')
os.environ["ANTHROPIC_API_KEY"] = ANTHROPIC_API_KEY
# Set up username and password in HF secrets
username = os.getenv('username')
password = os.getenv('password')
# Function to chunk the document
def chunk_text(text, chunk_size=1000, overlap=100):
chunks = []
start = 0
while start < len(text):
end = start + chunk_size
chunk = text[start:end]
chunks.append(chunk)
start = end - overlap
return chunks
# Function to find the most relevant chunks
def get_relevant_chunks(query, chunks, top_n=3):
vectorizer = TfidfVectorizer()
tfidf_matrix = vectorizer.fit_transform(chunks + [query])
cosine_similarities = cosine_similarity(tfidf_matrix[-1], tfidf_matrix[:-1]).flatten()
relevant_indices = cosine_similarities.argsort()[-top_n:][::-1]
return [chunks[i] for i in relevant_indices]
# Function to process multiple PDFs
def process_pdfs(pdf_files):
all_chunks = []
for pdf_file in pdf_files:
reader = PdfReader(pdf_file)
full_text = ''.join(page.extract_text() for page in reader.pages)
chunks = chunk_text(full_text)
all_chunks.extend(chunks)
return all_chunks
# Add the paths to your desired knowledge base PDFs
reference_documents = ["knowledge_base.pdf"]
text_chunks = process_pdfs(reference_documents)
instructions = os.getenv('INSTRUCTIONS')
def chat_with_assistant(message, history):
# Find relevant chunks based on the user message
relevant_chunks = get_relevant_chunks(message, text_chunks)
context = "\n".join(relevant_chunks)
# Prepare the system message
system_message = f"""
#Role
-You are an impersonator and an educator.
-Your role is to adopt the personality, style, psychology, ideas, background, and circumstances of a historical figure.
-Your goal is to help students understand the historical figure better through and engaging conversation.
#Information
Your assigned historical figure is stated in your instructions:
{instructions}
Use the following as context for your answers.
{context}
However, use it seamlessly as background knowledge for a lively discussion and combine it with your own information. Do not provide citations or adopt a Q&A or academic tone.
#Important
-Always speak in the first person ("I") as the historical figure you are to incarnate.
-Always use appropriate language.
-Refuse to answer inappropriate questions or questions unrelated to your role and historical figure.
#Critical
-Important: Your knowledge of the world ends at the time of the death of your historical figure.
-Keep your responses concise and to the point. Avoid repetitions and always end on a period "." token
"""
# Prepare the message array
messages = []
# Add conversation history
for human_msg, ai_msg in history:
messages.append({"role": "user", "content": human_msg})
messages.append({"role": "assistant", "content": ai_msg})
# Add the current user message
messages.append({"role": "user", "content": message})
# Create Anthropic client
client = Anthropic(api_key=os.environ["ANTHROPIC_API_KEY"])
# Make the API call
response = client.messages.create(
model="claude-3-5-sonnet-20240620",
max_tokens=300,
system=system_message,
messages=messages
)
return response.content[0].text.strip()
# CSS for a blue-themed style
isp_theme = gr.themes.Default().set(
body_background_fill="#E6F3FF", # Light blue background
block_background_fill="#FFFFFF", # White for input blocks
block_title_text_color="#003366", # Dark blue for text
block_label_background_fill="#B8D8FF", # Light blue for labels
input_background_fill="#FFFFFF", # White for input fields
button_primary_background_fill="#0066CC", # Medium blue for primary buttons
button_primary_background_fill_hover="#0052A3", # Darker blue for hover
button_primary_text_color="#FFFFFF", # White text on buttons
button_secondary_background_fill="#B8D8FF", # Light blue for secondary buttons
button_secondary_background_fill_hover="#99C2FF", # Slightly darker blue for hover
button_secondary_text_color="#003366", # Dark blue text for secondary buttons
block_border_width="1px",
block_border_color="#0066CC", # Medium blue border
)
# Custom CSS for logo positioning and disclaimer footer
custom_css = """
#logo-img {
display: block;
margin: 0 auto;
width: 150px;
height: auto;
padding-bottom: 20px; /* Space below logo */
}
#disclaimer-footer {
width: 100%;
background-color: #B8D8FF;
color: #003366;
text-align: center;
padding: 10px 0;
font-size: 14px;
border-top: 1px solid #0066CC;
margin-top: 20px;
}
.container {
max-width: 1200px;
margin: 0 auto;
padding: 10px;
}
.title {
color: #003366;
margin-bottom: 10px;
text-align: center; /* Center the title */
}
.chatbot {
border: none;
border-radius: 5px;
padding: 10px;
margin-bottom: 15px;
}
.button-row {
display: flex;
gap: 10px;
justify-content: center; /* Center the buttons */
margin-bottom: 15px;
}
.chatbot .message,
.chatbot .message::before,
.chatbot .message::after {
border: none !important;
box-shadow: none !important;
}
.chatbot .message > div {
border: none !important;
box-shadow: none !important;
}
.chatbot .message-content {
padding: 2px 2px; /* Reduced padding to make text bubbles smaller */
margin-bottom: 5px; /* Space between messages */
max-width: 60%; /* Restrict width to make it more compact */
word-wrap: break-word; /* Ensure text wraps properly */
display: inline-block; /* Align content properly */
}
.chatbot .message-bubble {
background-color: #FFFFFF; /* Ensure background is white */
border-radius: 2px; /* Smaller rounded corners */
box-sizing: border-box; /* Ensure padding is included in width */
display: inline-block; /* Align the bubble content properly */
margin: 2px 0; /* Reduce margin to minimize bubble size */
}
"""
# Environment variables
assistant_avatar = os.getenv('AVATAR')
assistant_title = os.getenv('TITLE')
assistant_logo = os.getenv('LOGO')
# Gradio interface using Blocks
with gr.Blocks(theme=isp_theme, css=custom_css) as iface:
with gr.Column(elem_classes="container"):
# Logo and Title
gr.HTML(
f"""
<img id='logo-img' src='{assistant_logo}' alt='Assistant Logo' onerror="this.style.display='none';document.getElementById('logo-error').style.display='block';">
<div id='logo-error' style='display:none;'>Logo not found</div>
""",
elem_id='logo-container'
)
gr.Markdown(f"# {assistant_title}", elem_classes="title")
# Chatbot and message input
with gr.Row():
chatbot = gr.Chatbot(
height=500,
avatar_images=(None, assistant_avatar),
elem_classes="chatbot"
)
msg = gr.Textbox(
placeholder="Type your message here...",
container=False,
scale=7
)
with gr.Row(elem_classes="button-row"):
submit = gr.Button("Submit", variant="primary")
clear = gr.ClearButton([msg, chatbot], value="Clear", variant="secondary")
undo = gr.Button("Delete Previous", variant="secondary")
gr.HTML(
"<div id='disclaimer-footer'>You are chatting with an AI assistant. Make sure to evaluate the accuracy of its answers.</div>"
)
def user(user_message, history):
return "", history + [[user_message, None]]
def bot(history):
bot_message = chat_with_assistant(history[-1][0], history[:-1])
history[-1][1] = bot_message
return history
def delete_previous(history):
if len(history) > 0:
return history[:-1]
return history
msg.submit(user, [msg, chatbot], [msg, chatbot], queue=False).then(
bot, chatbot, chatbot
)
submit.click(user, [msg, chatbot], [msg, chatbot], queue=False).then(
bot, chatbot, chatbot
)
undo.click(delete_previous, chatbot, chatbot)
iface.launch(auth=(username, password)) |