偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

從 “被動(dòng)救火” 到 “主動(dòng)預(yù)判”:用 NeuralProphet 搭建運(yùn)維數(shù)據(jù) AI 預(yù)測(cè)體系

原創(chuàng) 精選
人工智能
NeuralProphet 非常好用,我們可以用NeuralProphet 模型來(lái)預(yù)測(cè)系統(tǒng)指標(biāo)(CPU、內(nèi)存、磁盤、網(wǎng)絡(luò))。那么如何用 NeuralProphet 這個(gè)模型呢, 我的思路也比較簡(jiǎn)單粗暴, 來(lái)看看吧。

作者 | 崔皓

審校 | 重樓

開篇

對(duì)多數(shù)運(yùn)維工程師而言,日常工作更像一場(chǎng) “被動(dòng)的消防演練”—— 緊盯著監(jiān)控面板上跳動(dòng)的 CPU 使用率、內(nèi)存占用、磁盤容量與網(wǎng)絡(luò)流量,等數(shù)值觸達(dá)告警閾值時(shí),再匆忙排查問(wèn)題、擴(kuò)容資源、處理故障。這種 “盯數(shù)據(jù) - 等告警 - 忙救火” 的模式,看似能保障系統(tǒng)穩(wěn)定,卻藏著難以規(guī)避的痛點(diǎn):當(dāng)業(yè)務(wù)高峰期突然來(lái)臨,CPU 使用率驟升導(dǎo)致服務(wù)卡頓;當(dāng)磁盤空間在深夜悄然耗盡,核心業(yè)務(wù)中斷才觸發(fā)告警;當(dāng)網(wǎng)絡(luò)流量突發(fā)峰值沖垮帶寬,用戶投訴已堆積成山……

我們總在事后補(bǔ)救,卻很少能提前回答:“1 小時(shí)后 CPU 會(huì)不會(huì)過(guò)載?”“3 天后磁盤空間是否夠用?”“下周這個(gè)時(shí)段網(wǎng)絡(luò)流量會(huì)不會(huì)突破閾值?” 并非運(yùn)維工程師不愿主動(dòng)預(yù)判,而是傳統(tǒng)運(yùn)維中,既缺乏能捕捉系統(tǒng)指標(biāo)時(shí)間規(guī)律的工具,也沒(méi)有低成本落地的預(yù)測(cè)方法 —— 直到 NeuralProphet 的出現(xiàn),讓 “提前預(yù)測(cè)運(yùn)維數(shù)據(jù)” 從復(fù)雜的 AI 課題,變成了像搭樂(lè)高積木一樣可落地的實(shí)踐。

想象一下用樂(lè)高積木搭建一個(gè)模型:每一塊積木都有特定的形狀和功能,有的負(fù)責(zé)搭建底座(對(duì)應(yīng)數(shù)據(jù)的基礎(chǔ)趨勢(shì)),有的負(fù)責(zé)拼接循環(huán)結(jié)構(gòu)(對(duì)應(yīng)指標(biāo)的周期性波動(dòng)),有的負(fù)責(zé)填補(bǔ)細(xì)節(jié)(對(duì)應(yīng)突發(fā)異常的修正),將這些積木按邏輯組合,就能從零散部件變成完整的、可復(fù)用的模型。NeuralProphet 處理運(yùn)維時(shí)間序列數(shù)據(jù)(如 CPU 使用率、內(nèi)存波動(dòng))的方式,與此幾乎完全一致。

它本質(zhì)上是 Facebook 經(jīng)典預(yù)測(cè)模型 Prophet 的 “升級(jí)版”——Prophet 曾因?qū)?fù)雜時(shí)間序列拆解為 “趨勢(shì)、周期、節(jié)假日” 等可解釋模塊而風(fēng)靡運(yùn)維圈,但在面對(duì)運(yùn)維數(shù)據(jù)的 “短期高頻波動(dòng)”(如每 10 分鐘一次的 CPU 驟升)時(shí),常因缺乏 “局部上下文” 建模能力導(dǎo)致預(yù)測(cè)偏差;同時(shí),其基于 Stan 的后端架構(gòu),也讓普通運(yùn)維工程師難以根據(jù)實(shí)際場(chǎng)景調(diào)整參數(shù)。

而 NeuralProphet 的誕生,正是為了解決這些痛點(diǎn)。它完整保留了 Prophet “模塊化拆解數(shù)據(jù)” 的核心優(yōu)勢(shì) —— 比如將 CPU 使用率數(shù)據(jù)拆成 “長(zhǎng)期增長(zhǎng)趨勢(shì)(業(yè)務(wù)擴(kuò)容導(dǎo)致的使用率緩步上升)”“日周期波動(dòng)(早 9 晚 6 的辦公高峰)”“周周期波動(dòng)(工作日與周末的負(fù)載差異)” 等獨(dú)立模塊,讓非 AI 背景的運(yùn)維人員也能看懂預(yù)測(cè)邏輯;同時(shí),它通過(guò)引入 “自回歸組件”(能捕捉近 1 小時(shí)內(nèi)的短期波動(dòng))和 “PyTorch 后端”(支持靈活調(diào)參與輕量化部署),完美彌補(bǔ)了 Prophet 的短板,既能精準(zhǔn)預(yù)測(cè)下 10 分鐘的 CPU 峰值,也能適配從邊緣服務(wù)器到云集群的不同運(yùn)維場(chǎng)景。

上面說(shuō)了這么多,其實(shí)就是一句話:NeuralProphet 非常好用,我們可以用NeuralProphet 模型來(lái)預(yù)測(cè)系統(tǒng)指標(biāo)(CPU、內(nèi)存、磁盤、網(wǎng)絡(luò))。

那么如何用 NeuralProphet 這個(gè)模型呢, 我的思路也比較簡(jiǎn)單粗暴, 如下圖所示。

為了大家理解方便,我們舉個(gè)簡(jiǎn)單的例子,我們使用“ 8 月份的數(shù)據(jù)”(CPU 等)來(lái)預(yù)測(cè)“下一個(gè)小時(shí)的數(shù)據(jù)”,然后把“8 月份的數(shù)據(jù)”+“下一個(gè)小時(shí)的數(shù)據(jù)”預(yù)測(cè)“再下一個(gè)小時(shí)的數(shù)據(jù)”。依次類推,有點(diǎn)俄羅斯套娃的感覺,實(shí)際情況也是如此。CPU 的使用率數(shù)據(jù)會(huì)在系統(tǒng)中不斷產(chǎn)生,有了歷史數(shù)據(jù)可以幫助我們預(yù)測(cè)下個(gè)時(shí)間段(一小時(shí))的數(shù)據(jù),同時(shí)下個(gè)時(shí)間段的數(shù)據(jù)也會(huì)成為歷史數(shù)據(jù),為后面數(shù)據(jù)的預(yù)測(cè)發(fā)光發(fā)熱。

好了,有了目標(biāo)接下來(lái)就好辦了,整個(gè)實(shí)戰(zhàn)案例的思路如下圖所示。

