| | import os |
| | import uuid |
| | from datetime import datetime, timezone |
| |
|
| | import gradio as gr |
| | from azure.cosmos import CosmosClient, PartitionKey |
| | from azure.cosmos.exceptions import CosmosHttpResponseError |
| | from dotenv import load_dotenv |
| |
|
| | load_dotenv() |
| |
|
| |
|
| | def _get_env(name: str) -> str: |
| | value = os.getenv(name, "").strip() |
| | return value |
| |
|
| |
|
| | def get_container(): |
| | endpoint = _get_env("COSMOS_ENDPOINT") |
| | key = _get_env("COSMOS_KEY") |
| | db_name = _get_env("COSMOS_DATABASE") |
| | container_name = _get_env("COSMOS_CONTAINER") |
| |
|
| | if not all([endpoint, key, db_name, container_name]): |
| | missing = [ |
| | k |
| | for k in [ |
| | "COSMOS_ENDPOINT", |
| | "COSMOS_KEY", |
| | "COSMOS_DATABASE", |
| | "COSMOS_CONTAINER", |
| | ] |
| | if not _get_env(k) |
| | ] |
| | raise ValueError( |
| | "Missing Cosmos configuration: " + ", ".join(missing) |
| | ) |
| |
|
| | client = CosmosClient(endpoint, credential=key) |
| | database = client.create_database_if_not_exists(id=db_name) |
| | container = database.create_container_if_not_exists( |
| | id=container_name, |
| | partition_key=PartitionKey(path="/id"), |
| | ) |
| | return container |
| |
|
| |
|
| | _container_cache = None |
| |
|
| |
|
| | def submit_feedback(name, team, assistant_type, submit_anonymous, do_text, dont_text): |
| | name = (name or "").strip() |
| | team = (team or "").strip() |
| | assistant_type = (assistant_type or "").strip() |
| | do_text = (do_text or "").strip() |
| | dont_text = (dont_text or "").strip() |
| |
|
| | if not do_text and not dont_text: |
| | return ( |
| | ( |
| | "<div style=\"padding:14px 16px;border-radius:8px;" |
| | "background:#ffe9e9;color:#7a1d1d;border:1px solid #f2bcbc;" |
| | "font-weight:600;\">Please enter a Dos or a Don'ts (or both) before submitting.</div>" |
| | ), |
| | gr.update(), |
| | gr.update(), |
| | gr.update(), |
| | gr.update(), |
| | gr.update(), |
| | gr.update(), |
| | ) |
| |
|
| | if submit_anonymous: |
| | name = "" |
| | team = "" |
| |
|
| | global _container_cache |
| | try: |
| | if _container_cache is None: |
| | _container_cache = get_container() |
| |
|
| | item = { |
| | "id": str(uuid.uuid4()), |
| | "created_at": datetime.now(timezone.utc).isoformat(), |
| | "name": name or None, |
| | "team": team or None, |
| | "assistant_type": assistant_type or None, |
| | "do": do_text or None, |
| | "dont": dont_text or None, |
| | } |
| | _container_cache.create_item(body=item) |
| | except ValueError as exc: |
| | return ( |
| | ( |
| | "<div style=\"padding:14px 16px;border-radius:8px;" |
| | "background:#ffe9e9;color:#7a1d1d;border:1px solid #f2bcbc;" |
| | f"font-weight:600;\">Configuration error: {exc}</div>" |
| | ), |
| | gr.update(), |
| | gr.update(), |
| | gr.update(), |
| | gr.update(), |
| | gr.update(), |
| | gr.update(), |
| | ) |
| | except CosmosHttpResponseError as exc: |
| | return ( |
| | ( |
| | "<div style=\"padding:14px 16px;border-radius:8px;" |
| | "background:#ffe9e9;color:#7a1d1d;border:1px solid #f2bcbc;" |
| | f"font-weight:600;\">Cosmos DB error: {exc.message}</div>" |
| | ), |
| | gr.update(), |
| | gr.update(), |
| | gr.update(), |
| | gr.update(), |
| | gr.update(), |
| | gr.update(), |
| | ) |
| | except Exception as exc: |
| | return ( |
| | ( |
| | "<div style=\"padding:14px 16px;border-radius:8px;" |
| | "background:#ffe9e9;color:#7a1d1d;border:1px solid #f2bcbc;" |
| | f"font-weight:600;\">Unexpected error: {exc}</div>" |
| | ), |
| | gr.update(), |
| | gr.update(), |
| | gr.update(), |
| | gr.update(), |
| | gr.update(), |
| | gr.update(), |
| | ) |
| |
|
| | return ( |
| | ( |
| | "<div style=\"padding:16px 18px;border-radius:10px;" |
| | "background:#e8f7ee;color:#0f5b2f;border:1px solid #bfe5cc;" |
| | "font-weight:700;font-size:16px;\">✅ Saved! Thanks for your feedback.</div>" |
| | ), |
| | gr.update(value=""), |
| | gr.update(value=""), |
| | gr.update(value="General"), |
| | gr.update(value=False), |
| | gr.update(value=""), |
| | gr.update(value=""), |
| | ) |
| |
|
| |
|
| | with gr.Blocks(title="AI Assistant Do/Don't Collection") as demo: |
| | gr.Markdown( |
| | "# AI Assistant Do/Don't Collection\n" |
| | "Share guidance for building our AI assistants. You can fill either field or both." |
| | ) |
| |
|
| | with gr.Row(): |
| | name_input = gr.Textbox(label="Your name (optional)", placeholder="Jane Doe") |
| | team_input = gr.Textbox(label="Team / Org (optional)", placeholder="Product, IT, ...") |
| | assistant_type_input = gr.Dropdown( |
| | label="Assistant type (optional)", |
| | choices=[ |
| | "General", |
| | "Resiliency Programs (WFPH, FORTIFIED, ..)", |
| | "Communication", |
| | "Code and Standards", |
| | "Internal Ops", |
| | "Research", |
| | ], |
| | value="General", |
| | ) |
| |
|
| | submit_anonymous_input = gr.Checkbox( |
| | label="Submit anonymously (ignore name and team)", |
| | value=False, |
| | ) |
| |
|
| | do_input = gr.Textbox( |
| | label="Dos", |
| | placeholder="What should we consider when creating AI assistants?", |
| | lines=6, |
| | ) |
| | dont_input = gr.Textbox( |
| | label="Don'ts", |
| | placeholder="What should we avoid when creating AI assistants?", |
| | lines=6, |
| | ) |
| |
|
| | submit_btn = gr.Button("Submit") |
| | status = gr.HTML() |
| |
|
| | submit_btn.click( |
| | fn=submit_feedback, |
| | inputs=[ |
| | name_input, |
| | team_input, |
| | assistant_type_input, |
| | submit_anonymous_input, |
| | do_input, |
| | dont_input, |
| | ], |
| | outputs=[ |
| | status, |
| | name_input, |
| | team_input, |
| | assistant_type_input, |
| | submit_anonymous_input, |
| | do_input, |
| | dont_input, |
| | ], |
| | ) |
| |
|
| |
|
| | if __name__ == "__main__": |
| | demo.launch() |
| |
|