Spaces:
Sleeping
Sleeping
File size: 7,628 Bytes
a3e0475 ffbccbb fc5f1c7 e653ea8 d6f5773 fc5f1c7 a3e0475 5c095c6 1755fdf e653ea8 1755fdf fe8e64b 546ff54 ab8074b e653ea8 546ff54 ab8074b e653ea8 546ff54 ab8074b e653ea8 b256ef1 5c095c6 1755fdf 5c095c6 594a593 e653ea8 391ca85 1755fdf 304d58b 5c095c6 a3e0475 258dcf5 e653ea8 1755fdf a3e0475 e653ea8 1755fdf e653ea8 1755fdf e653ea8 1755fdf e653ea8 1755fdf e653ea8 1755fdf e653ea8 1755fdf 594a593 e653ea8 594a593 cb6f832 e653ea8 594a593 e653ea8 885b84d 594a593 cb6f832 1755fdf c567c97 e653ea8 594a593 e653ea8 1755fdf 74bfc30 1755fdf 74bfc30 1755fdf 74bfc30 1755fdf e653ea8 594a593 74bfc30 1755fdf d6afb7a 594a593 74bfc30 304d58b 74bfc30 594a593 f77e366 594a593 1755fdf e653ea8 594a593 74bfc30 594a593 1755fdf e653ea8 792148f fe8e64b 1755fdf 74bfc30 1755fdf 74bfc30 d6afb7a 594a593 e653ea8 594a593 304d58b 885b84d 304d58b 885b84d 15aede2 304d58b 885b84d 304d58b 885b84d 304d58b 885b84d 304d58b f8490df 1755fdf f8490df d6afb7a 47a03de 594a593 b54b055 d6afb7a e653ea8 1755fdf e653ea8 1755fdf e653ea8 |
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 |
import os
import re
import requests
import torch
import streamlit as st
from langchain_huggingface import HuggingFaceEndpoint
from langchain_core.prompts import PromptTemplate
from langchain_core.output_parsers import StrOutputParser
from transformers import pipeline
from langdetect import detect
# β
Check for GPU or Default to CPU
device = "cuda" if torch.cuda.is_available() else "cpu"
print(f"β
Using device: {device}")
# β
Environment Variables
HF_TOKEN = os.getenv("HF_TOKEN")
if HF_TOKEN is None:
raise ValueError("HF_TOKEN is not set. Please add it to your environment variables.")
NASA_API_KEY = os.getenv("NASA_API_KEY")
if NASA_API_KEY is None:
raise ValueError("NASA_API_KEY is not set. Please add it to your environment variables.")
# β
Set Up Streamlit
st.set_page_config(page_title="HAL - NASA ChatBot", page_icon="π")
# β
Ensure Session State Variables (Maintains Chat History)
if "chat_history" not in st.session_state:
st.session_state.chat_history = [{"role": "assistant", "content": "Hello! How can I assist you today?"}]
if "response_ready" not in st.session_state:
st.session_state.response_ready = False
if "follow_up" not in st.session_state:
st.session_state.follow_up = ""
# β
Initialize Hugging Face Model (CPU/GPU Compatible)
def get_llm_hf_inference(model_id="meta-llama/Llama-2-7b-chat-hf", max_new_tokens=800, temperature=0.3):
return HuggingFaceEndpoint(
repo_id=model_id,
max_new_tokens=max_new_tokens,
temperature=temperature,
token=HF_TOKEN,
task="text-generation",
device=-1 if device == "cpu" else 0
)
# β
NASA API Function
def get_nasa_apod():
url = f"https://api.nasa.gov/planetary/apod?api_key={NASA_API_KEY}"
response = requests.get(url)
if response.status_code == 200:
data = response.json()
return data.get("url", ""), data.get("title", ""), data.get("explanation", "")
return "", "NASA Data Unavailable", "I couldn't fetch data from NASA right now."
# β
Sentiment Analysis (Now Uses Explicit Device)
sentiment_analyzer = pipeline(
"sentiment-analysis",
model="distilbert/distilbert-base-uncased-finetuned-sst-2-english",
device=-1 if device == "cpu" else 0
)
def analyze_sentiment(user_text):
result = sentiment_analyzer(user_text)[0]
return result['label']
# β
Intent Detection
def predict_action(user_text):
if "NASA" in user_text.lower() or "space" in user_text.lower():
return "nasa_info"
return "general_query"
# β
Ensure English Responses (Fixed Detection Error)
def ensure_english(text):
"""Ensures the response is in English, preventing false language detection errors."""
try:
detected_lang = detect(text)
if detected_lang == "en":
return text # β
It's in English, return as-is
except:
pass # π₯ Ignore detection errors, assume English
return "β οΈ Sorry, I only respond in English. Can you rephrase your question?"
# β
Follow-Up Question Generation (Ensures Proper Formatting)
def generate_follow_up(user_text):
"""Generates a structured follow-up question in a concise format."""
prompt_text = (
f"Given the user's question: '{user_text}', generate a SHORT follow-up question in the format: "
"'Would you like to learn more about [related topic] or explore something else?'. "
"Ensure it's concise and structured exactly as requested without extra commentary."
)
hf = get_llm_hf_inference(max_new_tokens=30, temperature=0.3)
output = hf.invoke(input=prompt_text).strip()
# β
Extract relevant part, removing unwanted symbols
cleaned_output = re.sub(r"```|''|\"", "", output).strip()
if "Would you like to learn more about" not in cleaned_output:
cleaned_output = "Would you like to explore another related topic or ask about something else?"
return cleaned_output
# β
Main Response Function (Fixed History & Language Issues)
def get_response(system_message, user_text, max_new_tokens=800):
"""Generates a response and ensures conversation history is updated."""
chat_history = st.session_state.chat_history # β
Get Chat History
# β
Store User Input in Chat History BEFORE Generating Response
chat_history.append({'role': 'user', 'content': user_text})
# β
Detect Intent (NASA vs General AI chat)
action = predict_action(user_text)
if action == "nasa_info":
nasa_url, nasa_title, nasa_explanation = get_nasa_apod()
response = f"**{nasa_title}**\n\n{nasa_explanation}"
follow_up = generate_follow_up(user_text)
# β
Append to chat history
chat_history.append({'role': 'assistant', 'content': response})
chat_history.append({'role': 'assistant', 'content': follow_up})
st.session_state.chat_history = chat_history
return response, follow_up, nasa_url
# β
Format Conversation History for Model Input
formatted_chat_history = "\n".join(f"{msg['role']}: {msg['content']}" for msg in chat_history)
# β
Invoke Hugging Face Model
hf = get_llm_hf_inference(max_new_tokens=max_new_tokens, temperature=0.3)
prompt = PromptTemplate.from_template(
"[INST] You are a helpful AI assistant.\n\nCurrent Conversation:\n{chat_history}\n\n"
"User: {user_text}.\n [/INST]\n"
"AI: Provide a detailed explanation with depth. Use a conversational tone."
"π¨ Answer **only in English**."
"\nHAL:"
)
chat = prompt | hf.bind(skip_prompt=True) | StrOutputParser(output_key='content')
response = chat.invoke(input=dict(system_message=system_message, user_text=user_text, chat_history=formatted_chat_history))
response = response.split("HAL:")[-1].strip() if "HAL:" in response else response.strip()
# β
Prevent False Language Errors
response = ensure_english(response)
if not response:
response = "I'm sorry, but I couldn't generate a response. Can you rephrase your question?"
follow_up = generate_follow_up(user_text)
# β
Append Responses to Chat History
chat_history.append({'role': 'assistant', 'content': response})
chat_history.append({'role': 'assistant', 'content': follow_up})
st.session_state.chat_history = chat_history
return response, follow_up, None
# β
Streamlit UI
st.title("π HAL - NASA AI Assistant")
# β
Justify all chatbot responses
st.markdown("""
st.markdown("""
<style>
.user-msg, .assistant-msg {
padding: 11px;
border-radius: 10px;
margin-bottom: 5px;
width: fit-content;
max-width: 80%;
text-align: justify;
}
.user-msg { background-color: #696969; color: white; }
.assistant-msg { background-color: #333333; color: white; }
.container { display: flex; flex-direction: column; align-items: flex-start; }
@media (max-width: 600px) { .user-msg, .assistant-msg { font-size: 16px; max-width: 100%; } }
</style>
""", unsafe_allow_html=True)
""", unsafe_allow_html=True)
# β
Display Chat History
for message in st.session_state.chat_history:
st.markdown(f"**{message['role'].capitalize()}**: {message['content']}")
# β
Chat Input
user_input = st.chat_input("Type your message here...")
if user_input:
response, follow_up, image_url = get_response("You are a helpful AI assistant.", user_input)
if response:
st.markdown(f"**HAL**: {response}")
if follow_up:
st.markdown(f"**HAL**: {follow_up}")
if image_url:
st.image(image_url, caption="NASA Image of the Day")
|