首先,生成歷史數(shù)據(jù),也就是真實(shí)的系統(tǒng)指標(biāo)數(shù)據(jù),模擬真實(shí)數(shù)據(jù)分為 CPU、內(nèi)存、磁盤、網(wǎng)絡(luò),每 10 分鐘生成一條數(shù)據(jù)。

接著,利用已經(jīng)生成的歷史數(shù)據(jù)訓(xùn)練模型,模型就用NeuralProphet,生成的模型保存?zhèn)溆谩?/span>

然后,利用訓(xùn)練好的模型預(yù)測(cè)下一個(gè)小時(shí)的系統(tǒng)指標(biāo)數(shù)據(jù),例如:現(xiàn)在時(shí)間是 9 月 1 日的 00:00:00, 我們要預(yù)測(cè) 從 00:00:00 到 01:00:00 的 CPU 使用率,由于預(yù)測(cè)數(shù)據(jù)也是 10 分鐘一條,所以會(huì)生成 6 條 CPU 使用率的數(shù)據(jù)。

最終的效果如下,藍(lán)色的線條為實(shí)際數(shù)據(jù),橙色線條為預(yù)測(cè)值,紅色的文字為誤差比,也就是實(shí)際值與預(yù)測(cè)值之間存在的差距。

NeuralProphet 的核心理念

好了,說(shuō)明了目的(系統(tǒng)數(shù)據(jù)預(yù)測(cè))以及方法(利用 NeuralProphet 預(yù)測(cè))之后,需要介紹主角NeuralProphet。

 NeuralProphet 的核心理念非常直觀:最終的預(yù)測(cè)值為“獨(dú)立組件”預(yù)測(cè)值的總和。簡(jiǎn)單來(lái)說(shuō),多個(gè)“獨(dú)立組件”等同于從多維度思考。把不同維度預(yù)測(cè)數(shù)據(jù)的模塊得到的結(jié)果加起來(lái)就是全面的預(yù)測(cè)。你可以想象有一個(gè)復(fù)雜問(wèn)題,讓多個(gè)不同的專家一起思考提出方案,然后整合他們的方案得到最終方案。

但是這些預(yù)測(cè)模型或者說(shuō)思考方案總得通過(guò)一個(gè)公式表示一下, 要不我們也不好描述,于是就有了下面的公式。:

?t = T(t) + S(t) + E(t) + F(t) + A(t) + L(t)

看到公式這么復(fù)雜,我是有點(diǎn)懵的,用一個(gè)列表表示,通過(guò)“說(shuō)人話”對(duì)其進(jìn)行解釋。

組件符號(hào)

簡(jiǎn)單描述

T(t)

趨勢(shì) (Trend):數(shù)據(jù)隨時(shí)間變化的長(zhǎng)期基礎(chǔ)走向(例如,增長(zhǎng)或下降)。

S(t)

季節(jié)性 (Seasonality):在固定周期內(nèi)重復(fù)出現(xiàn)的模式(例如,每周、每年的周期)。

E(t)

事件 (Events):特殊日期(如節(jié)假日)對(duì)數(shù)據(jù)產(chǎn)生的短期影響。

F(t)

未來(lái)回歸量 (Future Regressors):其未來(lái)值已知的外部變量(例如,已計(jì)劃的營(yíng)銷活動(dòng))。

A(t)

自回歸 (Auto-Regression):近期歷史觀測(cè)值對(duì)未來(lái)值的直接影響。

L(t)

滯后回歸量 (Lagged Regressors):其未來(lái)值未知的外部變量(例如,昨天的天氣)。

下面再花一點(diǎn)點(diǎn)篇幅對(duì)各個(gè)組件進(jìn)行介紹,特別是自回歸。如果對(duì)這部分不感興趣或者已經(jīng)有所了解的同學(xué),可以自行跳到實(shí)戰(zhàn)環(huán)節(jié),從“安裝依賴”開始看。

趨勢(shì) (T(t)):整體走向

趨勢(shì)組件捕捉的是時(shí)間序列總體、長(zhǎng)期的發(fā)展方向。為了使趨勢(shì)線能夠適應(yīng)現(xiàn)實(shí)世界中的變化,NeuralProphet 引入了變化點(diǎn) (changepoints) 的概念。假設(shè)你在開車,正在直線行駛,路上的一個(gè)轉(zhuǎn)彎,你的方向(或速度)就要根據(jù)這個(gè)轉(zhuǎn)彎發(fā)生變化,這個(gè)轉(zhuǎn)彎就是變化點(diǎn) (changepoints) 。

NeuralProphet 將趨勢(shì)建模為一個(gè)“分段線性”序列。數(shù)據(jù)變化的趨勢(shì)基本就是一條直線,直線可以在變化點(diǎn) (changepoints)改變方向。讓模型識(shí)別在數(shù)據(jù)中反復(fù)出現(xiàn)的變化模式,從而知道在變化點(diǎn)轉(zhuǎn)彎--改變方向。

線性

分段線性

季節(jié)性 (S(t)):周期性節(jié)律

季節(jié)性是指在固定時(shí)期內(nèi)發(fā)生的可預(yù)測(cè)、重復(fù)的模式,重點(diǎn)是可預(yù)測(cè)和重復(fù)。比如:勞動(dòng)節(jié)、兒童節(jié)、春節(jié)人們會(huì)更多出游購(gòu)物,零售店的銷售額通常在周末達(dá)到高峰。冰淇淋的銷量在夏季會(huì)顯著增加,等等。

NeuralProphet 利用傅里葉項(xiàng)(本質(zhì)上是正弦和余弦函數(shù)的組合)使模型能夠同時(shí)捕捉多種季節(jié)性,例如,一個(gè)模型可以同時(shí)識(shí)別出數(shù)據(jù)中的每日、每周和年度模式。

此外,季節(jié)性還具備如下特性:

? 加法性 (Additive) 季節(jié)性:一家冰淇淋店每到夏天,銷量總是在平日基礎(chǔ)上固定增加50份,這個(gè)增量不受公司規(guī)模變化的影響。

? 乘法性 (Multiplicative) 季節(jié)性:一家電商公司每逢節(jié)假日的銷售額,總是能達(dá)到當(dāng)年平均水平的兩倍,因此公司規(guī)模越大,節(jié)假日帶來(lái)的銷量增長(zhǎng)就越多。

自回歸 (A(t)):近期歷史的影響

自回歸 (Auto-Regression, AR) 在短期預(yù)測(cè)方面表現(xiàn)突出。在介紹自回歸之前先說(shuō)說(shuō)什么是回歸,回歸是通過(guò)外部變量(如促銷活動(dòng))與目標(biāo)指標(biāo)(CPU 使用率)的關(guān)系,量化外部因素對(duì)目標(biāo)的影響,比如 “電商平臺(tái)的促銷能讓服務(wù)器的 CPU 負(fù)載提升 15%”;而自回歸是回歸的特殊形式,不依賴外部變量,僅通過(guò)目標(biāo)指標(biāo)自身的歷史數(shù)據(jù)(如過(guò)去 1 小時(shí)的 CPU 使用率)預(yù)測(cè)未來(lái)值,核心是捕捉 “歷史慣性”—— 比如 “上 10 分鐘 CPU 使用率超 80%,下 10 分鐘大概率維持高負(fù)載”,也就是 “同一變量過(guò)去影響未來(lái)” 。

