added parameters to the proposer #3
16
api.py
16
api.py
@ -5,7 +5,8 @@ from dotenv import load_dotenv
|
||||
from settings import load_settings
|
||||
from utils import construct_prompt
|
||||
|
||||
from config import INPUT_TEMPLATE, SYSTEM_PROMPT, PROMPT_TEMPLATE
|
||||
#from config import SYSTEM_PROMPT, PROMPT_TEMPLATE
|
||||
from config.config import INPUT_EXAMPLE, SYSTEM_PROMPT, PROMPT_TEMPLATE
|
||||
|
||||
# Load API key from .env file
|
||||
load_dotenv()
|
||||
@ -17,13 +18,12 @@ if not api_key:
|
||||
|
||||
api_url = "https://genai.dev.odp.lhgroup.de/openai/deployments/gpt-4-turbo/chat/completions?api-version=2023-07-01-preview"
|
||||
|
||||
def fetch_okrs(user_input: str):
|
||||
#settings = load_settings()
|
||||
|
||||
#system_prompt = settings["system_prompt"]
|
||||
#input_template = settings["input_template"]
|
||||
|
||||
user_prompt = construct_prompt(prompt_template=PROMPT_TEMPLATE, user_input=user_input)
|
||||
def fetch_okrs(user_input: str, okr_cycle: str = 'JAN 25 to APR 25', num_key_results: int=3):
|
||||
user_prompt = construct_prompt(
|
||||
prompt_template=PROMPT_TEMPLATE,
|
||||
user_input=user_input,
|
||||
okr_cycle=okr_cycle,
|
||||
num_key_results=num_key_results)
|
||||
|
||||
headers = {"api-key": api_key, "Content-Type": "application/json"}
|
||||
body = {
|
||||
|
||||
12
config.py
12
config.py
@ -82,8 +82,8 @@ The json could be structured like this:
|
||||
|
||||
PROMPT_TEMPLATE = """
|
||||
Please help us in defining proper OKRs.
|
||||
Here is what we have thought about and we would like to phrase an OKR with maximum 5 key results.
|
||||
The next OKR cycle is from JAN 2025 till APR 2025.
|
||||
Here is what we have thought about and we would like to phrase an OKR with {num_key_results} key results.
|
||||
The next OKR cycle is from {okr_cycle}
|
||||
|
||||
this is the user input:
|
||||
{user_input}
|
||||
@ -99,8 +99,6 @@ We would like to improve this, to have a better steering function, e.g. by addin
|
||||
To achieve this, we need to develop a bonus concept which is viable, feasible and desirable.
|
||||
We need to simulate the concept, so that we don't risk issuing too much bonus which we cannot cover.
|
||||
We need to define organizational processes and responsibilities so that we are able to pay a bonus.
|
||||
|
||||
How should the OKR look like for the next cycle which starts in Jan 2025 and ends in Apr 2025?
|
||||
"""
|
||||
|
||||
# Prompt template for user input
|
||||
@ -130,3 +128,9 @@ team = [
|
||||
'Michelle Wehrli',
|
||||
'Johannes Otto'
|
||||
]
|
||||
|
||||
cycle_definitions = {
|
||||
'Cycle1': 'JAN 2025 to APR 2025',
|
||||
'Cycle2': 'MAY 2025 to AUG 2025',
|
||||
'Cycle3': 'SEP 2025 to DEC 2025'
|
||||
}
|
||||
0
config/__init__.py
Normal file
0
config/__init__.py
Normal file
69
config/config.py
Normal file
69
config/config.py
Normal file
@ -0,0 +1,69 @@
|
||||
cycle_definitions = {
|
||||
'Cycle1': 'JAN 2025 to APR 2025',
|
||||
'Cycle2': 'MAY 2025 to AUG 2025',
|
||||
'Cycle3': 'SEP 2025 to DEC 2025'
|
||||
}
|
||||
|
||||
SYSTEM_PROMPT = """
|
||||
You are an OKR coach who helps beginners create well-phrased OKRs (Objectives and Key Results).
|
||||
Your goal is to provide a proposal for an OKR based on user input, formatted as JSON.
|
||||
If the input is unclear or incomplete, include a hint with specific questions or suggestions
|
||||
to help improve the input.
|
||||
|
||||
Always follow this format for your response:
|
||||
{
|
||||
"hint": "Suggestions or questions to improve the input, if needed. If no hint is needed, return an empty string.",
|
||||
"proposal": [
|
||||
{
|
||||
"objective": "A clear and concise objective variant",
|
||||
"key_results": ["Key result 1", "Key result 2", "... up to 5 key results"]
|
||||
},
|
||||
...
|
||||
]
|
||||
}
|
||||
|
||||
Keep your responses concise, actionable, and aligned with OKR best practices. If you need more context from the user, ask for it in the `hint`.
|
||||
Always provide a 'hint' how to further improve the user input in order to get better results.
|
||||
|
||||
"""
|
||||
|
||||
# Prompt template for user input
|
||||
PROMPT_TEMPLATE = """
|
||||
Please help us in defining proper OKRs.
|
||||
Here is what we have thought about and we would like to phrase an OKR with {num_key_results} key results.
|
||||
The next OKR cycle is from {okr_cycle}
|
||||
|
||||
this is the user input:
|
||||
{user_input}
|
||||
|
||||
Please provide the response in json format.
|
||||
"""
|
||||
|
||||
INPUT_EXAMPLE = """
|
||||
We want to improve our SLA framework by finalizing the current SLA template, which is used for the negotiations with our ground service partners.
|
||||
The resulting SLA will be used in order to measure the quality of the service partner and issue penalties if targets are not met.
|
||||
We would like to improve this, to have a better steering function, e.g. by adding a bonus component to the SLA framework.
|
||||
|
||||
To achieve this, we need to develop a bonus concept which is viable, feasible and desirable.
|
||||
We need to simulate the concept, so that we don't risk issuing too much bonus which we cannot cover.
|
||||
We need to define organizational processes and responsibilities so that we are able to pay a bonus.
|
||||
"""
|
||||
|
||||
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'
|
||||
]
|
||||
76
proposer.py
76
proposer.py
@ -1,28 +1,40 @@
|
||||
import streamlit as st
|
||||
from api import fetch_okrs
|
||||
from config import INPUT_TEMPLATE, team
|
||||
#from config import INPUT_TEMPLATE, team, cycle_definitions
|
||||
from config.config import INPUT_EXAMPLE, cycle_definitions, team
|
||||
from utils import extract_llm_response
|
||||
|
||||
def proposer_page():
|
||||
# Streamlit App Layout
|
||||
st.title("AO/PM OKR Proposer")
|
||||
import json
|
||||
|
||||
from ui.parameters import section_parameters
|
||||
|
||||
def section_user_input():
|
||||
# section for input parameters
|
||||
section_parameters()
|
||||
|
||||
# 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()),
|
||||
value=st.session_state.get("user_input", INPUT_EXAMPLE.strip()),
|
||||
height=300,
|
||||
)
|
||||
|
||||
st.session_state['user_input'] = user_input
|
||||
|
||||
generate_okrs_clicked = st.button("Generate OKR Proposal")
|
||||
|
||||
if generate_okrs_clicked:
|
||||
print("session_state:", st.session_state)
|
||||
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)
|
||||
response = fetch_okrs(
|
||||
user_input=user_input,
|
||||
okr_cycle=st.session_state['okr_cycle'],
|
||||
num_key_results=st.session_state['num_key_results'])
|
||||
|
||||
if response:
|
||||
# Extract Objective and Key Results from response
|
||||
objective, key_results, hint = extract_llm_response(response)
|
||||
@ -30,6 +42,7 @@ def proposer_page():
|
||||
st.session_state["key_results"] = key_results
|
||||
st.session_state["hint"] = hint
|
||||
|
||||
def section_okr_proposals():
|
||||
# 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
|
||||
@ -52,7 +65,8 @@ def proposer_page():
|
||||
"Select Responsibles for Objective:",
|
||||
options=team_members,
|
||||
default=[],
|
||||
key="responsibles_objective"
|
||||
key="responsibles_objective",
|
||||
max_selections=1
|
||||
)
|
||||
|
||||
# Display Key Results with Responsibles Below Each One
|
||||
@ -61,12 +75,18 @@ def proposer_page():
|
||||
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}:",
|
||||
kr_text = st.text_area(
|
||||
label=f'KR{i}',
|
||||
value=kr,
|
||||
key=f"proposal_kr_{i}"
|
||||
)
|
||||
#kr_text = st.text_area(f"Key Result {i}:", value=kr, key=f"kr_{i}")
|
||||
responsible_for_kr = st.pills(
|
||||
label=f"Select Responsibles for Key Result {i}:",
|
||||
options=team_members,
|
||||
default=[],
|
||||
key=f"responsibles_kr_{i}"
|
||||
key=f"responsibles_kr_{i}",
|
||||
selection_mode='multi'
|
||||
)
|
||||
|
||||
key_result_boxes.append(kr_text)
|
||||
@ -75,7 +95,7 @@ def proposer_page():
|
||||
# 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))]
|
||||
finalized_key_results = [st.session_state[f"proposal_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
|
||||
@ -83,6 +103,7 @@ def proposer_page():
|
||||
initials_str_objective = ", ".join(initials_objective)
|
||||
|
||||
finalized_objective = f"{initials_str_objective} {finalized_objective}"
|
||||
st.session_state['finalized_objective'] = finalized_objective
|
||||
|
||||
finalized_key_results_with_initials = []
|
||||
for i, kr in enumerate(finalized_key_results):
|
||||
@ -90,6 +111,7 @@ def proposer_page():
|
||||
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}")
|
||||
st.session_state['finalized_key_results_with_initials'] = finalized_key_results_with_initials
|
||||
|
||||
# Display finalized data in non-editable format (full width)
|
||||
st.subheader("Finalized Objective:")
|
||||
@ -112,3 +134,33 @@ def proposer_page():
|
||||
language=None,
|
||||
wrap_lines=True
|
||||
)
|
||||
export_data_as_json()
|
||||
|
||||
def export_data_as_json():
|
||||
# Prepare data for export
|
||||
finalized_key_results_with_initials = st.session_state.get('finalized_key_results_with_initials')
|
||||
export_data = {
|
||||
"user_input": st.session_state.get('user_input'),
|
||||
"finalized_objective": st.session_state.get('finalized_objective'),
|
||||
"key_results": [kr.split(':')[-1].strip() for kr in finalized_key_results_with_initials]
|
||||
}
|
||||
|
||||
# Convert data to JSON string
|
||||
json_data = json.dumps(export_data, indent=4)
|
||||
|
||||
# Add a download button
|
||||
st.download_button(
|
||||
label="Download Finalized OKR",
|
||||
data=json_data,
|
||||
file_name="okr_data.json",
|
||||
mime="application/json"
|
||||
)
|
||||
|
||||
def proposer_page():
|
||||
# Streamlit App Layout
|
||||
st.title("AO/PM OKR Proposer")
|
||||
|
||||
section_user_input()
|
||||
|
||||
section_okr_proposals()
|
||||
|
||||
|
||||
@ -1,7 +1,8 @@
|
||||
import streamlit as st
|
||||
import json
|
||||
import os
|
||||
from config import SYSTEM_PROMPT, INPUT_TEMPLATE, PROMPT_TEMPLATE, team
|
||||
from config.config import SYSTEM_PROMPT, INPUT_EXAMPLE, PROMPT_TEMPLATE, team
|
||||
|
||||
'''
|
||||
def settings_page():
|
||||
st.title("Settings")
|
||||
@ -100,7 +101,7 @@ def load_settings():
|
||||
# Default settings
|
||||
return {
|
||||
"system_prompt": SYSTEM_PROMPT,
|
||||
"input_template": INPUT_TEMPLATE,
|
||||
"input_template": INPUT_EXAMPLE,
|
||||
"prompt_template": PROMPT_TEMPLATE,
|
||||
"num_key_results": 4,
|
||||
"team_members": ["Khanh Dinh", "Robin Plitzko", "Roberto Renna"],
|
||||
|
||||
0
ui/__init__.py
Normal file
0
ui/__init__.py
Normal file
24
ui/parameters.py
Normal file
24
ui/parameters.py
Normal file
@ -0,0 +1,24 @@
|
||||
import streamlit as st
|
||||
from config.config import cycle_definitions
|
||||
|
||||
def section_parameters():
|
||||
st.subheader(body='Parameters for the OKR')
|
||||
|
||||
# Requested Parameter - Number of Key Results
|
||||
num_key_results = st.number_input(
|
||||
label='Please provide the number of key results',
|
||||
min_value=1,
|
||||
max_value=5,
|
||||
key='num_key_results',
|
||||
value=3
|
||||
)
|
||||
|
||||
# Requested Parameter - OKR Cycle
|
||||
options = [f"{key} ({value})" for key, value in cycle_definitions.items()]
|
||||
okr_cycle = st.segmented_control(
|
||||
label="Please select the OKR cycle",
|
||||
options=options,
|
||||
selection_mode="single",
|
||||
default=options[0]
|
||||
)
|
||||
st.session_state['okr_cycle'] = okr_cycle
|
||||
12
utils.py
12
utils.py
@ -3,8 +3,16 @@ import streamlit as st
|
||||
import re
|
||||
|
||||
# Function to construct the prompt
|
||||
def construct_prompt(prompt_template: str, user_input: str) -> str:
|
||||
return prompt_template.format(user_input=user_input)
|
||||
def construct_prompt(
|
||||
prompt_template: str,
|
||||
user_input: str,
|
||||
okr_cycle: str = 'JAN 25 to APR 25',
|
||||
num_key_results: int = 3 ) -> str:
|
||||
|
||||
return prompt_template.format(
|
||||
user_input=user_input,
|
||||
okr_cycle=okr_cycle,
|
||||
num_key_results=num_key_results)
|
||||
|
||||
|
||||
def parse_json_content(cleaned_content: str):
|
||||
|
||||
Loading…
Reference in New Issue
Block a user