import pandas as pd import streamlit as st import os import json from openai import AzureOpenAI from model import create_models, configure_settings, load_documents_and_create_index, \ create_chat_prompt_template, execute_query from datasets import Dataset, DatasetDict, load_dataset, concatenate_datasets client = AzureOpenAI(azure_endpoint="https://personality-service.openai.azure.com/", api_key=os.getenv("AZURE_OPENAI_KEY"), api_version="2024-02-15-preview") TOKEN = os.getenv('hf_token') def store_feedback(user_input, response, feedback, rating,repo): dataset = load_dataset(repo, token=TOKEN, download_mode="force_redownload", ignore_verifications=True) new_entry = pd.DataFrame({"user_input": [user_input], "response": [response], "feedback": [feedback], "rating": [rating]}) new_dataset = Dataset.from_pandas(new_entry) updated_dataset = concatenate_datasets([dataset["train"], new_dataset]) updated_dataset.push_to_hub(repo, private=False, token=TOKEN) # Function to generate a completion using OpenAI API def generate_one_completion(message, temperature): response = client.chat.completions.create( model="personality_gpt4o", temperature=temperature, max_tokens=1000, # Adjust based on desired response length frequency_penalty=0.2, # To avoid repetition presence_penalty=0.2, # To introduce new topics messages=message, stream=False ) return response import json def get_profile_str(profile): bio_info = profile['bio_information'] main_profile = profile['main_profile'] red_flag = profile['red_flag'] motivation = profile['motivation'] profile_str = f"Bio Information:\n" for key, value in bio_info.items(): profile_str += f"- {key.replace('_', ' ').title()}: {value}\n" profile_str += f"\nMain Profile:\n" for key, value in main_profile.items(): profile_str += f"- {key.title()}: {value['score']} - {value['summary']}\n" profile_str += f"\nRed Flags:\n" for key, value in red_flag.items(): profile_str += f"- {key.title()}: {value['score']} - {value['summary']}\n" profile_str += f"\nMotivation:\n" for key, value in motivation.items(): profile_str += f"- {key.title()}: {value['score']} - {value['summary']}\n" return profile_str def generate_prompt_from_profile(profile, version="TestTakersSummary"): with open('prompts.json') as f: prompt_sets = json.load(f)['Prompts'] prompt_templates = prompt_sets[version] try: # Fetching profile data individual_name = profile['bio_information'].get('Name', 'the individual') # Generating bio, profile, and red flags sections bio_section = "\n".join( [f"- {k.replace('_', ' ').title()}: {v}" for k, v in profile['bio_information'].items()]) main_profile_section = "\n".join( [f"- {trait.title()}: {details['score']} - {details['summary']}" for trait, details in profile['main_profile'].items()]) red_flags_section = "\n".join( [f"- {trait.title()}: {details['score']} - {details['summary']}" for trait, details in profile['red_flag'].items()]) motivation_section = "\n".join( [f"- {trait.title()}: {details['score']} - {details['summary']}" for trait, details in profile['motivation'].items()]) # Replacing placeholders in the prompts prompts = [ x.replace('{{INDIVIDUAL_NAME}}', individual_name).replace('{{BIO}}', bio_section).replace('{{PROFILE}}',main_profile_section).replace( '{{REDFLAGS_PROFILE}}', red_flags_section).replace('{{MOTIVATION_PROFILE}}', motivation_section) for x in prompt_templates] # Compiling final prompt prompt = "\n".join(prompts) except KeyError as e: return [{"role": "system", "content": f"Error processing profile data: missing {str(e)}"}] message = [ {"role": "system", "content": prompt_sets[version][0]}, {"role": "user", "content": prompt} ] return message def display_profile_info(profile): main_profile = profile["main_profile"] red_flag = profile["red_flag"] bio_info = profile["bio_information"] st.sidebar.markdown("### Bio Information: ") st.sidebar.markdown("\n".join([f"- **{key.replace('_', ' ')}**: {value}" for key, value in bio_info.items()])) st.sidebar.markdown("### Main Profile: ") st.sidebar.markdown("\n".join( [f"- **{attribute}**: {details['score']} - {details['summary']}" for attribute, details in main_profile.items()])) st.sidebar.markdown("### Red Flags: ") st.sidebar.markdown("\n".join( [f"- **{attribute}**: {details['score']} - {details['summary']}" for attribute, details in red_flag.items()])) st.sidebar.markdown("### Motivation: ") st.sidebar.markdown("\n".join( [f"- **{attribute}**: {details['score']} - {details['summary']}" for attribute, details in profile['motivation'].items()])) def validate_json(profile): required_keys = ['bio_information', 'main_profile', 'red_flag', 'motivation'] for key in required_keys: if key not in profile: return False, f"Key '{key}' is missing." if not isinstance(profile[key], dict): return False, f"'{key}' should be a dictionary." return True, "JSON structure is valid." def logout(): st.session_state['authenticated'] = False st.session_state['profile'] = None st.session_state['show_chat'] = None st.session_state['analysis'] = None st.rerun() def main_app(): sidebar_components() if st.button('Logout'): logout() # Streamlit app st.title('Metaprofiling\'s Career Insight Analyzer Demo') # Check if a profile is selected if st.session_state['profile']: profile = st.session_state['profile'] display_profile_info(profile) # Display the profile information st.markdown(""" ### Generation Temperature Adjust the 'Generation Temperature' to control the creativity of the AI responses. - A *lower temperature* (closer to 0.0) generates more predictable, conservative responses. - A *higher temperature* (closer to 1.0) generates more creative, diverse responses. """) # Temperature slider st.session_state['temperature'] = st.slider("", min_value=0.0, max_value=1.0, value=0.5, step=0.01) # Allow user to choose from different versions of the prompt st.session_state['version'] = st.selectbox("Select Prompt Version", ["TestTakersSummary", "ManagersSummary"]) # Generate and display prompt prompt = None if st.button(f'Analyze Profile ({st.session_state["version"]})'): # with st.spinner('Generating completion...'): prompt = generate_prompt_from_profile(profile, version=st.session_state['version']) with st.chat_message("assistant"): stream = client.chat.completions.create( model="personality_gpt4o", temperature=st.session_state['temperature'], max_tokens=4096, # Adjust based on desired response length frequency_penalty=0.2, # To avoid repetition presence_penalty=0.2, # To introduce new topics messages=prompt, stream=True) response = st.write_stream(stream) # st.markdown(response_test_taker) st.session_state['analysis'] = response st.session_state['show_chat'] = True st.rerun() # display the response if st.session_state['analysis']: # Ask for feedback st.markdown(st.session_state['analysis']) feedback = st.text_input("Provide your feedback on the response:") rating = st.slider("Rate the response:", 0, 10, 5) if st.button('Submit Feedback'): store_feedback(str(prompt), st.session_state['analysis'], feedback, rating, "wu981526092/feedback_report") else: st.write("Please upload a profile JSON file or use the example profile.") # Function to verify credentials and set the session state def verify_credentials(): if st.session_state['username'] == os.getenv("username_app") and st.session_state['password'] == os.getenv( "password_app"): st.session_state['authenticated'] = True else: st.error("Invalid username or password") # Login page def login_page(): st.title("Welcome to Metaprofiling's Career Insight Analyzer Demo") st.write( "This application provides in-depth analysis and insights into professional profiles. Please log in to continue.") # Description and Instructions st.markdown(""" ## How to Use This Application - Enter your username and password in the sidebar. - Click on 'Login' to access the application. - Once logged in, you will be able to upload and analyze professional profiles. """) st.sidebar.write("Login:") username = st.sidebar.text_input("Username") # , key='username') password = st.sidebar.text_input("Password", type="password") # , key='password') st.session_state['username'] = username st.session_state['password'] = password st.sidebar.button("Login", on_click=verify_credentials) def sidebar_components(): with st.sidebar: if st.button('Reset'): st.session_state['profile'] = None st.session_state['show_chat'] = None st.session_state['analysis'] = None st.rerun() if not st.session_state['show_chat']: # Instructions for JSON format st.markdown("### JSON File Requirements:") st.markdown("1. Must contain 'bio_information', 'main_profile', and 'red_flag' as top-level keys.") st.markdown("2. Both keys should have dictionary values.") st.markdown("### Choose the Definition:") st.session_state['definition'] = st.selectbox("Select Definition", [1, 2]) st.session_state['chat_context'] = st.selectbox("Select Chat Context", ["analysis", "profile"]) # File uploader st.markdown("### Upload a profile JSON file") uploaded_file = st.file_uploader("", type=['json']) if uploaded_file is not None: try: profile_data = json.load(uploaded_file) valid, message = validate_json(profile_data) if valid: st.session_state['profile'] = profile_data else: st.error(message) except json.JSONDecodeError: st.error("Invalid JSON file. Please upload a valid JSON file.") # Button to load example profile if st.button('Use Example Profile'): if st.session_state['definition'] == 1: file_name = "example_data_definition_1.json" else: file_name = "example_data_definition_2.json" with open(file_name, 'r') as file: st.session_state['profile'] = json.load(file) # elif uploaded_file is not None: # st.session_state['profile'] = json.load(uploaded_file) else: st.sidebar.title("Chat with Our Career Advisor") #st.sidebar.markdown( #"Hello, we hope you learned something about yourself in this report. This chat is here so you can ask any questions you have about your report! It’s also a great tool to get ideas about how you can use the information in your report for your personal development and achieving your current goals.") # Name to be included in the questions # name = st.session_state['profile']['bio_information'].get('Name', 'the individual') # List of question templates where {} will be replaced with the name question_templates = [ "What are the main risks associated with {}’s profile?", "What are the implications of {}’s profile for working with others?", # "What conclusions might we draw from his profile about {}’s style of leadership?", # "Looking specifically at {}'s Red Flags, are there any particular areas of concern?", # "Based on this profile, is {} better suited as a COO or a CEO?", # "If speed of execution is important, based on his profile, how likely is {} to be able to achieve this?", # "How is {} likely to react to business uncertainty and disruption?", # "Based on his profile, what should a coaching plan designed for {} focus on?" ] # Formatting each question template with the name questions_list = [question.format("Test Taker") for question in question_templates] # Prepare the questions for Markdown display questions_markdown = "\n\n".join( [f"Q{index + 1}: {question}" for index, question in enumerate(questions_list)]) # Code to display in the app st.sidebar.markdown("### Suggest Questions") st.sidebar.markdown(questions_markdown) # st.sidebar.text_area("Suggested Questions", value=questions.choices[0].message.content, height=200, disabled=True) user_input = st.sidebar.text_input("Ask a question about the profile analysis:") llm, embed_model = create_models() configure_settings(llm, embed_model) index = load_documents_and_create_index() if st.sidebar.button('Submit'): if user_input: if st.session_state['chat_context'] == "profile": chat_prompt_template = create_chat_prompt_template(get_profile_str(st.session_state['profile']),st.session_state['definition']) else: chat_prompt_template = create_chat_prompt_template(st.session_state['analysis'],st.session_state['definition']) response = execute_query(index, chat_prompt_template, user_input) # Display the response st.sidebar.markdown(response) # Ask for feedback feedback = st.sidebar.text_input("Provide your feedback on the response:") rating = st.sidebar.slider("Rate the response:", 0, 10, 5) if st.sidebar.button('Submit Feedback'): store_feedback(user_input, response, feedback, rating, "wu981526092/feedback_report") st.sidebar.success("Feedback submitted successfully!") # Initialize session state variables with default values if not already set session_defaults = { 'show_chat': None, 'definition': 1, 'chat_context': "analysis", 'profile': None, 'analysis': None, 'temperature': 0, 'version': "", 'username': '', 'password': '', 'authenticated': False } for key, default in session_defaults.items(): if key not in st.session_state: st.session_state[key] = default # Show login or main app based on authentication status if st.session_state['authenticated']: main_app() else: login_page() # # Display the sidebar components based on the state # if 'show_chat' not in st.session_state: # st.session_state['show_chat'] = None # # if 'definition' not in st.session_state: # st.session_state['definition'] = 1 # # if 'chat_context' not in st.session_state: # st.session_state['chat_context'] = "analysis" # # if 'profile' not in st.session_state: # st.session_state['profile'] = None # # if 'analysis' not in st.session_state: # st.session_state['analysis'] = None # # if 'temperature' not in st.session_state: # st.session_state['temperature'] = 0 # # if 'version' not in st.session_state: # st.session_state['version'] = "" # # # Initialize session state for username, password, and authentication # if 'username' not in st.session_state: # st.session_state['username'] = '' # if 'password' not in st.session_state: # st.session_state['password'] = '' # if 'authenticated' not in st.session_state: # st.session_state['authenticated'] = False # # Show login or main app based on authentication # if st.session_state['authenticated']: # main_app() # else: # login_page()