所以,自回歸的核心思想:“最近發(fā)生的事情是對(duì)接下來(lái)會(huì)發(fā)生的事情產(chǎn)生影響?!?模型會(huì)回顧過(guò)去特定數(shù)量的數(shù)據(jù)點(diǎn),這些數(shù)據(jù)點(diǎn)被稱為“滯后項(xiàng) (lags)”。例如,如果我們使用 5 個(gè)滯后項(xiàng),模型就會(huì)查看最近的 5 個(gè)觀測(cè)值來(lái)幫助預(yù)測(cè)下一個(gè)值。

好了到這里,可能有人感覺趨勢(shì)和自回歸有點(diǎn)像,都是通過(guò)歷史預(yù)測(cè)未來(lái),所以我們停下來(lái),給他們做一個(gè)小區(qū)分。趨勢(shì)是運(yùn)維指標(biāo)長(zhǎng)期的宏觀走向(比如業(yè)務(wù)增長(zhǎng)導(dǎo)致 CPU 使用率每月穩(wěn)步上升 2%),自回歸則是指標(biāo)短期的實(shí)時(shí)動(dòng)態(tài)(比如上 10 分鐘 CPU 突升 15%,下 10 分鐘大概率維持高負(fù)載)。

NeuralProphet 的 AR 模塊基于一個(gè)名為 AR-Net 的架構(gòu),它可以配置為兩種模式,兼具簡(jiǎn)單性和強(qiáng)大的功能:

? 線性 AR:這是一種簡(jiǎn)單直接的方法。它假設(shè)每個(gè)過(guò)去的值都對(duì)預(yù)測(cè)有一個(gè)直接的、加權(quán)的線性影響。這種方式非常容易解釋,你可以清楚地看到每個(gè)滯后項(xiàng)對(duì)預(yù)測(cè)的貢獻(xiàn)大小。

? 深度 AR:這是一種更高級(jí)的方法,它使用一個(gè)小型神經(jīng)網(wǎng)絡(luò)(即 AR-Net)來(lái)發(fā)現(xiàn)過(guò)去值與未來(lái)預(yù)測(cè)之間復(fù)雜的、非線性的關(guān)系。這通??梢蕴岣哳A(yù)測(cè)的準(zhǔn)確性,但其內(nèi)部工作機(jī)制不如線性 AR 那樣易于直接解讀。

回歸量與事件:外部影響因素

回歸量是幫助預(yù)測(cè)目標(biāo)的外部變量,可以理解為“外援”。例如:“要預(yù)測(cè)冰淇淋銷量(目標(biāo)),了解每日溫度(“外援”=回歸量)會(huì)非常有幫助?!?/span>

NeuralProphet 可以處理多種類型的外部影響因素,下表對(duì)它們進(jìn)行了比較:

類型

關(guān)鍵特征

簡(jiǎn)單示例

滯后回歸量

歷史值已知,未來(lái)值未知。功能上與自回歸模塊相同,但使用外部變量作為輸入。

利用昨天的天氣數(shù)據(jù)來(lái)預(yù)測(cè)今天的能源消耗。

未來(lái)回歸量

歷史和未來(lái)值都已知。

在銷售預(yù)測(cè)中包含已提前計(jì)劃好的市場(chǎng)營(yíng)銷活動(dòng)的日期。

事件與節(jié)假日

特殊的一次性或重復(fù)性日期。它們被建模為二元變量,并且可以自動(dòng)包含特定國(guó)家的節(jié)假日。

對(duì)每年“黑色星期五”購(gòu)物節(jié)期間出現(xiàn)的銷售高峰進(jìn)行建模。

上面已經(jīng)了解了所有的構(gòu)建模塊,NeuralProphet模型就是將每個(gè)獨(dú)立組件生成的預(yù)測(cè)值(趨勢(shì) + 季節(jié)性 + 自回歸 + 回歸量等)全部加在一起,得到最終的綜合預(yù)測(cè)值,可以理解為“匯總專家意見”。這種方法的最大好處是可解釋性 (explainability)。由于每個(gè)組件可以獨(dú)立建模,用戶可以單獨(dú)繪制每個(gè)組件的圖表,從而確切地了解是哪個(gè)因素在影響最終預(yù)測(cè)結(jié)果。

安裝依賴

好了理論的部分已經(jīng)講完,如果沒(méi)有聽懂也不要緊,直接實(shí)操幫助理解,如果還是沒(méi)有聽懂,那就回到開頭再看一遍。接下來(lái),我們需要安裝必要的環(huán)境,先確認(rèn)已安裝conda,conda 是老演員了,安裝的鏈接放到這里,https://anaconda.org/anaconda/conda。

為了本次實(shí)踐創(chuàng)建虛擬環(huán)境,如下:

conda create -n forecast python=3.12

創(chuàng)建完畢之后,啟用虛擬環(huán)境,如下:

conda activate forecast

然后再虛擬環(huán)境中,安裝相關(guān)的依賴包,如下:

# 基于 PyTorch 的時(shí)間序列預(yù)測(cè)工具,用來(lái)訓(xùn)練模型并進(jìn)行預(yù)測(cè)
pip install neuralprophet
# 用于處理Excel的庫(kù),演示用數(shù)據(jù)保存在Excel
pip install openpyxl
# 用于構(gòu)建網(wǎng)頁(yè)應(yīng)用界面
pip install streamlit

生成“歷史數(shù)據(jù)”

安裝完了環(huán)境,我們開始造一些數(shù)據(jù),方便后面測(cè)試,在造數(shù)據(jù)之前先回顧一下我們要做的事情,如下圖所示。

一般而言,我們?cè)陬A(yù)測(cè)未來(lái)的系統(tǒng)指標(biāo)的時(shí)候,需要利用歷史數(shù)據(jù),未來(lái)演示的需要我們用代碼生成所謂的“歷史數(shù)據(jù)”。在真實(shí)的場(chǎng)景中,大家可以按照我后面說(shuō)的數(shù)據(jù)格式,將系統(tǒng)指標(biāo)(CPU、內(nèi)存、磁盤、網(wǎng)絡(luò))的信息填入到 XSL 中,為后面訓(xùn)練預(yù)測(cè)模型做好準(zhǔn)備。在forecast目錄中新建python腳本。

cd /forecast
# 直接編輯,在保存時(shí)會(huì)生成文件
vim history_data.py

import numpy as np
import pandas as pd

# ============================
# 參數(shù)配置
# ============================
start_time = pd.Timestamp("2025-08-01 00:00:00")
end_time = pd.Timestamp("2025-08-31 23:59:59")
rng = pd.date_range(start=start_time, end=end_time, freq="10min")

periods = len(rng)
np.random.seed(42)  # 保證可復(fù)現(xiàn)

