|
import os |
|
|
|
from langchain.agents import AgentType, initialize_agent |
|
import gradio as gr |
|
|
|
import pandas as pd |
|
from collections import Counter |
|
from openai import AzureOpenAI |
|
import time |
|
import re |
|
|
|
|
|
structured_memory = { |
|
"π¨βπΌ Scrum Master": {}, |
|
"π‘ Product Owner": {}, |
|
"π¨βπ» Developer": {}, |
|
"π¨ Designer": {}, |
|
} |
|
selected_items = [] |
|
|
|
def prepare_model(selected_model): |
|
if selected_model == 'o4-mini': |
|
client = AzureOpenAI( |
|
api_version="2024-12-01-preview", |
|
azure_endpoint="https://nextgenagilehu4401821853.openai.azure.com/", |
|
api_key="2ziHxIi2Pz511IscFVVjBpgHkm2nDXNfPAvXyFWpsmCHlpHwAOuJJQQJ99BEACHYHv6XJ3w3AAAAACOGmC8m" |
|
) |
|
elif selected_model == 'o3-mini': |
|
client = AzureOpenAI( |
|
api_version="2024-12-01-preview", |
|
azure_endpoint="https://nextgenagilehu4401821853.openai.azure.com/", |
|
api_key="2ziHxIi2Pz511IscFVVjBpgHkm2nDXNfPAvXyFWpsmCHlpHwAOuJJQQJ99BEACHYHv6XJ3w3AAAAACOGmC8m" |
|
) |
|
return client |
|
|
|
def clear_selections(): |
|
global selected_items |
|
selected_items.clear() |
|
return "" |
|
|
|
def add_selection(option): |
|
global selected_items |
|
selected_items += [option] |
|
flat_list = [item for sublist in selected_items for item in sublist] |
|
counts = Counter(flat_list) |
|
formatted_output = ", ".join(f"{count} {option.lower()}" for option, count in counts.items()) |
|
return formatted_output |
|
|
|
|
|
persona_prompts = { |
|
"π¨βπΌ Scrum Master": "You are an experienced Scrum Master responsible for creating detailed JIRA tickets across parameters like EPIC, Feature, Story, Tasks, Subtasks, assignee based on job designation,sprint and story points", |
|
"π‘ Product Owner": "You are a Product Owner focused on defining product features, value delivery, and aligning JIRA tickets with business outcomes. Depending on requirements you can focus upon these aspects: Description,Business Context,User Value,Scope,Out of Scope,Dependencies,Acceptance Criteria,Definition of Done,User Impact Metrics,Next Steps", |
|
"π¨βπ» Developer": "You are a Software Developer breaking down technical objectives into implementation tasks, bug fixes, and engineering subtasks.Depending on requirements you can focus upon these aspects: Description, Acceptance Criteria, Technical Details:Frontend,Backend,Database,Integrations,Logging & Monitoring, Component/s, Definition of Done, Sub-tasks,Story Points", |
|
"π¨ Designer": "You are a UX/UI Designer structuring JIRA tickets around user flows, UI components, and design assets." |
|
} |
|
|
|
|
|
persona_default_prompts = { |
|
"π¨βπΌ Scrum Master": "Objective: Automate JIRA story creation for a new agile project", |
|
"π‘ Product Owner": "Objective: Define user stories for a travel booking feature", |
|
"π¨βπ» Developer": "Objective: Break down the user login system into dev tasks", |
|
"π¨ Designer": "Objective: Create tasks for designing the homepage UI" |
|
} |
|
|
|
model_select = { |
|
"O-4 Mini": "o4-mini", |
|
"O-3 Mini" : "o3-mini" |
|
} |
|
|
|
def process_files(message, chat_history, persona,model): |
|
selected_model = model_select.get(model) |
|
client = prepare_model(selected_model) |
|
system_prompt = persona_prompts.get(persona) |
|
memory = structured_memory[persona] |
|
|
|
if message.lower().startswith("objective:"): |
|
objective = message.split(":", 1)[-1].strip() |
|
if len(selected_items) > 0: |
|
flat_list = [item for sublist in selected_items for item in sublist] |
|
counts = Counter(flat_list) |
|
formatted_output = ", ".join(f"{count} {option.lower()}" for option, count in counts.items()) |
|
full_prompt = f"Create a complete JIRA ticket for the {objective} where your team structure is: {formatted_output}" |
|
else: |
|
full_prompt = f"Create a complete JIRA ticket for the {objective}" |
|
|
|
chat_response = client.chat.completions.create( |
|
messages=[ |
|
{"role": "system", "content": system_prompt}, |
|
{"role": "user", "content": full_prompt} |
|
], |
|
max_completion_tokens=100000, |
|
model=selected_model |
|
) |
|
bot_message = chat_response.choices[0].message.content |
|
memory["current"] = bot_message |
|
|
|
elif any(keyword in message.lower() for keyword in ["improve", "update", "change"]): |
|
if "current" not in memory: |
|
bot_message = "Please provide a project objective first using 'Objective: <your project>'." |
|
else: |
|
previous_output = memory["current"] |
|
improvement_prompt = f"Improve the following JIRA ticket structure based on the user's instruction.\n\nStructure:\n{previous_output}\n\nUser Request:\n{message}" |
|
chat_response = client.chat.completions.create( |
|
messages=[ |
|
{"role": "system", "content": system_prompt}, |
|
{"role": "user", "content": improvement_prompt} |
|
], |
|
max_completion_tokens=100000, |
|
model=selected_model |
|
) |
|
bot_message = chat_response.choices[0].message.content |
|
memory["current"] = bot_message |
|
else: |
|
bot_message = "Please start with 'Objective: <project>' or a request to update something." |
|
|
|
chat_history.append({"role": "user", "content": message}) |
|
chat_history.append({"role": "assistant", "content": bot_message}) |
|
time.sleep(1) |
|
return "", chat_history |
|
|
|
def insert_prefix(prefix_text, textbox_content): |
|
if not textbox_content.lower().startswith(prefix_text.lower()): |
|
return f"{prefix_text} {textbox_content}" |
|
else: |
|
return textbox_content |
|
|
|
def set_default_prompt(persona): |
|
return persona_default_prompts.get(persona, "") |
|
|
|
|
|
with gr.Blocks() as demo: |
|
with gr.Row(): |
|
with gr.Column(scale=1): |
|
gr.Image("/afh/projects/NextGenAgileTool-aefe44c3-e188-4674-9bd7-fd55842e362e/data/logo-removebg-preview.png", width=135, height=100,show_download_button=False , container= False,show_fullscreen_button=False, show_label=False) |
|
|
|
gr.Markdown("### π½ Choose Model") |
|
|
|
model = gr.Dropdown( |
|
choices=[ |
|
"O-4 Mini", |
|
"O-3 Mini" |
|
], |
|
value="", |
|
label="" |
|
) |
|
|
|
gr.Markdown("### π§ Choose Persona") |
|
|
|
persona = gr.Dropdown( |
|
choices=[ |
|
"π¨βπΌ Scrum Master", |
|
"π‘ Product Owner", |
|
"π¨βπ» Developer", |
|
"π¨ Designer" |
|
], |
|
value="π¨βπΌ Scrum Master", |
|
label="π§ Persona" |
|
) |
|
|
|
with gr.Column(scale=9): |
|
|
|
chatbot = gr.Chatbot( |
|
label="Chat History", |
|
type="messages", |
|
height=500, |
|
value=[ |
|
{"role": "assistant", "content": "Hello! π Start with an 'Objective' or ask to 'Improve' an earlier ticket."} |
|
] |
|
) |
|
|
|
with gr.Row(): |
|
objective_btn = gr.Button("β‘οΈ Objective") |
|
improve_btn = gr.Button("βοΈ Improve") |
|
update_btn = gr.Button("β»οΈ Update") |
|
change_btn = gr.Button("π Change") |
|
|
|
with gr.Row(): |
|
msg = gr.Textbox( |
|
placeholder="Type your request here...", |
|
label="Your Prompt", |
|
lines=2, |
|
submit_btn=True |
|
) |
|
|
|
clear = gr.ClearButton([msg, chatbot]) |
|
|
|
|
|
msg.submit(process_files, [msg, chatbot, persona,model], [msg, chatbot]) |
|
persona.change(set_default_prompt, persona, msg) |
|
|
|
objective_btn.click(insert_prefix, inputs=[gr.State("Objective:"), msg], outputs=msg) |
|
improve_btn.click(insert_prefix, inputs=[gr.State("Improve:"), msg], outputs=msg) |
|
update_btn.click(insert_prefix, inputs=[gr.State("Update:"), msg], outputs=msg) |
|
change_btn.click(insert_prefix, inputs=[gr.State("Change:"), msg], outputs=msg) |
|
|
|
|
|
|
|
|
|
|
|
server_info = demo.launch(share=True) |
|
|
|
|
|
match = re.search(r"Running on public URL: (https?://[^\s]+)", server_info) |
|
public_url = match.group(1) if match else "URL not found" |
|
|
|
|
|
with open("gradio_link.txt", "w") as f: |
|
f.write(public_url) |
|
|