iT邦幫忙

2026 iThome 鐵人賽

DAY 14
0
AI 自動化

AaaS from Scratch: 從一次性定義,到規模化分析系列 第 14 篇

[Dat 14] Data Upload 與 HTML Report

  • 分享至 

  • xImage
  •  

[Day 14] Data Upload 與 HTML Report

上一篇我們把 Chat UI 接上 Agent,加入 streaming,也讓每個 conversation 可以 reuse 自己的 sandbox。

今天補上 frontend 的另外兩個部分:

  1. 讓 user upload 自己的 dataset。
  2. 讓 Agent 產生的 HTML report 可以直接在 conversation 裡看到。

Upload Data

Frontend 有一個 Data page,讓 user upload 自己的 dataset。

目前的 flow 大概是:

CSV / Parquet
    ↓
Polars Parse
    ↓
Preview
    ↓
Infer Data Types
    ↓
Save

Upload 之後,backend 會先用 Polars parse,讓 user 看到:

  • columns
  • inferred data types
  • sample rows

確認之後,再決定怎麼保存。

Data page

這裡可以看到除了前面一直使用的 videos dataset,也可以加入 user 自己 upload 的資料,例如 bookstore_sales。

Table 還是 File?

目前有兩種方式:

Save as Agent 怎麼使用
Database Table SQL:query_database / export_query
Parquet File Sandbox 裡直接用 Polars

兩種方式處理不同需求:

Database Table
→ query
→ filtering
→ aggregation

Parquet File
→ sandbox analysis
→ Polars
→ larger processing

Frontend 做的不只是「上傳檔案」。

真正要做的是把 user upload 的 data 變成 Agent 可以使用的 datasource。

Agent 自己 Discover Dataset

前面幾篇我們一直假設 database 裡只有:

videos

但開始允許 user upload 之後,這個假設就不存在了。

Agent 需要自己知道:

現在有哪些 datasets?
有哪些 columns?
data type 是什麼?

所以加入一個:

list_datasets()

Conceptually:

Agent
  ↓
list_datasets()
  ↓
videos
bookstore_sales
uploaded_xxx

這樣新增 dataset 時,不需要一直修改 system prompt。

Agent 可以先 discover 現在有哪些 datasource,再決定下一步怎麼分析。

Agent-generated HTML

有 data 之後,接下來就是 result 怎麼呈現。

Agent 現在可以在 sandbox 裡產生:

report.html

例如包含:

  • summary
  • metrics
  • tables
  • charts
  • observations

有些問題只需要簡單 chart:

Generated chart

而有些 analysis 會產生完整的 HTML report。

Backend execution 結束後,會把 artifact 從 sandbox 拉回來,再透過:

/api/artifacts/...

提供給 frontend。

Chat UI 就可以直接把 report render 在 conversation 裡。

HTML report in conversation

整個 flow 變成:

User Question
    ↓
Agent
    ↓
Analysis
    ↓
Sandbox
    ↓
report.html
    ↓
Backend
    ↓
Frontend

這也開始接近一開始對 Analysis output 的想像。

不是只有:

Agent
→ Markdown Answer

而是:

Agent
→ Analysis
→ HTML Report

為什麼是 HTML?

HTML 適合這個 project 的原因在於 output 不一定只是文字。

可能同時需要:

Text
Table
Chart
Layout
Interactive Visualization

如果只回 Markdown,presentation ability 會比較受限。

HTML 則可以讓 Agent 根據不同 analysis result,自由組合 report structure。

例如同一個 Analysis 套到不同 dataset:

Same Analysis
+ US Data
→ US Report

Same Analysis
+ Germany Data
→ Germany Report

Report 的 layout 可以類似,但真正的 findings、charts 和 observations 會跟著 data 改變。

所以我們保存的不是一份固定 HTML template。

HTML 是每次 execution 產生的 artifact。

但 HTML 不能直接相信

這裡會遇到跟之前很像的問題。

Before:

Untrusted Python
→ 不要直接跑在 Backend

今天則是:

Untrusted HTML / JavaScript
→ 不要直接跑在 Application Origin

因為這份 HTML 是 model-generated HTML。

它可能包含 JavaScript,例如 Plotly。

如果直接跟 application 用同一個 origin 執行:

Model-written JavaScript
        ↓
Same Origin
        ↓
可能存取 Storage / Cookies / API

這不是我們想要的。

所以這些 HTML 一樣要被視為 untrusted content。

Browser Sandbox

Frontend 使用:

<iframe
  src={artifact.url}
  sandbox="allow-scripts"
  referrerPolicy="no-referrer"
/>

這裡允許:

allow-scripts

因為 report 裡面的 chart library 可能需要 JavaScript。

但刻意沒有:

allow-same-origin

所以 report 可以執行自己的 script,但不會拿到 application origin 的權限。

Conceptually:

report.html
    ↓
Sandboxed iframe
    ↓
Can run its own JS
    ↓
Cannot act as the application

第二層保護

只靠 iframe 還不夠。

因為 user 也可能直接點:

Open ↗

把 artifact 單獨打開。

所以 backend 回傳 artifact 時,也加上:

Content-Security-Policy: sandbox allow-scripts
X-Content-Type-Options: nosniff

變成兩層:

Inside App
→ iframe sandbox

Direct Open
→ CSP sandbox

這樣即使 report 被單獨打開,本身還是 isolated。

Direct-open sandboxed report

Markdown Answer 跟 HTML Report 分開

Agent 的一般回答不需要支援 arbitrary HTML。

所以 normal answer 走:

Agent Text
→ react-markdown

而且不 render raw HTML。

例如 Agent 回:

<img src=x onerror="...">

Frontend 不會直接把它當成 executable HTML。

HTML report 則走另外一條 path:

Agent Text
→ Markdown Renderer

Agent Report
→ Sandboxed iframe

我會把這兩種 content 分開處理,而不是全部丟給同一個 renderer。

跟 Day 12 是同一個 Principle

前一篇我們處理的是:

Agent-generated Python
→ Execution Sandbox

今天處理的是:

Agent-generated HTML
→ Browser Sandbox

背後其實是同一件事:

Model-generated content 不應該因為「是 Agent 產生的」就被當成 trusted content。

Takeaway

到這裡,user flow 已經開始完整:

Upload Data
    ↓
Discover Dataset
    ↓
Chat with Agent
    ↓
Sandbox Analysis
    ↓
Generate HTML Report
    ↓
Render in Frontend

Frontend 本身不是這個系列的核心。

它的作用是把前面做好的:

Datasource
Agent
Skills
Sandbox
Artifacts

組成一個 user 真正可以操作的 workflow。

現在 user 已經可以:

Upload Data
→ Ask Question
→ Run Analysis
→ See Report

上一篇
[Day 13] Frontend:Streaming 與 Conversation
下一篇
[Day 15] 用 Jev 來做 Skill Routing
系列文
AaaS from Scratch: 從一次性定義,到規模化分析 共 17 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言