# ============================
# 輔助函數(shù):日內(nèi)波動(dòng)模式
# ============================
def daily_pattern(minutes, amplitude=1.0, phase_shift=0):
    radians = (minutes / (24 * 60)) * 2 * np.pi
    return 0.5 + 0.5 * np.sin(radians - 0.3 + phase_shift)

minutes_from_start = (np.arange(periods) * 10) % (24 * 60)
weekday = rng.weekday  # 0=周一
hours = rng.hour

# ============================
# CPU
# ============================
cpu_base = 10 + 5 * (np.random.rand(periods) - 0.5)
cpu_daily = 25 * daily_pattern(minutes_from_start)
cpu = cpu_base + cpu_daily * np.where(weekday < 5, 1.0, 0.7)
spike_mask = (np.random.rand(periods) < 0.005)  # 偶發(fā)高峰
cpu[spike_mask] += np.random.uniform(20, 60, size=spike_mask.sum())

# ============================
# 內(nèi)存
# ============================
mem_base = 50 + 10 * np.sin((np.arange(periods) / periods) * 2 * np.pi)
mem_noise = np.random.normal(0, 2.0, size=periods)
mem_weekday_effect = np.where(weekday < 5, 1.02, 0.99)
memory_used = mem_base * mem_weekday_effect + mem_noise
mem_spike_mask = (np.random.rand(periods) < 0.002)
memory_used[mem_spike_mask] += np.random.uniform(5, 20, size=mem_spike_mask.sum())
memory_used = np.clip(memory_used, 10, 99.5)

# ============================
# 磁盤使用率
# ============================
disk_start, disk_end = 60.0, 62.0
disk_trend = np.linspace(disk_start, disk_end, periods)
disk_noise = np.random.normal(0, 0.05, size=periods)
disk_used = np.clip(disk_trend + disk_noise, 20, 99.9)

# ============================
# 網(wǎng)絡(luò)流量
# ============================
net_in_base = 5 * daily_pattern(minutes_from_start) + 1.0
net_out_base = 3 * daily_pattern(minutes_from_start) + 0.5
lunch_mask = ((hours >= 11) & (hours <= 13))
net_in = net_in_base * (1.2 * np.where(weekday < 5, 1, 0.9))
net_out = net_out_base * (1.15 * np.where(weekday < 5, 1, 0.9))
net_in[lunch_mask] *= 1.3
net_out[lunch_mask] *= 1.2
burst_mask = (np.random.rand(periods) < 0.003)
net_in[burst_mask] += np.random.uniform(20, 200, size=burst_mask.sum())
net_out[burst_mask] += np.random.uniform(5, 80, size=burst_mask.sum())

# ============================
# 組合 DataFrame
# ============================
df_aug = pd.DataFrame({
    "ds": rng,
    "cpu": np.round(np.clip(cpu, 0, 100), 2),
    "memory": np.round(memory_used, 2),
    "disk": np.round(disk_used, 2),
    "net_in": np.round(net_in, 3),
    "net_out": np.round(net_out, 3)
})

# ============================
# 每小時(shí)統(tǒng)計(jì)(平均、最大、最?。?# ============================
df_hourly = df_aug.set_index("ds").resample("1h").agg(
    {
        "cpu": ["mean", "max", "min"],
        "memory": ["mean", "max", "min"],
        "disk": ["mean", "max", "min"],
        "net_in": ["mean", "max", "min"],
        "net_out": ["mean", "max", "min"],
    }
)
df_hourly.columns = ["_".join(col).strip() for col in df_hourly.columns.values]
df_hourly.reset_index(inplace=True)


# ============================
# 為每個(gè)指標(biāo)創(chuàng)建單獨(dú)的sheet(ds:日期,y:值)
# ============================
# CPU sheet
df_cpu = pd.DataFrame({
    "ds": rng,
    "y": cpu
})

# Memory sheet
df_memory = pd.DataFrame({
    "ds": rng,
    "y": memory_used
})

# Disk sheet
df_disk = pd.DataFrame({
    "ds": rng,
    "y": disk_used
})

# Network In sheet
df_net_in = pd.DataFrame({
    "ds": rng,
    "y": net_in
})

# Network Out sheet
df_net_out = pd.DataFrame({
    "ds": rng,
    "y": net_out
})

# ============================
# 導(dǎo)出到 Excel
# ============================
output_file = "server_metrics_2025_08.xlsx"
with pd.ExcelWriter(output_file, engine="openpyxl") as writer:
    df_aug.to_excel(writer, index=False, sheet_name="10min_data")
    df_hourly.to_excel(writer, index=False, sheet_name="hourly_stats")
    # 添加各個(gè)指標(biāo)的單獨(dú)sheet
    df_cpu.to_excel(writer, index=False, sheet_name="cpu")
    df_memory.to_excel(writer, index=False, sheet_name="memory")
    df_disk.to_excel(writer, index=False, sheet_name="disk")
    df_net_in.to_excel(writer, index=False, sheet_name="net_in")
    df_net_out.to_excel(writer, index=False, sheet_name="net_out")

print(f"? 數(shù)據(jù)已生成并導(dǎo)出到 {output_file}")

代碼詳細(xì)內(nèi)容如下:

  • 參數(shù)配置:設(shè)定 2025 年 8 月 1 日至 31 日的時(shí)間范圍,按 10 分鐘間隔生成時(shí)間序列,固定隨機(jī)種子確保數(shù)據(jù)可復(fù)現(xiàn)。
  • 函數(shù)定義:編寫日內(nèi)波動(dòng)模式函數(shù),通過(guò)三角函數(shù)計(jì)算,模擬指標(biāo)一天內(nèi)隨分鐘變化的周期性波動(dòng)規(guī)律。
  • 時(shí)間計(jì)算:算出每個(gè)時(shí)間點(diǎn)對(duì)應(yīng)的起始分鐘數(shù)、星期幾和小時(shí)數(shù),為后續(xù)指標(biāo)模擬提供時(shí)間維度數(shù)據(jù)。
  • CPU 生成:先確定 CPU 基礎(chǔ)值范圍,疊加日內(nèi)波動(dòng),按工作日和周末調(diào)整幅度,再用隨機(jī)掩碼添加偶發(fā)高峰,限制值在 0-100%。
  • 內(nèi)存生成:以正弦曲線為內(nèi)存基礎(chǔ)趨勢(shì),疊加隨機(jī)噪聲,結(jié)合工作日差異調(diào)整,加偶發(fā)峰值后限制在 10%-99.5%。
  • 磁盤生成:設(shè)定磁盤使用率從 60.0 到 62.0 的線性增長(zhǎng)趨勢(shì),疊加小噪聲,將值限制在 20%-99.9%。
  • 網(wǎng)絡(luò)生成:為網(wǎng)絡(luò)流入、流出設(shè)定日內(nèi)波動(dòng)基礎(chǔ)值,按工作日和午餐時(shí)段調(diào)整,用隨機(jī)掩碼加突發(fā)流量,確保值非負(fù)。
  • 組合數(shù)據(jù):將所有指標(biāo)數(shù)據(jù)與時(shí)間序列組合,生成含完整指標(biāo)的 DataFrame,保留指定小數(shù)位數(shù)。
  • 小時(shí)統(tǒng)計(jì):對(duì)原始 10 分鐘數(shù)據(jù)按小時(shí)重采樣,計(jì)算各指標(biāo)每小時(shí)的均值、最大值、最小值,整理成統(tǒng)計(jì) DataFrame。
  • 單表創(chuàng)建:為 CPU、內(nèi)存等 5 個(gè)指標(biāo)各建單獨(dú) DataFrame,僅含 “時(shí)間(ds)” 和 “指標(biāo)值(y)” 兩列。
  • 導(dǎo)出 Excel:用 ExcelWriter 將所有數(shù)據(jù)導(dǎo)出到 “server_metrics_2025_08.xlsx”,包含多類數(shù)據(jù)表。
  • 完成提示:打印數(shù)據(jù)已生成并導(dǎo)出到指定文件的提示信息。

