|
1 | | --- Build daily feature metrics from DWD. |
| 1 | +-- Build hourly feature metrics from DWD using event-time windows. |
2 | 2 |
|
3 | | -INSERT INTO paimon_lake.dws.dws_ai_llm_feature_request_1d |
| 3 | +INSERT INTO paimon_lake.dws.dws_ai_llm_feature_request_1h |
4 | 4 | SELECT |
5 | | - `date`, |
| 5 | + CAST(window_start AS DATE) AS `date`, |
| 6 | + CAST(EXTRACT(HOUR FROM window_start) AS INT) AS `hour`, |
6 | 7 | app_name, |
7 | 8 | feature_name, |
8 | 9 | model_name, |
9 | | - COUNT(*) AS request_count, |
10 | | - SUM(CASE WHEN status = 'success' THEN 1 ELSE 0 END) AS success_count, |
11 | | - SUM(CASE WHEN status = 'error' THEN 1 ELSE 0 END) AS error_count, |
12 | | - SUM(prompt_tokens) AS prompt_tokens, |
13 | | - SUM(completion_tokens) AS completion_tokens, |
14 | | - SUM(total_tokens) AS total_tokens, |
15 | | - SUM(estimated_cost_usd) AS estimated_cost_usd, |
| 10 | + COUNT(*) AS request_cnt_1h, |
| 11 | + SUM(CASE WHEN status = 'success' THEN 1 ELSE 0 END) AS success_cnt_1h, |
| 12 | + SUM(CASE WHEN status = 'error' THEN 1 ELSE 0 END) AS error_cnt_1h, |
| 13 | + SUM(prompt_tokens) AS prompt_token_cnt_1h, |
| 14 | + SUM(completion_tokens) AS completion_token_cnt_1h, |
| 15 | + SUM(total_tokens) AS total_token_cnt_1h, |
| 16 | + SUM(estimated_cost_usd) AS estimated_cost_amt_1h, |
16 | 17 | AVG(latency_ms) AS avg_latency_ms, |
17 | | - -- Flink 1.20 SQL does not support PERCENTILE_CONT as a streaming aggregate. |
18 | | - -- Store an explicit upper-bound metric instead of naming MAX latency as p95. |
19 | 18 | CAST(MAX(latency_ms) AS BIGINT) AS max_latency_ms, |
20 | 19 | CAST(0 AS BIGINT) AS p95_latency_ms |
21 | | -FROM paimon_lake.dwd.dwd_ai_llm_request_di |
| 20 | +FROM TABLE( |
| 21 | + TUMBLE( |
| 22 | + TABLE paimon_lake.dwd.dwd_ai_llm_request_di, |
| 23 | + DESCRIPTOR(created_at), |
| 24 | + INTERVAL '1' HOUR |
| 25 | + ) |
| 26 | +) |
| 27 | +GROUP BY window_start, app_name, feature_name, model_name; |
| 28 | + |
| 29 | +-- Daily feature metrics roll up the hourly table so both grains share one definition. |
| 30 | + |
| 31 | +INSERT INTO paimon_lake.dws.dws_ai_llm_feature_request_1d |
| 32 | +SELECT |
| 33 | + `date`, |
| 34 | + app_name, |
| 35 | + feature_name, |
| 36 | + model_name, |
| 37 | + SUM(request_cnt_1h) AS request_count, |
| 38 | + SUM(success_cnt_1h) AS success_count, |
| 39 | + SUM(error_cnt_1h) AS error_count, |
| 40 | + SUM(prompt_token_cnt_1h) AS prompt_tokens, |
| 41 | + SUM(completion_token_cnt_1h) AS completion_tokens, |
| 42 | + SUM(total_token_cnt_1h) AS total_tokens, |
| 43 | + SUM(estimated_cost_amt_1h) AS estimated_cost_usd, |
| 44 | + SUM(avg_latency_ms * request_cnt_1h) / SUM(request_cnt_1h) AS avg_latency_ms, |
| 45 | + MAX(max_latency_ms) AS max_latency_ms, |
| 46 | + CAST(0 AS BIGINT) AS p95_latency_ms |
| 47 | +FROM paimon_lake.dws.dws_ai_llm_feature_request_1h |
22 | 48 | GROUP BY `date`, app_name, feature_name, model_name; |
23 | 49 |
|
24 | 50 | INSERT INTO paimon_lake.dws.dws_ai_retrieval_knowledge_base_request_1d |
@@ -129,3 +155,48 @@ SELECT |
129 | 155 | CAST(MAX(latency_ms) AS BIGINT) AS p95_latency_ms |
130 | 156 | FROM paimon_lake.dwd.dwd_ai_llm_request_di |
131 | 157 | GROUP BY `date`, region, environment, app_name, model_name; |
| 158 | + |
| 159 | +INSERT INTO paimon_lake.dws.dws_ai_llm_session_request_1d |
| 160 | +WITH session_metrics AS ( |
| 161 | + SELECT |
| 162 | + `date`, |
| 163 | + app_name, |
| 164 | + feature_name, |
| 165 | + session_id, |
| 166 | + COUNT(*) AS turn_cnt, |
| 167 | + SUM(total_tokens) AS token_cnt, |
| 168 | + TIMESTAMPDIFF(MILLISECOND, MIN(created_at), MAX(created_at)) + MAX(latency_ms) AS session_duration_ms |
| 169 | + FROM paimon_lake.dwd.dwd_ai_llm_request_di |
| 170 | + GROUP BY `date`, app_name, feature_name, session_id |
| 171 | +), |
| 172 | +resolved_sessions AS ( |
| 173 | + SELECT |
| 174 | + `date`, |
| 175 | + app_name, |
| 176 | + feature_name, |
| 177 | + session_id, |
| 178 | + MAX( |
| 179 | + CASE |
| 180 | + WHEN feedback_type = 'thumbs_up' OR (feedback_type = 'rating' AND rating_value >= 4) THEN 1 |
| 181 | + ELSE 0 |
| 182 | + END |
| 183 | + ) AS is_resolved |
| 184 | + FROM paimon_lake.dwd.dwd_ai_feedback_action_di |
| 185 | + GROUP BY `date`, app_name, feature_name, session_id |
| 186 | +) |
| 187 | +SELECT |
| 188 | + sessions.`date`, |
| 189 | + sessions.app_name, |
| 190 | + sessions.feature_name, |
| 191 | + COUNT(*) AS session_cnt_1d, |
| 192 | + AVG(sessions.turn_cnt) AS avg_turns_per_session, |
| 193 | + AVG(sessions.token_cnt) AS avg_tokens_per_session, |
| 194 | + AVG(sessions.session_duration_ms) AS avg_duration_per_session_ms, |
| 195 | + SUM(COALESCE(feedback.is_resolved, 0)) AS resolved_session_cnt_1d |
| 196 | +FROM session_metrics AS sessions |
| 197 | +LEFT JOIN resolved_sessions AS feedback |
| 198 | + ON sessions.`date` = feedback.`date` |
| 199 | + AND sessions.app_name = feedback.app_name |
| 200 | + AND sessions.feature_name = feedback.feature_name |
| 201 | + AND sessions.session_id = feedback.session_id |
| 202 | +GROUP BY sessions.`date`, sessions.app_name, sessions.feature_name; |
0 commit comments