Files
assist/src/analytics/__pycache__/token_monitor.cpython-310.pyc

118 lines
11 KiB
Plaintext
Raw Normal View History

o
SE<53>i/D<00>@s<>dZddlZddlZddlmZmZmZmZmZddl m Z m
Z
ddl m Z ddl mZddlmZdd lmZdd
lmZe<02>e<16>Ze Gd d <0C>d <0C><02>ZGd d<0E>d<0E>ZdS)uE
Token消耗监控模块
监控AI调用的Token使用情况和成本
<EFBFBD>N)<05>Dict<63>List<73>Optional<61>Any<6E>Tuple)<02>datetime<6D> timedelta)<01> dataclass)<01> defaultdict<63>)<01>
db_manager)<01> Conversation)<01> redis_managerc@sveZdZUdZeed<eed<eeed<eed<eed<eed<eed<e ed <e ed
<e
ed <d Z eeed <d S)<0E>
TokenUsageuToken使用记录<E8AEB0> timestamp<6D>user_id<69> work_order_id<69>
model_name<EFBFBD> input_tokens<6E> output_tokens<6E> total_tokens<6E>cost<73> response_time<6D>successN<73> error_message) <0C>__name__<5F>
__module__<EFBFBD> __qualname__<5F>__doc__r<00>__annotations__<5F>strr<00>int<6E>float<61>boolr<00>r$r$<00>E/Users/macos/Desktop/tsp-assist/assist/src/analytics/token_monitor.pyrs
 rc@s>eZdZdZdd<03>Zdd<05>Z  d0ded eed