執(zhí)行如下命令,命令完成之后在python腳本所在目錄生成歷史數(shù)據(jù)的excel文件。

python history_data.py

如下圖所示,會(huì)在 history_data.py 相同的目錄下生成“server_metrics_2025_08.xlsx”的文件。

如下圖所示,在生成的excel中的 “ds”會(huì)顯示采集時(shí)間,我們按照 10 分鐘一次采集數(shù)據(jù),同時(shí)在“y”列顯示的是 CPU 的使用率。

在上圖的下部的“sheet”中,列出了不同維度的數(shù)據(jù),按從左到右的順序分別是:

  • 10min_data:包含所有指標(biāo)的數(shù)據(jù)
  • hourly_stats:所有指標(biāo)按小時(shí)統(tǒng)計(jì)數(shù)據(jù)
  • cpu:cpu使用率
  • memory:內(nèi)存使用率
  • disk:磁盤使用率
  • net_in:網(wǎng)絡(luò)入流量
  • net_out:網(wǎng)絡(luò)出流量

訓(xùn)練模型

我們通過(guò)代碼的方式生成了系統(tǒng)指標(biāo)的歷史數(shù)據(jù),接著會(huì)根據(jù)這些數(shù)據(jù)訓(xùn)練模型。

在forecast目錄中新建python腳本,如下:

cd /forecast
# 直接編輯,在保存時(shí)會(huì)生成文件
vim train_model.py

下面代碼用來(lái)訓(xùn)練歷史數(shù)據(jù),這里只選擇 cpu 進(jìn)行訓(xùn)練, 其他的 sheet 中存放了內(nèi)存、磁盤和網(wǎng)絡(luò)信息,在代碼中已經(jīng) remark 上了,有興趣的同學(xué)可以自行訓(xùn)練。

from neuralprophet import NeuralProphet
import pandas as pd
import warnings
from neuralprophet import save

# 忽略警告
warnings.filterwarnings('ignore')

# 1. 讀取Excel數(shù)據(jù)
excel_path = 'server_metrics_2025_08.xlsx'
sheet_name = 'cpu'
# sheet_name = 'memory'
# sheet_name = 'disk'
# sheet_name = 'net_in'
# sheet_name = 'net_out'
df = pd.read_excel(excel_path, sheet_name=sheet_name)

# 只保留 ds 和 y 列
df = df[['ds', 'y']]

# 2. 初始化并訓(xùn)練模型
m = NeuralProphet(
    changepoints_range=0.8,         # 只在前80%歷史數(shù)據(jù)中尋找變點(diǎn),避免對(duì)最新數(shù)據(jù)過(guò)擬合
    trend_reg=1,                    # 適度正則化,防止趨勢(shì)過(guò)度擬合 
    seasonality_reg=0.5,            # 適度正則化,防止季節(jié)性過(guò)擬合
    n_lags=144,                     # n_lags越大,可用訓(xùn)練樣本越少
    ar_reg=0.7,                     # 輕微正則化自回歸系數(shù),防止過(guò)擬合
    n_forecasts=6,                  # 預(yù)測(cè)的步數(shù),10分?jǐn)?shù)間隔的數(shù)據(jù)生成6條
    collect_metrics={ "MAE": "MeanAbsoluteError", "MAPE": "MeanAbsolutePercentageError" },
)

# 3. 分割訓(xùn)練集和驗(yàn)證集
df_train, df_val = m.split_df(df, valid_p=0.2)

# 4. 訓(xùn)練模型
m.fit(df_train, validation_df=df_val, freq="10min")

# 5. 保存模型到本地目錄
save(m, sheet_name + ".np")

這里稍微對(duì)代碼部分做解釋;

  • 導(dǎo)入工具:引入 NeuralProphet 模型、pandas 數(shù)據(jù)處理庫(kù)、警告忽略工具及模型保存函數(shù)。
  • 忽略警告:關(guān)閉程序運(yùn)行中的警告提示,使輸出更簡(jiǎn)潔。
  • 讀取數(shù)據(jù):從 “server_metrics_2025_08.xlsx”Excel 文件中讀取指定工作表(默認(rèn) cpu,可切換為 memory、disk 等)的數(shù)據(jù)。
  • 數(shù)據(jù)篩選:僅保留數(shù)據(jù)中的 “ds”(時(shí)間)和 “y”(指標(biāo)值)兩列,符合 NeuralProphet 模型要求的輸入格式。
  • 模型初始化:創(chuàng)建 NeuralProphet 模型實(shí)例,配置核心參數(shù) —— 在前 80% 數(shù)據(jù)中尋找趨勢(shì)變點(diǎn),對(duì)趨勢(shì)和季節(jié)性特征進(jìn)行適度正則化,設(shè)置 144 個(gè)歷史滯后項(xiàng)捕捉自回歸效應(yīng),輕微正則化自回歸系數(shù),指定預(yù)測(cè) 6 個(gè)時(shí)間步(10 分鐘間隔),并收集 MAE 和 MAPE 評(píng)估指標(biāo)。
  • 數(shù)據(jù)分割:將數(shù)據(jù)集按 8:2 比例拆分為訓(xùn)練集(df_train)和驗(yàn)證集(df_val),用于模型訓(xùn)練和性能驗(yàn)證。
  • 模型訓(xùn)練:使用訓(xùn)練集訓(xùn)練模型,同時(shí)用驗(yàn)證集評(píng)估效果,指定數(shù)據(jù)時(shí)間間隔為 10 分鐘。
  • 保存模型:將訓(xùn)練好的模型以 “指標(biāo)名稱.np”(如 cpu.np)的格式保存到本地,便于后續(xù)加載使用。

預(yù)測(cè)系統(tǒng)指標(biāo)

