fixed the user input and changed the finalized key

result design
This commit is contained in:
Khanh Dinh 2025-01-03 10:27:29 +01:00
parent d59ebdc4c3
commit c6230b0f1c
5 changed files with 157 additions and 41 deletions

View File

@ -110,4 +110,23 @@ Here is what we have thought about and we would like to phrase an OKR with up to
this is the user input: this is the user input:
{user_input} {user_input}
""" """
team = [
'Khanh Dinh',
'Roberto Renna',
'Suat Sonkur',
'Sven Eichmeyer',
'Robin Plitzko',
'Vikas Rathore',
'Nadia Kartascheff',
'Andreas Muheim',
'Christopher Koch',
'Andreas Pluess',
'Manfred Hahn',
'Michaela Schumacher',
'Sandra Pastoor',
'Mareen Fox Rogers',
'Michelle Wehrli',
'Johannes Otto'
]

View File

@ -1,4 +1,4 @@
import streamlit as st '''import streamlit as st
from api import fetch_okrs from api import fetch_okrs
from config import SYSTEM_PROMPT, INPUT_TEMPLATE, PROMPT_TEMPLATE from config import SYSTEM_PROMPT, INPUT_TEMPLATE, PROMPT_TEMPLATE
@ -118,4 +118,121 @@ def proposer_page():
body=kr, body=kr,
language=None, language=None,
wrap_lines=True wrap_lines=True
) )
'''
import streamlit as st
from api import fetch_okrs
from config import INPUT_TEMPLATE, team
from utils import extract_llm_response
def proposer_page():
# Streamlit App Layout
st.title("AO/PM OKR Proposer")
# Input Section and Buttons Row
st.subheader("Enter your idea or goal:")
user_input = st.text_area(
"Input your idea here:",
value=st.session_state.get("user_input", INPUT_TEMPLATE.strip()),
height=300,
)
generate_okrs_clicked = st.button("Generate OKR Proposal")
if generate_okrs_clicked:
if not user_input.strip():
st.warning("Please provide some input before generating OKRs.")
else:
with st.spinner("Generating OKRs..."):
response = fetch_okrs(user_input=user_input)
if response:
# Extract Objective and Key Results from response
objective, key_results, hint = extract_llm_response(response)
st.session_state["objective"] = objective
st.session_state["key_results"] = key_results
st.session_state["hint"] = hint
# Display Results Only if an OKR Has Been Generated
if "objective" in st.session_state and "key_results" in st.session_state:
# Ensure team members exist in session state
if "team_members" not in st.session_state:
# Sorting the list alphabetically by the first name
sorted_names = sorted(team, key=lambda name: name.split()[0])
st.session_state["team_members"] = sorted_names # Default team members
team_members = st.session_state["team_members"]
# Display Objective Field with Responsibles Input Below It
st.subheader("Proposal Objective:")
objective_text = st.text_area(
"Proposal Objective:",
value=st.session_state.get("objective", ""),
height=100,
)
responsible_for_objective = st.multiselect(
"Select Responsibles for Objective:",
options=team_members,
default=[],
key="responsibles_objective"
)
# Display Key Results with Responsibles Below Each One
st.subheader("Proposal Key Results:")
key_result_boxes = []
responsibles_for_key_results = []
for i, kr in enumerate(st.session_state["key_results"], start=1):
kr_text = st.text_area(f"Key Result {i}:", value=kr, key=f"kr_{i}")
responsible_for_kr = st.multiselect(
f"Select Responsibles for Key Result {i}:",
options=team_members,
default=[],
key=f"responsibles_kr_{i}"
)
key_result_boxes.append(kr_text)
responsibles_for_key_results.append(responsible_for_kr)
# Finalize Button Center-Aligned
if st.button("Finalize"):
finalized_objective = objective_text.strip()
finalized_key_results = [st.session_state[f"kr_{i+1}"].strip() for i in range(len(key_result_boxes))]
# Append initials of responsibles to Objective and Key Results
responsibles_list_objective = responsible_for_objective
initials_objective = [f"[{''.join([part[0] for part in name.split()]).upper()}]" for name in responsibles_list_objective]
initials_str_objective = ", ".join(initials_objective)
finalized_objective = f"{initials_str_objective} {finalized_objective}"
finalized_key_results_with_initials = []
for i, kr in enumerate(finalized_key_results):
responsibles_list_kr = responsibles_for_key_results[i]
initials_kr = [f"{''.join([part[0] for part in name.split()]).upper()}" for name in responsibles_list_kr]
initials_str_kr = ", ".join(initials_kr)
finalized_key_results_with_initials.append(f"KR{i+1}: [{initials_str_kr}] {kr}")
# Display finalized data in non-editable format (full width)
st.subheader("Finalized Objective:")
st.code(
body=finalized_objective,
language=None,
wrap_lines=True
)
st.subheader("Finalized Key Results:")
for kr in finalized_key_results_with_initials:
with st.container():
col1, col2 = st.columns(spec=[0.1, 0.9])
with col1:
st.caption(kr.split(':')[0])
with col2:
st.code(
body=kr.split(':')[-1],
language=None,
wrap_lines=True
)