ed ed ed e de
deede fdd<12>Z d
ed ed ede fdd<14>Z de fdd<17>Zde fdd<19>Zdededefdd<1E>Zdejde fd d!<21>Zd"ede fd#d$<24>Zd1ded&edeeeffd'd(<28>Zd1d&edeeeffd)d*<2A>Zd2d&edeeeeffd,d-<2D>Zd2d&edefd.d/<2F>ZdS)3<> TokenMonitoruToken消耗监控器cCs4ddd<03>ddd<03>ddd<03>d<07>|_dd d
d d <0C>|_dS) Ng<4E><67><EFBFBD><EFBFBD>Mb`?g<>~j<>t<EFBFBD>x?)<02>input<75>outputg-C<1C><>6J?g{<14>G<EFBFBD>z<EFBFBD>?g<><1E><>Q<EFBFBD><51>?)<03>qwen-plus-latestz
qwen-turbozqwen-maxgY@g4@i'g<><67><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>?)<04>daily_cost_limit<69>hourly_cost_limit<69>token_limit_per_requestZerror_rate_threshold)<02> token_prices<65>
thresholds<EFBFBD><01>selfr$r$r%<00>__init__%s<04><04><04><08> <0C>zTokenMonitor.__init__cCst<00><01>S)u获取Redis客户端)r<00>get_connectionr/r$r$r%<00>_get_redis_client>szTokenMonitor._get_redis_clientTNrrrrrrrr<00>returnc Cs<>z6||} |<00>|||<05>}
tt<02><03>|||||| |
|||d<01> } |<00>| <0B>|<00>| <0B>t<06>d| <09>d|
d<04>d<05><05>| WStyQ} zt<06> d| <0C><00><02>WYd} ~ dSd} ~ ww)u记录Token使用情况) rrrrrrrrrrruToken使用记录: u tokens, 成本: z.4f<EFBFBD>元u记录Token使用失败: N)
<EFBFBD>_calculate_costrr<00>now<6F>_save_to_redis<69>_check_thresholds<64>logger<65>info<66> Exception<6F>error) r0rrrrrrrrrr<00>usage<67>er$r$r%<00>record_token_usageBs2 <06>

<08><02>zTokenMonitor.record_token_usagecCs@||jvrd}|j|}|d|d}|d|d}||S)u计算Token成本r)i<>r'r()r-)r0rrrZpricesZ
input_costZ output_costr$r$r%r6ps

zTokenMonitor._calculate_costr>c Cs<>|<00><00>}|sdSzW|j<01><01>}|j|j|j|j|j|j|j|j |j
|j d<02>
}|<02> dt j|dd<05>|i<01>|<02> d|j<02><00>t j|dd<05>|i<01>|jrW|<02> d|j<03><00>t j|dd<05>|i<01>|<02>dd<08>WdStyz}zt<11>d |<05><00><02>WYd}~dSd}~ww)
u保存到RedisN)
rrrrrrrrrr<00>token_usage:dailyF)<01> ensure_ascii<69>token_usage:user:ztoken_usage:work_order:i<00>'u!保存Token使用到Redis失败: )r3rrrrrrrrrrr<00>zadd<64>json<6F>dumps<70>expirer<r:r=)r0r><00> redis_clientrZ
usage_datar?r$r$r%r8{sD
<06><04>
<04>
<04><08><02>zTokenMonitor._save_to_redisc
Cs<>zM|j|jdkr|<00>dd|j<00><00>d<04>|<00>|j<04><05><00>}||jdkr/|<00>dd|d<08>d <09>d
<EFBFBD>|<00>|j<04>}||jd krK|<00>d d |d<08>d <09>d<04>WdSWdStyh}zt<08> d|<04><00><02>WYd}~dSd}~ww)u检查阈值并触发预警r,Zhigh_token_usageu单次请求Token使用过多: <20>warningr*Zdaily_cost_exceededu今日成本超限: z.2fr5<00>criticalr+Zhourly_cost_exceededu每小时成本超限: u检查阈值失败: N)
rr.<00>_trigger_alert<72>get_daily_costr<00>date<74>get_hourly_costr<r:r=)r0r><00>
daily_costZ hourly_costr?r$r$r%r9<00>s4
<04> <04>  
<EFBFBD><06><08><02>zTokenMonitor._check_thresholds<64>
alert_type<EFBFBD>message<67>severityc
Cs<>z>ddlm}t<02><03><00>!}|d|<01><00>||||dt<04><05>d<05>}|<05>|<06>|<05><07>Wd<00>n1s/wYt<08> d|<02><00><02>WdSt
yY}zt<08> d|<07><00><02>WYd}~dSd}~ww) u 触发预警r )<01>Alertu Token监控_T)<07> rule_namerP<00>levelrRrQ<00> is_active<76>
created_atNuToken监控预警: u触发Token监控预警失败: ) <0C> core.modelsrSr <00> get_sessionrr7<00>add<64>commitr:rIr<r=)r0rPrQrRrS<00>session<6F>alertr?r$r$r%rK<00>s( 
<06>
<1C> <08><02>zTokenMonitor._trigger_alertrMc
Cs<>zM|<00><00>}|s
WdSt<01>|tj<03><04><00><02><05>}t<01>|tj<06><04><00><02><05>}|jd||dd<04>}d}|D]\}}zt<08> |<07>} || <09>
dd<06>7}Wq-tj yJYq-w|WSt yh}
zt <0A>d|
<EFBFBD><00><02>WYd}
~
dSd}
~
ww) u获取指定日期的成本<E68890>rAT<><01>
withscoresrru获取日成本失败: N)r3r<00>combine<6E>min<69>timer<00>max<61> zrangebyscorerE<00>loads<64>get<65>JSONDecodeErrorr<r:r=) r0rMrH<00>
start_time<EFBFBD>end_time<6D> usage_records<64>
total_cost<EFBFBD> record_data<74>_<>recordr?r$r$r%rL<00>s4<06> 
<02><08><02>zTokenMonitor.get_daily_costrc
Cs<>zN|<00><00>}|s
WdS|jdddd<03>}|tdd<05>}|<03><03>}|<04><03>}|jd||dd<08>}d}|D]\} }
zt<05>| <09>} || <0B>d d<02>7}Wq.tjyKYq.w|WSt yi} zt
<EFBFBD> d
| <0C><00><02>WYd } ~ dSd } ~ ww) u获取指定小时的成本r^r)<03>minute<74>second<6E> microsecond<6E>)<01>hoursrATr_ru获取小时成本失败: N) r3<00>replacerrrerErfrgrhr<r:r=) r0rrHZ
hour_startZhour_endrirjrkrlrmrnror?r$r$r%rN<00>s8<06> 
<02><08><02>zTokenMonitor.get_hourly_cost<73><00>daysc
Cs z<>|<00><00>}|s
iWSt<01><02><00><03>}t<01><02>t|d<01><00><03>}|jd|<01><00>||dd<04>}ddddddtt<07>tdd<08><00>d <09>}g}|D]<5D>\} }
z<EFBFBD>t<08> | <09>} |d
| <0B>
d
d<05>7<|d | <0B>
d d<05>7<|d d7<| <0B>
dd<03>ru|dd7<n|dd7<| <0B>
dd<13>} |d| d7<| <0B>
d<15>r<>|<08> | d<00>t<01> |
<EFBFBD><01> d<16>} |d| d| <0B>
d
d<05>7<|d| d | <0B>
d d<05>7<Wq<tjy<>Yq<w|r<>t|<08>t|<08>|d<|d dkr<>|d|d |d<nd|d<t|<07>WSt<12>y}zt<13>d|<0E><00><02>iWYd}~Sd}~ww)u获取用户Token使用统计<E7BB9F>rwrCTr_rr^cSs
ddd<02>S)Nr)<02>tokensrr$r$r$r$r%<00><lambda>;s
z3TokenMonitor.get_user_token_stats.<locals>.<lambda>)rrl<00>total_requests<74>successful_requests<74>failed_requests<74>avg_response_time<6D> model_usage<67> daily_usagerrlrr{rsrr|r}r<00>unknownrr<00>%Y-%m-%dr<64>ryr~<00> success_rateu获取用户Token统计失败: N)r3rr7rrrer
r!rErfrg<00>append<6E> fromtimestamp<6D>strftimerh<00>sum<75>len<65>dictr<r:r=)r0rrwrHrjrirk<00>stats<74>response_timesrmrror<00>date_strr?r$r$r%<00>get_user_token_stats"sh <06>
<06> 
  
 $<02> 
<08><02>z!TokenMonitor.get_user_token_statsc
Cs&z<>|<00><00>}|s
iWSt<01><02><00><03>}t<01><02>t|d<01><00><03>}|jd||dd<04>}dddddt<06>tt<08>tdd<08><00>d <09>}|D]<5D>\}}z<>t <09>
|<07>} |d
| <09> d
d<05>7<|d | <09> d d<05>7<|d d7<| <09> dd<03>rq|dd7<n|dd7<|d<00> | <09> dd<14><02>| <09> dd<16>}
|d|
d7<t<01> |<08><01>d<18>} |d| d| <09> d
d<05>7<|d| d | <09> d d<05>7<|d| dd7<Wq8t jy<>Yq8w|d dkr<>|d|d |d<nd|d<t|d<00>|d<t|<06>WSt<12>y} zt<13>d| <0C><00><02>iWYd} ~ Sd} ~ ww)u获取系统Token使用统计rxrATr_rr^cSs dddd<02>S)Nr)ryr<00>requestsr$r$r$r$r%rz<00>s z5TokenMonitor.get_system_token_stats.<locals>.<lambda>)rrlr{r|r}<00> unique_usersrr<>rrlrr{rsrr|r}r<>r<00>rr<>rr<>r<>ryr<>r<>u获取系统Token统计失败: N)r3rr7rrre<00>setr
r!rErfrgrZr<>r<>rhr<>r<>r<r:r=) r0rwrHrjrirkr<>rmrrorr<>r?r$r$r%<00>get_system_token_statsksd <06>
<06> 
    <02> 
<08><02>z#TokenMonitor.get_system_token_stats<74>c
Cs<>z*g}t|<01>D]}t<01><02><00><03>t|d<01>}|<00>|<04>}|<02>|<04><07>|d<02><02>qtt |<02><01>WSt
yF}zt <0B> d|<06><00><02>gWYd}~Sd}~ww)u获取成本趋势rx)rMru获取成本趋势失败: N) <0A>rangerr7rMrrLr<><00> isoformat<61>list<73>reversedr<r:r=)r0rwZ
trend_data<EFBFBD>irMrOr?r$r$r%<00>get_cost_trend<6E>s 

<EFBFBD><08><02>zTokenMonitor.get_cost_trendc
Cs<>zH|<00><00>}|s
WdSt<01><02>t|d<02><00><04>}|<02>dd|<03>}|<02>d<04>}|D] }|<02>|d|<03>q#|<02>d<05>}|D] }|<02>|d|<03>q4t<07>d|<04><00><02>|WSt yc}zt<07>
d|<08><00><02>WYd}~dSd}~ww) u清理旧数据rrxrAztoken_usage:user:*ztoken_usage:work_order:*u&清理Token监控数据成功: 数量=u清理Token监控数据失败: N) r3rr7rr<00>zremrangebyscore<72>keysr:r;r<r=) r0rwrHZ cutoff_time<6D> removed_countZ user_keys<79>keyZwork_order_keysr?r$r$r%<00>cleanup_old_data<74>s.<04>

<08><02>zTokenMonitor.cleanup_old_data)TN)rv)r<>)rrrrr1r3r rr!r"r#rr@r6r8r9rKrrMrLrNrrr<>r<>rr<>r<>r$r$r$r%r&"sF <04><02><02><02><02><02><02><02> <02>
<EFBFBD>. -  #I Er&)rrE<00>logging<6E>typingrrrrrrr<00> dataclassesr <00> collectionsr
<00> core.databaser rXr Zcore.redis_managerr<00> getLoggerrr:rr&r$r$r$r%<00><module>s