Mihai Băluță-Cujbă
Update "About" section in UI to clarify functionality and usage of the AI Technical Initiative Generator
bc4eb34
from __future__ import annotations
import base64
import json
from typing import Any, Dict, List, Optional
import gradio as gr
import numpy as np
from .agent import InitiativeAgent
from .connectors.base import ConnectorConfig
from .connectors.http import HTTPConnector
from .connectors.upload import UploadConnector
from .embeddings import embed_texts
from .prompts import DEFAULT_CATEGORIES
from .storage import (
Document,
append_to_index,
ensure_data_dir,
load_connections,
save_connections,
)
def _conn_to_row(c: Dict[str, Any]) -> List[str]:
return [c.get("name", "(unnamed)"), c.get("type", "?"), json.dumps(c.get("params", {}))[:80]]
def build_ui() -> gr.Blocks:
ensure_data_dir()
agent = InitiativeAgent()
with gr.Blocks(theme=gr.themes.Soft()) as demo:
gr.Markdown("""
# AI-Powered Technical Initiative Generator
Transform a business objective into a pragmatic, categorized initiative plan.
""")
with gr.Tab("Generate Initiatives"):
obj = gr.Textbox(label="Business Objective", placeholder="e.g., Reduce customer churn by 10%", lines=3)
with gr.Row():
use_internal = gr.Checkbox(value=True, label="Use Data Sources")
use_web = gr.Checkbox(value=False, label="Use Web Research")
with gr.Row():
cats = gr.CheckboxGroup(
choices=DEFAULT_CATEGORIES,
value=DEFAULT_CATEGORIES,
label="Categories",
)
num_per = gr.Slider(1, 5, value=3, step=1, label="Initiatives per Category")
constraints = gr.Textbox(label="Constraints (optional)", placeholder="comma-separated constraints", lines=2)
run = gr.Button("Generate", variant="primary")
with gr.Row():
out_md = gr.Markdown(label="Plan", elem_id="output-md")
with gr.Accordion("Details", open=False):
dbg = gr.Textbox(label="Debug Prompt", lines=6)
ctx = gr.JSON(label="Generation Context")
def _on_generate(o, ui, ui_flag, uw_flag, cs, n):
parsed_constraints = [c.strip() for c in (cs or "").split(",") if c.strip()]
res = agent.generate(
objective=o,
categories=ui,
use_internal=bool(ui_flag),
use_web=bool(uw_flag),
constraints=parsed_constraints,
num_per_category=int(n),
)
return res["output_markdown"], res["prompt"], {
"used_internal": res["used_internal"],
"used_web": res["used_web"],
"context_count": res["context_count"],
}
# Note: order of args must match function
run.click(_on_generate, [obj, cats, use_internal, use_web, constraints, num_per], [out_md, dbg, ctx])
with gr.Tab("Data Sources"):
gr.Markdown("Add and manage connections to multiple data sources.")
with gr.Row():
table = gr.Dataframe(
headers=["Name", "Type", "Params"],
value=[_conn_to_row(c) for c in load_connections()],
interactive=False,
label="Configured Connections",
row_count=(len(load_connections()) or 1),
col_count=(3),
)
with gr.Row():
with gr.Column():
mode = gr.Radio(["Upload", "URL"], value="Upload", label="Connection Type")
name = gr.Textbox(label="Name", placeholder="e.g., Support CSV")
upload = gr.File(label="Upload (CSV/JSON/TXT)", file_types=[".csv", ".json", ".txt"], type="filepath", visible=True)
url = gr.Textbox(label="URL", visible=False)
auth = gr.Dropdown(["none", "basic", "bearer"], value="none", label="Auth", visible=False)
username = gr.Textbox(label="Username", visible=False)
password = gr.Textbox(label="Password", type="password", visible=False)
token = gr.Textbox(label="Token", type="password", visible=False)
add_btn = gr.Button("Add Source", variant="primary")
def _toggle_fields(m):
if m == "Upload":
return (
gr.update(visible=True), # upload
gr.update(visible=False), # url
gr.update(visible=False), # auth
gr.update(visible=False), # username
gr.update(visible=False), # password
gr.update(visible=False), # token
)
else:
return (
gr.update(visible=False), # upload
gr.update(visible=True), # url
gr.update(visible=True), # auth
gr.update(visible=True), # username
gr.update(visible=True), # password
gr.update(visible=True), # token
)
mode.change(_toggle_fields, [mode], [upload, url, auth, username, password, token])
def _add_source(m, n, f, u, a, un, pw, tk):
conns = load_connections()
if m == "Upload":
if f is None:
raise gr.Error("Please upload a file.")
# f is a filepath
import os, mimetypes
filename = os.path.basename(f)
with open(f, "rb") as fh:
content = fh.read()
mime = mimetypes.guess_type(filename)[0] or "text/plain"
cfg = ConnectorConfig(
type="upload",
name=n or filename,
params={
"filename": filename,
"mime": mime,
"content": content,
},
)
docs = UploadConnector(cfg).fetch()
else:
if not u:
raise gr.Error("Please provide a URL.")
cfg = ConnectorConfig(
type="http",
name=n or u,
params={
"url": u,
"auth_type": a or "none",
"username": un or "",
"password": pw or "",
"token": tk or "",
},
)
docs = HTTPConnector(cfg).fetch()
# Embed and append
vectors = embed_texts([d.text for d in docs])
append_to_index(docs, vectors)
# Save connection (without raw content)
safe_params = dict(cfg.params)
if safe_params.get("content"):
safe_params["content"] = f"<bytes:{len(safe_params['content'])}>"
conns.append({"type": cfg.type, "name": cfg.name, "params": safe_params})
save_connections(conns)
return [
_conn_to_row(c) for c in conns
], gr.update(row_count=len(conns))
add_btn.click(
_add_source,
[mode, name, upload, url, auth, username, password, token],
[table, table],
)
with gr.Tab("About"):
gr.Markdown(
"""
### About: AI Technical Initiative Generator
This tool transforms a business objective into a categorized, actionable initiative plan for engineering leaders.
- Connect data sources (CSV/JSON uploads or URLs with Basic/Bearer auth) to ground outputs in your context.
- Optionally enable web research to incorporate recent, real‑world insights.
- Choose which categories to include and how many initiatives per category.
- Each initiative includes: Why now, Expected impact metric, and Effort.
Notes: Avoid uploading sensitive data to public Spaces. Enable Internet in Space settings to use web research and URL connectors.
"""
)
return demo