上面的代碼會(huì)生成一個(gè) np 為后綴的文件,.np 文件是一個(gè)模型檢查點(diǎn)文件,它是一個(gè)包含了模型完整狀態(tài)的快照,其核心內(nèi)容是模型在訓(xùn)練后學(xué)到的所有參數(shù)(權(quán)重),以及恢復(fù)訓(xùn)練所必需的模型配置和優(yōu)化器狀態(tài)。前面通過(guò)命令pip install neuralprophet 安裝neuralprophet 的基礎(chǔ)模型,此時(shí)只需要通過(guò)歷史數(shù)據(jù)訓(xùn)練成.np 的模型檢查點(diǎn)文件,再將這個(gè)文件與之前安裝的neuralprophet 基礎(chǔ)模型進(jìn)行合并,就是完整的模型了,再用這個(gè)完整的模型預(yù)測(cè)外來(lái)數(shù)據(jù)。只不過(guò),開發(fā)者看到的是.np 的文件,而不用關(guān)心模型是如何合并以及預(yù)測(cè)的,這一系列操作都是neuralprophet 框架幫我完成了。接下來(lái),我們來(lái)生成一個(gè) UI 界面,對(duì)外來(lái)數(shù)據(jù)進(jìn)行預(yù)測(cè),并且展示對(duì)應(yīng)內(nèi)容。

在forecast目錄中新建python 代碼,代碼中的 UI 界面 streamlit 生成。

cd /forecast
# 直接編輯,在保存時(shí)會(huì)生成文件
vim app.py

由于篇幅關(guān)系,我們只展示部分核心代碼,如下:

import streamlit as st
import pandas as pd
import plotly.graph_objects as go
from neuralprophet import load
import warnings
import numpy as np
from datetime import datetime, timedelta
import sys


def generate_forecast(df, sheet_name):
    """
    生成預(yù)測(cè)的獨(dú)立函數(shù)
    按步數(shù)遍歷,步數(shù)1取yhat1,步數(shù)2取yhat2...
    所有預(yù)測(cè)值都放到y(tǒng)hat1列中
    """
    try:
        # 在預(yù)測(cè)函數(shù)中僅保留'ds'和'y'列用于模型訓(xùn)練
        model_df = df[['ds', 'y']].copy()
        
        # 加載預(yù)訓(xùn)練模型
        model_path = f"{sheet_name}.np"
        
        model = load(model_path)
        
        # 生成預(yù)測(cè)
        future_df = model.make_future_dataframe(model_df, n_historic_predictions=False)
        forecast_result = model.predict(future_df, decompose=False)

        print(forecast_result)

        # 獲取最后一個(gè)數(shù)據(jù)點(diǎn)
        last_data_point = model_df['ds'].max()

        # 處理預(yù)測(cè)結(jié)果
        forecast_long = []
        last_actual_idx = forecast_result['y'].last_valid_index() if 'y' in forecast_result.columns else -1
        start_idx = last_actual_idx + 1 if last_actual_idx + 1 < len(forecast_result) else 0

        # 生成預(yù)測(cè)步驟,按步數(shù)取對(duì)應(yīng)yhat,統(tǒng)一放到y(tǒng)hat1列
        for step in range(1, FORECAST_STEPS + 1):
            yhat_col = f'yhat{step}'  # 步數(shù)1取yhat1,步數(shù)2取yhat2...
            
            current_idx = start_idx + (step - 1)
            if current_idx >= len(forecast_result):
                current_idx = len(forecast_result) - 1
                st.warning(f"預(yù)測(cè)數(shù)據(jù)不足,使用最后一條數(shù)據(jù)預(yù)測(cè)第{step}步")
            
            if current_idx < len(forecast_result):
                date = forecast_result.loc[current_idx, 'ds']
                
                if pd.notna(date) and yhat_col in forecast_result.columns and pd.notna(forecast_result.loc[current_idx, yhat_col]):
                    forecast_time = last_data_point + step * FORCE_TIME_INTERVAL
                    # 所有預(yù)測(cè)值都放到y(tǒng)hat1列
                    forecast_entry = {
                        'ds': forecast_time,
                        'yhat1': forecast_result.loc[current_idx, yhat_col],
                        'step': step
                    }
                    forecast_long.append(forecast_entry)
                else:
                    st.warning(f"第{step}步預(yù)測(cè)值缺失,使用歷史平均值")
                    forecast_time = last_data_point + step * FORCE_TIME_INTERVAL
                    avg_value = model_df['y'].mean()
                    forecast_entry = {
                        'ds': forecast_time,
                        'yhat1': avg_value,
                        'step': step
                    }
                    forecast_long.append(forecast_entry)
            else:
                forecast_time = last_data_point + step * FORCE_TIME_INTERVAL
                avg_value = model_df['y'].mean()
                forecast_entry = {
                    'ds': forecast_time,
                    'yhat1': avg_value,
                    'step': step
                }
                forecast_long.append(forecast_entry)

        # 轉(zhuǎn)換為DataFrame
        forecast_long = pd.DataFrame(forecast_long)
        forecast_merged = forecast_long.merge(df[['ds', 'y']], on='ds', how='left')
        
        return forecast_merged
        
    except Exception as e:
        st.error(f"預(yù)測(cè)出錯(cuò): {str(e)}")
        st.info("可能的原因:模型文件不存在、數(shù)據(jù)格式不正確或模型訓(xùn)練不完整")
        return None

代碼的主要內(nèi)容如下:

  • 數(shù)據(jù)篩選:從輸入的歷史數(shù)據(jù)中,僅保留 “ds(時(shí)間列)” 和 “y(指標(biāo)值列)” 并復(fù)制,形成模型可識(shí)別的輸入數(shù)據(jù)(model_df)。
  • 加載模型:cpu.np,通過(guò) NeuralProphet 的 load 函數(shù)加載本地預(yù)訓(xùn)練好的模型。
  • 生成預(yù)測(cè)數(shù)據(jù):調(diào)用模型的 make_future_dataframe 方法,基于歷史數(shù)據(jù)創(chuàng)建未來(lái)預(yù)測(cè)所需的時(shí)間框架(關(guān)閉 “包含歷史預(yù)測(cè)” 功能,僅生成未來(lái)數(shù)據(jù));再用 predict 方法生成預(yù)測(cè)結(jié)果,關(guān)閉 “成分分解” 功能(不拆分趨勢(shì)、季節(jié)性等組件),并打印預(yù)測(cè)結(jié)果供調(diào)試查看。
  • 確定時(shí)間基準(zhǔn):提取歷史數(shù)據(jù)中最新的時(shí)間點(diǎn)(last_data_point),作為后續(xù)計(jì)算 “未來(lái)預(yù)測(cè)時(shí)間” 的基準(zhǔn)。
  • 初始化存儲(chǔ)列表:創(chuàng)建空列表 forecast_long,用于暫存每一步的預(yù)測(cè)結(jié)果;同時(shí)找到歷史數(shù)據(jù)在預(yù)測(cè)結(jié)果中的最后有效索引(last_actual_idx),確定未來(lái)預(yù)測(cè)的起始位置(start_idx)。
  • 循環(huán)生成預(yù)測(cè):按設(shè)定的預(yù)測(cè)步數(shù)(FORECAST_STEPS)循環(huán),每一步對(duì)應(yīng)一個(gè)預(yù)測(cè)列(如第 1 步取 yhat1、第 2 步取 yhat2):

     a. 計(jì)算當(dāng)前步在預(yù)測(cè)結(jié)果中的索引(current_idx),若索引超出預(yù)測(cè)結(jié)果范圍,自動(dòng)調(diào)整為最后一條數(shù)據(jù)的索引,并通過(guò) Streamlit 給出 “預(yù)測(cè)數(shù)據(jù)不足” 的警告;

     b. 若索引有效,先獲取對(duì)應(yīng)時(shí)間,若 “時(shí)間非空、預(yù)測(cè)列存在、預(yù)測(cè)值非空”,則以 “歷史最新時(shí)間 + 當(dāng)前步數(shù) × 時(shí)間間隔(FORCE_TIME_INTERVAL)” 為預(yù)測(cè)時(shí)間,將 “時(shí)間、該步預(yù)測(cè)值(存入 yhat1)、步數(shù)” 組成字典存入列表;

     c. 若預(yù)測(cè)值缺失或時(shí)間無(wú)效,通過(guò) Streamlit 給出 “預(yù)測(cè)值缺失” 的警告,用歷史指標(biāo)的平均值作為預(yù)測(cè)值,同樣按上述格式存入列表;

     d. 若索引無(wú)效(極端情況),直接用歷史平均值作為預(yù)測(cè)值,生成對(duì)應(yīng)時(shí)間和數(shù)據(jù)存入列表。

