CoolFace
Apppublic

supercode168/enterprise-workflow-ai-agent

sourceHugging Facemitupdated 4mo agoView on Hugging Face
0likes
app.py312 linesDownload Raw Back to root
1from __future__ import annotations2 3import html4import json5import sys6from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer7from pathlib import Path8from urllib.parse import parse_qs, urlparse9 10from agent_core import (11    dashboard_metrics,12    investment_research_workflow,13    load_csv,14    SAMPLE_CSV,15    compliance_review_workflow,16    triage,17)18 19 20HOST = "127.0.0.1"21PORT = 876522 23 24def page_shell(body: str) -> bytes:25    return f"""<!doctype html>26<html lang="en">27<head>28  <meta charset="utf-8">29  <meta name="viewport" content="width=device-width, initial-scale=1">30  <title>Enterprise Workflow AI Agent</title>31  <style>32    :root {{33      --ink: #172033;34      --muted: #627089;35      --line: #dbe3ef;36      --fill: #f6f8fb;37      --accent: #2266cc;38      --accent-dark: #174a93;39      --warn: #9b5a00;40      --good: #146c43;41    }}42    * {{ box-sizing: border-box; }}43    body {{44      margin: 0;45      font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Arial, sans-serif;46      color: var(--ink);47      background: #ffffff;48    }}49    header {{50      border-bottom: 1px solid var(--line);51      padding: 22px 32px 18px;52    }}53    h1 {{ margin: 0 0 6px; font-size: 28px; letter-spacing: 0; }}54    h2 {{ margin: 28px 0 12px; font-size: 18px; }}55    p {{ line-height: 1.5; }}56    .sub {{ color: var(--muted); margin: 0; }}57    main {{ max-width: 1180px; margin: 0 auto; padding: 22px 28px 40px; }}58    .grid {{ display: grid; gap: 16px; }}59    .metrics {{ grid-template-columns: repeat(4, minmax(0, 1fr)); }}60    .two {{ grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }}61    .card {{62      border: 1px solid var(--line);63      border-radius: 8px;64      padding: 16px;65      background: #fff;66    }}67    .metric-value {{ font-size: 28px; font-weight: 700; color: var(--accent-dark); }}68    .metric-label {{ color: var(--muted); font-size: 13px; margin-top: 4px; }}69    textarea {{70      width: 100%;71      min-height: 118px;72      padding: 12px;73      border: 1px solid var(--line);74      border-radius: 6px;75      font: inherit;76      resize: vertical;77    }}78    button {{79      margin-top: 10px;80      border: 0;81      border-radius: 6px;82      padding: 10px 14px;83      background: var(--accent);84      color: #fff;85      font-weight: 650;86      cursor: pointer;87    }}88    button:hover {{ background: var(--accent-dark); }}89    table {{ width: 100%; border-collapse: collapse; font-size: 14px; }}90    th, td {{ border-bottom: 1px solid var(--line); padding: 9px 8px; text-align: left; vertical-align: top; }}91    th {{ color: var(--muted); font-weight: 650; background: var(--fill); }}92    .pill {{ display: inline-block; padding: 3px 8px; border-radius: 999px; background: var(--fill); border: 1px solid var(--line); font-size: 12px; }}93    .high, .emergency {{ color: #8a1f11; font-weight: 700; }}94    .medium {{ color: var(--warn); font-weight: 700; }}95    .low {{ color: var(--good); font-weight: 700; }}96    ul {{ padding-left: 22px; }}97    @media (max-width: 840px) {{98      header {{ padding: 18px; }}99      main {{ padding: 18px; }}100      .metrics, .two {{ grid-template-columns: 1fr; }}101    }}102  </style>103</head>104<body>105  <header>106    <h1>Enterprise Workflow AI Agent</h1>107    <p class="sub">Service operations copilot: triage, retrieval, checklist generation, tenant reply drafting, and dashboarding.</p>108  </header>109  <main>{body}</main>110</body>111</html>""".encode("utf-8")112 113 114def render_dashboard(result=None, query_text: str = "") -> bytes:115    metrics = dashboard_metrics()116    categories = "".join(117        f"<tr><td>{html.escape(str(k))}</td><td>{v}</td></tr>" for k, v in metrics["by_category"][:8]118    )119    boroughs = "".join(120        f"<tr><td>{html.escape(str(k))}</td><td>{v}</td></tr>" for k, v in metrics["by_borough"][:8]121    )122    recent = "".join(123        "<tr>"124        f"<td>{html.escape(str(t['ticket_id']))}</td>"125        f"<td>{html.escape(str(t['complaint_type']))}</td>"126        f"<td>{html.escape(str(t['descriptor']))}</td>"127        f"<td>{html.escape(str(t['borough']))}</td>"128        f"<td>{html.escape(str(t['response_hours']))}</td>"129        "</tr>"130        for t in metrics["recent_tickets"]131    )132    result_html = ""133    if result:134        cases = "".join(135            "<tr>"136            f"<td>{html.escape(c['ticket_id'])}</td>"137            f"<td>{html.escape(c['complaint_type'])}</td>"138            f"<td>{html.escape(c['descriptor'])}</td>"139            f"<td>{html.escape(c['resolution_description'])}</td>"140            f"<td>{c['similarity']}</td>"141            "</tr>"142            for c in result.similar_cases143        )144        checklist = "".join(f"<li>{html.escape(item)}</li>" for item in result.checklist)145        missing = ", ".join(result.missing_information) if result.missing_information else "None"146        result_html = f"""147        <section class="card">148          <h2>Triage Result</h2>149          <p><span class="pill">Category</span> {html.escape(result.category)}150          &nbsp; <span class="pill">Urgency</span> <span class="{result.urgency}">{html.escape(result.urgency)}</span>151          &nbsp; <span class="pill">Team</span> {html.escape(result.responsible_team)}</p>152          <p><strong>Suggested next action:</strong> {html.escape(result.suggested_next_action)}</p>153          <p><strong>Missing information:</strong> {html.escape(missing)}</p>154          <h2>Technician Checklist</h2>155          <ul>{checklist}</ul>156          <h2>Tenant Reply Draft</h2>157          <p>{html.escape(result.tenant_reply)}</p>158          <h2>Similar Historical Cases</h2>159          <table><thead><tr><th>ID</th><th>Type</th><th>Descriptor</th><th>Resolution</th><th>Score</th></tr></thead><tbody>{cases}</tbody></table>160        </section>161        """162    body = f"""163    <section class="grid metrics">164      <div class="card"><div class="metric-value">{metrics["total_tickets"]}</div><div class="metric-label">Tickets in database</div></div>165      <div class="card"><div class="metric-value">{metrics["avg_response_hours"]}</div><div class="metric-label">Average response hours</div></div>166      <div class="card"><div class="metric-value">{len(metrics["by_category"])}</div><div class="metric-label">Complaint categories</div></div>167      <div class="card"><div class="metric-value">3</div><div class="metric-label">Enterprise scenarios planned</div></div>168    </section>169 170    <section class="card">171      <h2>Ticket Intake</h2>172      <form method="post" action="/triage">173        <textarea name="text" placeholder="Example: Tenant reports no hot water in unit 12B since this morning. There is a baby in the apartment.">{html.escape(query_text)}</textarea>174        <button type="submit">Run Triage</button>175      </form>176    </section>177 178    {result_html}179 180    <section class="grid two">181      <div class="card">182        <h2>Ticket Volume by Category</h2>183        <table><thead><tr><th>Category</th><th>Count</th></tr></thead><tbody>{categories}</tbody></table>184      </div>185      <div class="card">186        <h2>Ticket Volume by Borough</h2>187        <table><thead><tr><th>Borough</th><th>Count</th></tr></thead><tbody>{boroughs}</tbody></table>188      </div>189    </section>190 191    <section class="card">192      <h2>Recent Tickets</h2>193      <table><thead><tr><th>ID</th><th>Type</th><th>Descriptor</th><th>Borough</th><th>Response Hours</th></tr></thead><tbody>{recent}</tbody></table>194    </section>195    """196    return page_shell(body)197 198 199def render_document_workflow(kind: str, result=None, text: str = "") -> bytes:200    if kind == "investment":201        title = "Investment Research Copilot"202        subtitle = "Paste annual-report, company, market, or fund notes to generate an analyst-ready first pass."203        action = "/investment"204        placeholder = "Paste company report text, market notes, or fund description..."205    else:206        title = "Compliance Review Copilot"207        subtitle = "Paste contract, policy, or procedure text to extract obligations, risk flags, and review checklist."208        action = "/compliance"209        placeholder = "Paste contract or compliance policy text..."210 211    result_html = ""212    if result:213        fields = "".join(214            f"<tr><td>{html.escape(str(k))}</td><td>{html.escape(json.dumps(v, ensure_ascii=False))}</td></tr>"215            for k, v in result.extracted_fields.items()216        )217        risks = "".join(f"<li>{html.escape(item)}</li>" for item in result.risk_flags) or "<li>No obvious risk flags found in this short sample.</li>"218        checklist = "".join(f"<li>{html.escape(item)}</li>" for item in result.action_checklist)219        result_html = f"""220        <section class="card">221          <h2>Workflow Output</h2>222          <p><span class="pill">Workflow</span> {html.escape(result.workflow_type)}</p>223          <h2>Executive Summary</h2>224          <p>{html.escape(result.summary)}</p>225          <h2>Extracted Fields</h2>226          <table><thead><tr><th>Field</th><th>Value</th></tr></thead><tbody>{fields}</tbody></table>227          <h2>Risk Flags</h2>228          <ul>{risks}</ul>229          <h2>Action Checklist</h2>230          <ul>{checklist}</ul>231          <h2>Stakeholder Draft</h2>232          <p>{html.escape(result.stakeholder_draft)}</p>233        </section>234        """235 236    body = f"""237    <section class="card">238      <p><a href="/">Service Operations</a> · <a href="/investment">Investment Research</a> · <a href="/compliance">Compliance Review</a></p>239      <h2>{title}</h2>240      <p>{subtitle}</p>241      <form method="post" action="{action}">242        <textarea name="text" placeholder="{html.escape(placeholder)}">{html.escape(text)}</textarea>243        <button type="submit">Run Workflow</button>244      </form>245    </section>246    {result_html}247    """248    return page_shell(body)249 250 251class Handler(BaseHTTPRequestHandler):252    def _send(self, data: bytes, content_type: str = "text/html; charset=utf-8") -> None:253        self.send_response(200)254        self.send_header("Content-Type", content_type)255        self.send_header("Content-Length", str(len(data)))256        self.end_headers()257        self.wfile.write(data)258 259    def do_GET(self) -> None:260        parsed = urlparse(self.path)261        if parsed.path == "/api/triage":262            text = parse_qs(parsed.query).get("text", [""])[0]263            result = triage(text)264            data = json.dumps(result.to_dict(), indent=2).encode("utf-8")265            self._send(data, "application/json; charset=utf-8")266            return267        if parsed.path == "/api/investment":268            text = parse_qs(parsed.query).get("text", [""])[0]269            data = json.dumps(investment_research_workflow(text).to_dict(), indent=2).encode("utf-8")270            self._send(data, "application/json; charset=utf-8")271            return272        if parsed.path == "/api/compliance":273            text = parse_qs(parsed.query).get("text", [""])[0]274            data = json.dumps(compliance_review_workflow(text).to_dict(), indent=2).encode("utf-8")275            self._send(data, "application/json; charset=utf-8")276            return277        if parsed.path == "/investment":278            self._send(render_document_workflow("investment"))279            return280        if parsed.path == "/compliance":281            self._send(render_document_workflow("compliance"))282            return283        self._send(render_dashboard())284 285    def do_POST(self) -> None:286        length = int(self.headers.get("Content-Length", "0"))287        raw = self.rfile.read(length).decode("utf-8")288        text = parse_qs(raw).get("text", [""])[0]289        if self.path == "/triage":290            self._send(render_dashboard(triage(text), text))291            return292        if self.path == "/investment":293            self._send(render_document_workflow("investment", investment_research_workflow(text), text))294            return295        if self.path == "/compliance":296            self._send(render_document_workflow("compliance", compliance_review_workflow(text), text))297            return298        self.send_error(404)299 300 301def main() -> None:302    if not Path("data/tickets.db").exists():303        load_csv(SAMPLE_CSV)304    port = int(sys.argv[1]) if len(sys.argv) > 1 else PORT305    server = ThreadingHTTPServer((HOST, port), Handler)306    print(f"Serving Enterprise Workflow AI Agent at http://{HOST}:{port}")307    server.serve_forever()308 309 310if __name__ == "__main__":311    main()312