from sentence_transformers import SentenceTransformer import torch import gradio as gr from huggingface_hub import InferenceClient # This is the same pattern from the Generative AI lesson! It uses the # Inference Provider API to send your messages to an AI model and get # a response back. Swap out the model below for a different one if # you want to experiment! # # Note: if this Space doesn't already have one, you'll need to add an # HF_TOKEN secret in the Space's Settings tab for this to work # (Settings -> Variables and secrets -> New secret). client = InferenceClient("Qwen/Qwen2.5-7B-Instruct") model = SentenceTransformer('all-MiniLM-L6-v2') with open("knowledge.txt", "r", encoding="utf-8") as file: knowledge_text = file.read() def preprocess_text(text): cleaned_text = text.strip() # Split the cleaned_text by every newline character (\n) chunks = cleaned_text.split(".") # Create an empty list to store cleaned chunks cleaned_chunks = [] # Write your for-in loop below to clean each chunk and add it to the cleaned_chunks list for chunk in chunks: if chunk != " ": cleaned_chunks.append(chunk) return cleaned_chunks cleaned_chunks = preprocess_text(knowledge_text) def create_embeddings(text_chunks): # Convert each text chunk into a vector embedding and store as a tensor chunk_embeddings = model.encode(text_chunks, convert_to_tensor=True) # Return the chunk_embeddings return chunk_embeddings chunk_embeddings = create_embeddings(cleaned_chunks) def get_top_chunks(query, chunk_embeddings, text_chunks): # Convert the query text into a vector embedding query_embedding = model.encode(query, convert_to_tensor=True) # Complete this line # Normalize the query embedding to unit length for accurate similarity comparison query_embedding_normalized = query_embedding / query_embedding.norm() # Normalize all chunk embeddings to unit length for consistent comparison chunk_embeddings_normalized = chunk_embeddings / chunk_embeddings.norm(dim=1, keepdim=True) # Calculate cosine similarity between all chunks and the query using matrix multiplication similarities = torch.matmul(chunk_embeddings_normalized, query_embedding_normalized) # Find the indices of the 3 chunks with highest similarity scores top_indices = torch.topk(similarities, k=3).indices # Create an empty list to store the most relevant chunks top_chunks = [] # Loop through the top indices and retrieve the corresponding text chunks # This is only one way scholars may write this, but there are other ways! for i in top_indices: chunk = text_chunks[i] top_chunks.append(chunk) return top_chunks def respond(message, history): top_chunks = get_top_chunks(message, chunk_embeddings, cleaned_chunks) context = "\n\n".join(top_chunks) #messages = [{"role": "system", "content": f"You are a friendly chatbot who is an expert career recommendations. Answer the user using relevant and accurate content: {context}"}] messages = [{ "role": "system", "content": f""" You are Career Compass, a friendly career mentor for teenagers and high school students. Your goal is to help students discover careers, educational pathways, and opportunities that match their interests and goals. Communication style: - Be friendly, supportive, and encouraging. - Speak naturally and conversationally. - Use simple language that teenagers can easily understand. - Use relevant emojis on each response, maximum 5. - Avoid sounding like a textbook or formal counselor. - Sound like a knowledgeable older mentor. - Format responses using headings, bullet points, and short paragraphs. - Avoid long blocks of text unless necessary. - Talk in first person. Response guidelines: - Personalize recommendations whenever possible. - Explain WHY a career fits the user's interests. - Give multiple options rather than one career. - Encourage exploration and curiosity. - End most responses with a follow-up question. - Detail the key skills needed for each career. - Answer the user using relevant and accurate content: - Before recommending careers, briefly acknowledge what the student said. - Mention both exciting aspects and possible challenges of each career. - Include a short action plan explaining what students can do next. For every career recommendation, include: 1. Career Name followed by a brief description of what this career involves and what professionals in this field do. 2. Why it may fit you - Explain the connection between the student's interests, strengths, and this career. 3. Key Skills Needed - List important technical skills and soft skills required for this career. 4. Education Pathway - Mention possible college degrees, majors, or courses students can pursue. - Include relevant certifications, online courses, or additional learning opportunities when useful. 5. Future Opportunities - Briefly explain possible industries, job roles, or growth opportunities related to this career. {context} """ }] if history: messages.extend(history) messages.append({"role": "user", "content": message}) response = "" for chunk in client.chat_completion( messages, max_tokens=1000, temperature = 0.5, stream = True ): token = chunk.choices[0].delta.content response += token yield response """return response.choices[0].message.content.strip()*/""" custom_css = """ /* Background of the whole chatbot */ .gradio-container { background-color: #A4508b; } /* Title text */ h1 { color: #A4508B; font-family: Arial, sans-serif; } /* User message bubble */ .message.user { background-color: #FFD6E0 !important; color: #A4508B !important; border-radius: 20px !important; padding: 12px 16px !important; } /* Bot message bubble */ .message.bot { background-color: #E8D9FF !important; color: #A4508B !important; border-radius: 20px !important; padding: 12px 16px !important; } /* Make the chat bubbles rounded */ .message { border-radius: 20px !important; } /* Input box */ textarea { border-radius: 20px !important; border: 2px solid #E8A0BF !important; background-color: #FFFFFF !important; } /* Send button */ button { background-color: #E8A0BF !important; color: white !important; border-radius: 20px !important; border: none !important; } /* Send button hover */ button:hover { background-color: #D67D9B !important; } .welcome-text { text-align: center; } .welcome-text h3 { color: #EABFCB !important; font-size: 32px !important; } .welcome-text p { color: #EABFCB !important; font-size: 18px !important; } """ with gr.Blocks(fill_height=True, css=custom_css, theme=gr.themes.Soft()) as demo: gr.Image( value="banner.png", show_label=False, interactive=False, ) gr.Markdown( """ ### Welcome to Career Compass! 👋 I'm here to help you discover careers based on your interests, strengths, and goals. 🚀 """, elem_classes=["welcome-text"] ) gr.ChatInterface( respond, fill_height=True, examples=[ "What careers suit someone who loves biology?", "I enjoy coding. What careers can I explore?", "What skills do I need to become a doctor?", "Which careers match my personality?" ] ) demo.launch()