然后,通過(guò)如下命令執(zhí)行應(yīng)用查看結(jié)果。

streamlit run app.py

如下圖所示,在彈出的頁(yè)面中選擇“cpu”,以及展示的開始和結(jié)束時(shí)間,然后點(diǎn)擊“生成預(yù)測(cè)”。在右邊的界面中會(huì)展示預(yù)測(cè)的曲線(橙色),這就是我們利用 8 月份 CPU 使用率的模型預(yù)測(cè)出來(lái),9 月 1 日 00:00 到 02:50 的數(shù)據(jù),每 10 分鐘產(chǎn)生一個(gè)數(shù)據(jù)點(diǎn)。

如果把鼠標(biāo)放到任何一個(gè)數(shù)據(jù)點(diǎn)上,可以看到如下圖所示的紅色字體“誤差比”,描述了預(yù)測(cè)值與實(shí)際值之間的誤差情況。

接入LLM進(jìn)行對(duì)話

好,到這里,數(shù)據(jù)預(yù)測(cè)的功能完成了,接著來(lái)到最后一步,我們可以與歷史數(shù)據(jù)進(jìn)行“對(duì)話”,讓大模型基于數(shù)據(jù)給出運(yùn)維存在的風(fēng)險(xiǎn),并提出建議。

接下來(lái),還是開始實(shí)戰(zhàn)操作,先安裝一些依賴。

# python-dotenv:可以使用load_dotenv從同目錄的.env文件中讀取配置
pip install python-dotenv openai

由于要使用 DeepSeek 模型,所以要?jiǎng)?chuàng)建.env文件,用來(lái)保存 DeepSeek API Key。

DEEPSEEK_API_KEY=sk-*********

新建config.py文件,用于管理配置參數(shù),包括:項(xiàng)目根目錄(使用 Path 獲取當(dāng)前文件所在目錄)、Excel數(shù)據(jù)文件的路徑(指向服務(wù)器指標(biāo)數(shù)據(jù)文件)、需要監(jiān)控的服務(wù)器資源類型列表(CPU、內(nèi)存、磁盤、網(wǎng)絡(luò)入流量和出流量),以及這些資源類型的中文顯示映射(便于用戶界面展示),同時(shí)還定義了日期時(shí)間的標(biāo)準(zhǔn)格式化模式。

import os
from pathlib import Path

# 項(xiàng)目根目錄
ROOT_DIR = Path(__file__).parent

# Excel文件路徑
EXCEL_PATH = os.path.join(ROOT_DIR, 'server_metrics_2025_08.xlsx')

# 資源類型列表
RESOURCE_TYPES = ['cpu', 'memory', 'disk', 'net_in', 'net_out']

# 資源類型中文映射
RESOURCE_TYPE_MAP = {
    'cpu': 'CPU使用率',
    'memory': '內(nèi)存使用率',
    'disk': '磁盤使用率',
    'net_in': '網(wǎng)絡(luò)入流量',
    'net_out': '網(wǎng)絡(luò)出流量'
}

# 時(shí)間格式
DATETIME_FORMAT = '%Y-%m-%d %H:%M:%S'
DATE_FORMAT = '%Y-%m-%d'

新建logger.py文件,這是一個(gè)日志配置模塊,它使用 Python 的 logging 庫(kù)來(lái)設(shè)置應(yīng)用程序的日志記錄功能。該模塊首先在項(xiàng)目目錄下創(chuàng)建 logs 文件夾,然后配置日志記錄的格式(包含時(shí)間戳、日志級(jí)別和消息內(nèi)容)和日期格式。它會(huì)根據(jù)當(dāng)前日期創(chuàng)建日志文件(格式如 chat_app_20250919.log),并設(shè)置日志記錄同時(shí)輸出到文件和控制臺(tái)。日志級(jí)別被設(shè)置為 INFO,這意味著它會(huì)記錄信息性消息、警告和錯(cuò)誤。最后創(chuàng)建了一個(gè)名為 logger 的日志記錄器實(shí)例,供其他模塊使用來(lái)記錄應(yīng)用程序的運(yùn)行狀態(tài)和調(diào)試信息。

import logging
import os
from datetime import datetime
from pathlib import Path

# 創(chuàng)建logs目錄
log_dir = Path(__file__).parent / 'logs'
log_dir.mkdir(exist_ok=True)

# 配置日志格式
log_format = '%(asctime)s - %(levelname)s - %(message)s'
date_format = '%Y-%m-%d %H:%M:%S'

# 創(chuàng)建日志文件名(包含日期)
log_file = log_dir / f'chat_app_{datetime.now().strftime("%Y%m%d")}.log'

# 配置日志
logging.basicConfig(
    level=logging.INFO,
    format=log_format,
    datefmt=date_format,
    handlers=[
        logging.FileHandler(log_file, encoding='utf-8'),
        logging.StreamHandler()
    ]
)

# 創(chuàng)建logger實(shí)例
logger = logging.getLogger(__name__)

新建chat_app.py文件如下,代碼中會(huì)引用config.py和logger.py。 由于篇幅原因我們展示核心函數(shù)如下:

def initialize_openai_client():
    """初始化OpenAI客戶端
    
    功能:
    - 從環(huán)境變量獲取API密鑰
    - 初始化DeepSeek API客戶端
    - 配置API基礎(chǔ)URL
    
    返回:
    - OpenAI客戶端實(shí)例 或 None(如果初始化失?。?    """
    # 從環(huán)境變量獲取API密鑰
    api_key = os.getenv('DEEPSEEK_API_KEY')
    if not api_key:
        st.error("未找到DEEPSEEK_API_KEY環(huán)境變量")
        return None
    
    # 創(chuàng)建并返回配置好的客戶端實(shí)例
    return OpenAI(
        api_key=api_key,
        base_url="https://api.deepseek.com/v1"  # DeepSeek API的基礎(chǔ)URL
    )