13
settings.json Normal file
View File

@ -0,0 +1,13 @@
{
"system_prompt": "\nYou are an OKR coach who helps beginners create well-phrased OKRs (Objectives and Key Results). \nYour goal is to provide a proposal for an OKR based on user input, formatted as JSON. \nIf the input is unclear or incomplete, include a hint with specific questions or suggestions \nto help improve the input.\n\nAlways follow this format for your response:\n{\n \"hint\": \"Suggestions or questions to improve the input, if needed. If no hint is needed, return an empty string.\",\n \"proposal\": [\n {\n \"objective\": \"A clear and concise objective variant\",\n \"key_results\": [\"Key result 1\", \"Key result 2\", \"... up to 5 key results\"]\n },\n ...\n ]\n}\n\nKeep your responses concise, actionable, and aligned with OKR best practices. If you need more context from the user, ask for it in the `hint`.\nAlways provide a 'hint' how to further improve the user input in order to get better results.\n\n",
"input_template": "\nWe want to improve our SLA framework by finalizing the current SLA template, which is used for the negotiations with our ground service partners.\nThe resulting SLA will be used in order to measure the quality of the service partner and issue penalties if targets are not met. \nWe would like to improve this, to have a better steering function, e.g. by adding a bonus component to the SLA framework.\n\nTo achieve this, we need to develop a bonus concept which is viable, feasible and desirable. \nWe need to simulate the concept, so that we don't risk issuing too much bonus which we cannot cover.\nWe need to define organizational processes and responsibilities so that we are able to pay a bonus.\n\nHow should the OKR look like for the next cycle which starts in Jan 2025 and ends in Apr 2025?\n",
"prompt_template": "\nPlease help us in defining proper OKRs.\nHere is what we have thought about and we would like to phrase an OKR with maximum 5 key results.\nThe next OKR cycle is from JAN 2025 till APR 2025.\n\nthis is the user input:\n{user_input}\n\nPlease provide the response in json format. \n",
"num_key_results": 4,
"team_members": [
"Khanh Dinh",
"Robin Plitzko",
"Roberto Renna",
"Nadia Ka"
],
"team_member_template": "{name} - Team Member"
}

View File

@ -1,8 +1,8 @@
import streamlit as st import streamlit as st
import json import json
import os import os
from config import SYSTEM_PROMPT, INPUT_TEMPLATE, PROMPT_TEMPLATE from config import SYSTEM_PROMPT, INPUT_TEMPLATE, PROMPT_TEMPLATE, team
'''
def settings_page(): def settings_page():
st.title("Settings") st.title("Settings")
@ -85,7 +85,7 @@ def team_member_management():
st.warning(f"{new_member.strip()} is already in the team.") st.warning(f"{new_member.strip()} is already in the team.")
else: else:
st.warning("Please enter a valid name.") st.warning("Please enter a valid name.")
'''

View File

@ -103,16 +103,13 @@ def extract_llm_response(response):
Returns: Returns:
tuple: A tuple containing the objective (str), key results (list), and hint (str). tuple: A tuple containing the objective (str), key results (list), and hint (str).
""" """
print("RESPONSE:",response)
raw_message_content = response["choices"][0]["message"]["content"] raw_message_content = response["choices"][0]["message"]["content"]
print("raw_message_content:", raw_message_content)
# Clean and parse the JSON content # Clean and parse the JSON content
cleaned_content = raw_message_content.replace("`", "").split("json")[-1] cleaned_content = raw_message_content.replace("`", "").split("json")[-1]
print("cleaned content", cleaned_content)
parsed_data = parse_json_content(cleaned_content=cleaned_content) parsed_data = parse_json_content(cleaned_content=cleaned_content)
print("parsed_data:",parsed_data)
hint = parsed_data.get("hint", "") hint = parsed_data.get("hint", "")
@ -127,34 +124,4 @@ def extract_llm_response(response):
objective = "" objective = ""
key_results = [] key_results = []
#print("debug:", parsed_data.get("objective", "")) return objective, key_results, hint
return objective, key_results, hint
#try:
# Extract hint from the response
hint = response.get("hint", "")
# Extract proposals from the response
proposals = response.get("proposals", [])
print("hint:", hint)
print("proposals:", proposals)
# Check if proposals are available
if proposals:
# Extract the first proposal's objective and key results
first_proposal = proposals[0] # Get the first proposal (assuming it's a list)
objective = first_proposal.get("objective", "")
key_results = first_proposal.get("key_results", [])
else:
objective = ""
key_results = []
# Log parsed data for debugging
print("parsed_data:", {"objective": objective, "key_results": key_results, "hint": hint})
return objective, key_results, hint
#except Exception as e:
# print(f"Error parsing API response: {e}")
# return "", [], ""