def generate_prompt(start_dt, end_dt, resource_type=None):
    """生成提示詞:支持時(shí)間點(diǎn)或時(shí)間范圍。
    - 當(dāng) start_dt == end_dt 時(shí),生成“在 X 時(shí) ...”的時(shí)間點(diǎn)提示
    - 當(dāng)不相等時(shí),生成“在 X 至 Y 這段時(shí)間 ...”的時(shí)間范圍提示
    """
    if not start_dt or not end_dt:
        return ""

    start_str = start_dt.strftime("%Y-%m-%d %H:%M:%S")
    end_str = end_dt.strftime("%Y-%m-%d %H:%M:%S")

    resource_name = RESOURCE_TYPE_MAP.get(resource_type, resource_type) if resource_type else None

    if start_dt == end_dt:
        if resource_name:
            return f"在{start_str} 時(shí)服務(wù)器的{resource_name}情況如何?請(qǐng)進(jìn)行分析,指出異常與風(fēng)險(xiǎn)。"
        return f"在{start_str} 時(shí)服務(wù)器的整體運(yùn)行情況如何?請(qǐng)進(jìn)行分析,指出異常與風(fēng)險(xiǎn)。"
    else:
        if resource_name:
            return f"在{start_str} 至 {end_str} 這段時(shí)間內(nèi),服務(wù)器的{resource_name}情況如何?請(qǐng)進(jìn)行分析,指出異常與風(fēng)險(xiǎn)。"
        return f"在{start_str} 至 {end_str} 這段時(shí)間內(nèi),服務(wù)器的整體運(yùn)行情況如何?請(qǐng)進(jìn)行分析,指出異常與風(fēng)險(xiǎn)。"

def filter_data(df, date, time=None, resource_type=None, end_date=None, end_time=None):
    """根據(jù)選擇的日期時(shí)間范圍和資源類型篩選數(shù)據(jù)"""
    if df is None:
        logger.warning("輸入的DataFrame為空")
        return None
    
    logger.info(f"開始篩選數(shù)據(jù),起始日期:{date}, 起始時(shí)間:{time or '00:00:00'}")
    logger.info(f"結(jié)束日期:{end_date or date}, 結(jié)束時(shí)間:{end_time or '23:59:59'}")
    logger.info(f"資源類型:{resource_type or '所有資源'}")
    
    # 構(gòu)建開始日期時(shí)間
    start_datetime = pd.Timestamp.combine(date, time) if time else pd.Timestamp.combine(date, pd.Timestamp.min.time())
    
    # 構(gòu)建結(jié)束日期時(shí)間
    if end_date and end_time:
        end_datetime = pd.Timestamp.combine(end_date, end_time)
    elif end_date:
        end_datetime = pd.Timestamp.combine(end_date, pd.Timestamp.max.time())
    else:
        end_datetime = pd.Timestamp.combine(date, pd.Timestamp.max.time())
    
    logger.info(f"篩選時(shí)間范圍:{start_datetime} 至 {end_datetime}")
    
    # 篩選時(shí)間范圍內(nèi)的數(shù)據(jù)
    filtered_df = df[(df['ds'] >= start_datetime) & (df['ds'] <= end_datetime)]
    
    # 記錄篩選結(jié)果
    logger.info(f"時(shí)間范圍內(nèi)的數(shù)據(jù)條數(shù):{len(filtered_df)}")
    
    # 如果選擇了資源類型,只返回相關(guān)列
    if resource_type and resource_type in df.columns:
        filtered_df = filtered_df[['ds', resource_type]]
        logger.info(f"已篩選資源類型:{resource_type}")
    
    # 記錄最終結(jié)果
    logger.info(f"最終篩選結(jié)果數(shù)據(jù)條數(shù):{len(filtered_df)}")
    if not filtered_df.empty:
        logger.info(f"數(shù)據(jù)時(shí)間范圍:{filtered_df['ds'].min()} 至 {filtered_df['ds'].max()}")
        if resource_type:
            stats = filtered_df[resource_type].describe()
            logger.info(f"資源統(tǒng)計(jì)信息:\n{stats}")
    else:
        logger.warning("篩選結(jié)果為空")
    
    return filtered_df

其中initialize_openai_client函數(shù)連接系統(tǒng)與 DeepSeek 大模型的 “橋梁”,創(chuàng)建大模型調(diào)用客戶端。從環(huán)境變量中讀取DEEPSEEK_API_KEY,配置 DeepSeek API 的 URL(https://api.deepseek.com/v1),生成并返回可直接用于調(diào)用的客戶端實(shí)例。

執(zhí)行如下命令,運(yùn)行對(duì)話應(yīng)用。

streamlit run chat_app.py

如下圖所示,可以選擇一段時(shí)間以及對(duì)應(yīng)的系統(tǒng)指標(biāo)(CPU 使用率),此時(shí)會(huì)自動(dòng)填寫提示詞,讓 DeepSeek 協(xié)助分析異常和風(fēng)險(xiǎn),然后點(diǎn)擊“開始分析”按鈕。在右側(cè)的對(duì)話框中就可以看到“CPU 使用率分析報(bào)告”的詳細(xì)信息了。

作者介紹

崔皓,51CTO社區(qū)編輯,資深架構(gòu)師,擁有18年的軟件開發(fā)和架構(gòu)經(jīng)驗(yàn),10年分布式架構(gòu)經(jīng)驗(yàn)。

參考論文

https://arxiv.org/abs/2111.15397?fbclid=IwAR2vCkHYiy5yuPPjWXpJgAJs-uD5NkH4liORt1ch4a6X_kmpMqagGtXyez4

責(zé)任編輯:龐桂玉 來(lái)源: 51CTO
相關(guān)推薦

2012-02-01 13:33:45

2025-03-17 00:00:00

OT系統(tǒng)安全運(yùn)營(yíng)技術(shù)

2020-06-08 14:44:19

運(yùn)維智能技術(shù)

2025-04-28 02:55:00

2020-11-06 08:43:21

AIOps運(yùn)維DevOps

2018-09-14 14:20:43

人肉智能運(yùn)維

2009-11-17 16:49:06

主動(dòng)運(yùn)維

2018-12-10 08:10:39

2018-09-27 08:59:29

2025-01-16 11:45:26

2023-03-06 11:35:55

經(jīng)營(yíng)分析體系

2025-01-26 09:25:08

2021-11-06 23:22:33

運(yùn)維IT企業(yè)

2009-09-16 13:38:33

運(yùn)維管理

2017-05-10 14:50:41

爬蟲掃描器python

2021-01-06 05:27:46

數(shù)據(jù)庫(kù)運(yùn)維角度

2018-09-21 09:15:39

2017-09-25 18:32:11

人肉智能運(yùn)維服務(wù)監(jiān)控

2025-05-16 10:25:11

點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)