, L: m* E: Q L0 Q1 cfrom fastapi import Depends, FastAPI, BackgroundTasks, Response, Cookie, HTTPException ( H, S. J* T4 e$ {from fastapi.middleware.cors import CORSMiddleware$ O' z5 p" p4 G# d# D; \
from sqlalchemy.orm import Session5 J/ v. W6 e; V4 B2 o8 D7 l! y
from typing import Optional, Dict 3 _ P! c) m& t. `, Pimport crud, models, schemas ! \% U, X3 p5 |, Q2 O. p8 zfrom database import SessionLocal / E* R5 O3 e$ V1 {1 g- L% pfrom TopicModelTrainingTask import ** @, \% S4 b1 `5 R6 f6 K/ F# p
import uuid # c) i& N0 }* w. J, O+ a& v$ \9 o! A% q2 \0 _
app = FastAPI() $ ~; w/ b# q: L) X* s; O% [, L 1 o; h6 W0 W2 u% E, F6 a# j# 配置跨域问题 8 c! E0 o' _7 j9 X: X7 Lorigins = [ / h9 z# a; \2 P. G "http://localhost:8000",! P+ l% M7 z4 |, i
"http://localhost:3000" , A+ P( J0 l. H; \! k# j6 G]; |" R) e& c0 n0 l* k1 s4 Z
6 @7 f) c( D( r/ I* e! R
# 全局主题模型训练对象 & g3 t# m0 B& ]3 p8 Y; o) d+ itopic_model_training_tasks: Dict[str, TopicModelTrainingTask] = {}# }4 X' G: [7 V5 w7 ~
* ?8 ?. l+ {* ~* c- ^9 C
app.add_middleware(0 l5 B' A5 n# A3 S$ v6 }
CORSMiddleware, + H1 N1 t3 a9 G8 A2 C. }9 T; T$ U allow_origins=origins, 6 m" {. X1 ~1 H9 O! o allow_credentials=True, ) f, z: O( k, P' @ allow_methods=["*"],( a n6 L; p A0 G
allow_headers=["*"],) S, V7 y: S; B* R* M- i
)! b; D7 U" \6 v8 R( M# {2 z
* I! }: L# u1 A8 T
. a' \: _2 F5 T) Y
# 数据库连接依赖 5 ]# M0 p2 f) B; } Pdef get_db():& Y# F# G' P: a( P( ]) [1 r) F; n
try:. S6 W& T, p3 w6 W! I
db = SessionLocal()5 h' V8 e5 ]0 f3 }. n
yield db5 l$ Q) R- x4 h* [
finally:( A1 C" b0 Z n9 T
db.close()1 n" ~# Y; }) s: b% m0 e
) Y8 W+ `, ?! Q2 P& Q; u- O$ n
8 V) S$ u) B" `+ }" v. c% |
@app.get( # Y7 p0 n" h; A; P "/bilibilivideos/", $ H, y/ B3 |) A response_model=List[schemas.BilibiliVideo],5 r/ q, d( b& \6 T2 h+ J W* k
tags=['bilibili视频评论语料库数据接口']) G6 \5 A V( J% L" a
)5 {: Y2 C+ Q6 h8 o+ Q3 N
def get_bilibili_videos(db: Session = Depends(get_db)): ' _4 w/ ?- h, Y- g db_videos = crud.get_bilibili_videos(db)( I% |: p: x. O, H* w
return db_videos 0 q' ]; q! e2 }+ U7 I0 | , M5 Q' |* c1 V+ U1 ]$ w/ x6 g U
@app.get( 1 h" @0 n) a8 z. v "/bilibilivideos/{vid}/", ! X) k. v0 y: p6 H response_model=schemas.BilibiliVideo, B9 a0 N: O% S# n) p# e* D2 [
tags=['bilibili视频评论语料库数据接口']9 b& j8 O8 w3 D
) 1 x7 c, S$ X/ _- ldef get_bilibili_videos_by_vid(vid: int, db: Session = Depends(get_db)): ! g) N( }6 T- c8 \" v' j* e db_video = crud.get_bilibili_videos_by_vid(vid, db) & Z0 q+ H s, c K" r return db_video & J( c4 f& O8 _$ v. k' H0 a" r0 K: j- [! h
/ V2 V$ Y- S9 o: a2 m7 E. y
@app.get(7 U8 R0 ]2 p# H0 E4 \
"/bilibilivideos/{vid}/comments/", 6 a. I6 t3 j5 A3 T+ u response_model=List[schemas.BilibiliVideoComment], % D. x+ i6 k0 c0 ~2 L+ ^ tags=['bilibili视频评论语料库数据接口'] 3 @3 y. \$ u1 |; r0 W: c), ^0 ]. @) p, K6 @; u. p$ [3 T
def get_bilibili_video_comments_by_vid(vid: int, db: Session = Depends(get_db)):. E7 V0 Z) K) f
db_comments = crud.get_bilibili_video_comments_by_vid(vid, db) 3 }9 x+ _' B+ @" _$ o; e* T, A' Y) m return db_comments9 R2 {/ Z; A2 C% d }- d3 q; q+ }9 ^
% H& L7 }: G3 M, ?- i7 |8 _; T : \# D8 m# j) N( X, ^! Q- L@app.get( # q2 ~- P. y, A/ |8 ? "/onlineShoppingReviews/", ) q$ _( p. u! M response_model=List[schemas.OnlineShoppingReview], . @' x- t2 k# i! _ tags=['电商购物评价语料库数据接口']8 D4 G( I; `$ W: E0 [) q
) * k* Q6 h0 J" h# K# R8 S8 A1 Q: ~) Rdef get_online_shopping_reviews(db: Session = Depends(get_db)):) h: ?3 N) j/ K( |1 f; ?
db_reviews = crud.get_online_shopping_reviews(db)( D) g2 P) C7 G `- M
return db_reviews % Y# E' F: ]% I$ _) w3 o 4 ? B& t8 w" g& P8 w- c: o0 n$ C6 C9 V
@app.get(! m- K% W, R: _" N
"/takeawayReviews/", + j3 o9 d" v! c/ l3 O) {- d response_model=List[schemas.TakeawayReview], / D! |& U r# R* [. h tags=['外卖评价语料库数据接口']5 p* h( D' { D* g+ \
)' M) U t5 X7 j: p, @5 I8 i/ H
def get_takeaway_reviews(db: Session = Depends(get_db)):) }3 V& R2 @5 j
db_reviews = crud.get_takeaway_reviews(db)% R- p9 O5 N. p/ z1 e
return db_reviews' `! [" C* J S8 N4 M5 |! Y5 B
: P6 c6 P0 f/ |8 u& p
2 w5 F# W" x/ L/ W# l- H
@app.get(, g! c X# n% v0 j, z) J
"/chineseLyrics/",3 Z$ X: ~/ b) X" K1 {* ~/ C( w
response_model=List[schemas.ChineseLyrics],, S% r8 W1 h! m; m; S9 M
tags=['中文歌歌词语料库数据接口'] ' b* X8 l1 O* N7 f) # K6 x. u3 \% `def get_chinese_lyrics(db: Session = Depends(get_db)): ! m, w! f, ^4 ?3 G db_reviews = crud.get_chinese_lyrics(db)2 s9 l) L" I8 Q/ `' A+ B3 ~
return db_reviews $ A5 Q3 E; a* ~4 z6 h1 Q) } ) p# v: k, p$ k* K0 B( _. c7 I. T: X# k5 E( R; ^9 H# I% K
@app.get( 4 B# m( B! Y/ z) k "/COVID19News/",+ d5 U8 U+ z. b( H8 E
response_model=List[schemas.COVID19News], $ U7 g& {6 J, p% f4 \0 d0 ? tags=['新冠病毒新闻语料库数据接口']0 {: t2 T% B z# Z
) ^1 P. `7 _/ mdef get_COVID19_news(db: Session = Depends(get_db)): 5 N7 `6 C/ `, J# H6 O& a db_reviews = crud.get_COVID19_news(db) & }8 w- l- s2 y; O1 { return db_reviews - N( e6 i( O$ r& V5 C" o1 c8 _8 L 7 @3 O0 A. I3 b; u" T3 |4 ?4 f. r
# 为每个用户设置uuid标识符,并存入Cookie ! A' }( D" Y4 E; \' p' `def create_user_uuid_and_set_cookie(response: Response): $ |" m" M. j$ B$ F$ @& d* h/ @ user_uuid = str(uuid.uuid1())3 e8 ^6 M0 b S# C
response.set_cookie(key="user_uuid", value=user_uuid) ; m6 ~/ o' o) P* m1 r+ g) } return user_uuid, ?+ {9 J% e3 V
4 j% R- d, u2 P, Y
9 ~4 d) n5 h- Z' L8 K3 u
@app.post( 7 w- a; D {& N; h7 l5 q c! M( @ "/calculate/preprocessing/", 6 A- u% q6 R: S3 v. y9 P: Y) r tags=["计算模块数据接口"] # [' o8 L1 h9 b8 }- }, R9 b: Y)( R; L: D6 ~5 B
async def run_text_preprocessing_task(text_preprocessing_params: TextPreprocessingParams, ' y! e& s( M' p" i' i# |( b background_task: BackgroundTasks,# L2 ^! A7 V' i& Q/ e2 Z: t
response: Response, ) Y; }3 k! G5 s7 d4 E+ q% w user_uuid: str = Cookie(None)): ; b* G. X$ y( P2 @) A) W0 L+ N2 k if not user_uuid:, ?$ u. I8 c. r4 m4 e9 V2 l
user_uuid = create_user_uuid_and_set_cookie(response)& z; x- E. C) L; l2 ~
5 w% N! {: a1 u+ `5 O) E" `
global topic_model_training_tasks ' L: k& c7 U) S Z, z$ t! {; r6 q task = TopicModelTrainingTask(text_preprocessing_params) 6 W- u- {- e$ n% { topic_model_training_tasks[user_uuid] = task / X9 r, [% v& q* m4 c : G& J" S' `: S8 v background_task.add_task(task.preprocessing); ]0 M* J" P( x) K
return {"message": "已添加文本预处理后台任务"} ! a# w, Y% l# Y% N) n7 H/ x. ]3 N4 o/ ~- s5 P
; |0 e) Y+ F) C8 _
@app.post(4 v; I2 S+ Q+ T z; H
"/calculate/nmftraining/",9 y) V* W3 Z6 \5 j
tags=["计算模块数据接口"]8 X% c8 O! W* e4 @- v2 r
) ) F. }% y) k/ ^# j3 ` Tasync def run_nmf_training_and_tsne_task(nmf_training_params: NMFTrainingParams,# N- z# L4 n; z$ |9 _# Z
background_task: BackgroundTasks,' b' n' Q9 S. O- h5 Y* d* |2 |% |
response: Response, * ]& z. L) c+ g; M user_uuid: str = Cookie(None)):) k% r3 Z; n' P5 k8 n! d
if not user_uuid:& D# s1 | X& j# c
user_uuid = create_user_uuid_and_set_cookie(response) / o: \/ V& |, {7 l+ [, ]) K6 ? + [ [/ B! H" i8 H3 y global topic_model_training_tasks - h$ G1 Z5 ~) [4 G1 O3 w) a$ X2 O5 B6 R& J4 j+ Q% Z
if user_uuid and user_uuid in topic_model_training_tasks:5 L" [2 M" {& Z" l5 X0 P! O$ X
task = topic_model_training_tasks[user_uuid] ; F! w7 M/ y3 l/ Z! S6 m2 L if task.text_preprocessing_progress.status_code == 2:" S( n4 o' g0 K( }) r+ R$ m
background_task.add_task(task.nmf_training, nmf_training_params)3 v! W& m, A' l* b# ]7 |6 w
return {"message": "已添加NMF主题模型训练后台任务"} 5 J% }) @2 E7 S else: # j2 U5 a4 l* E% ~ raise HTTPException(status_code=404, detail="请先进行文本预处理任务!")- t! Q8 M, z! \. ?
else: k# ~5 s; x" M raise HTTPException(status_code=404, detail="未找到相应的训练对象!")/ R4 P- s- X. |0 A5 m- ~
0 t7 w2 }5 _3 v! \
{4 L6 q6 b# K: M/ [@app.get( 8 E7 v8 h2 D* v8 N "/calculate/nmftraining/keywordsearch/",2 {" w; G7 ^5 B! X$ b
response_model=KeywordSearchResult, e, F+ j7 F) H5 @0 F7 n
tags=["用户交互"] a) V9 w; a w0 m1 r1 M8 M
)4 d# X$ S# x3 _' v
async def search_keyword(search_text: str, * Y" g+ @( J: d) J response: Response,9 R) e; {, o' e( X! ]( f" W2 J
user_uuid: str = Cookie(None)):, y% {# g! F: f2 J, @
if not user_uuid:- F$ W7 u- o" D. {" J( v3 i
user_uuid = create_user_uuid_and_set_cookie(response)( w) d' x" o) u
3 n8 X I! A' ^1 i& F" c5 z
global topic_model_training_tasks4 ?" b3 }7 f# V+ G/ l, o
7 \8 C6 J8 m1 i if user_uuid and user_uuid in topic_model_training_tasks: & f. Y( U1 S l( B task = topic_model_training_tasks[user_uuid]: k1 m. `' B! A, e/ x% l# a* u
if task.text_preprocessing_progress.status_code == 2: $ h% T |; B9 L4 L search_text = search_text.lower() 6 ?/ k1 E% }' A" l ] bag_words = task.text_preprocessing.bagWords 0 `6 ?7 c/ u( K& v7 B; u5 X0 I keyword_search_result = KeywordSearchResult() / f4 M/ o; Y: m for wi, word in enumerate(bag_words): + [1 Z. y# g& o if search_text in word:% ?: d" |# M4 o& m
keyword_search_result.word_id_list.append(wi) 8 Q" J1 ^! D) ^: `) |' D keyword_search_result.word_list.append(word) ! M8 q, f% H4 ?% A( d9 c% I" { return keyword_search_result ( E* q8 [; l" N8 Q. I! q9 \* e1 l a else:' t6 s$ i, S% s& \
raise HTTPException(status_code=404, detail="请先进行文本预处理任务!") 7 `' T/ k0 X' ~5 d* S9 d1 B0 ` else:! |7 m9 P1 c) Q, m
raise HTTPException(status_code=404, detail="未找到相应的训练对象!")$ V7 ?6 _1 s X* g" s
3 p h# _2 G( X Q+ T+ w3 a$ o8 Z; P$ S
5 J& O6 E7 T9 z$ K- I( A* J% |
@app.post(# C6 \1 ~& {* |; ]. G0 ]
"/calculate/nmftraining/topickeywordoptimization/",) s2 p; A3 b+ B& z3 m% x
tags=["用户交互"], D1 n5 k- J: r7 E" l9 X" G
) , u" m8 U7 l Qasync def run_topic_keyword_optimization_task(tko_params: TopicKeywordOptimizationParams, " Z3 a. ^5 `8 C background_task: BackgroundTasks,. B, Z* `4 D" d8 ~, |7 b1 V4 `
response: Response, - H) R1 t2 b7 O# g user_uuid: str = Cookie(None)): - t2 A- X( h" L if not user_uuid:0 }7 [% m- Z- r0 U3 i, t" n
user_uuid = create_user_uuid_and_set_cookie(response) 4 ]' h9 v! k$ ]5 J! r" g* S5 A# r. V( ^' s
global topic_model_training_tasks : Y0 l2 e+ |6 ^2 S$ o0 Y8 d* t* `7 }) d- |( q8 J; P# i$ v- g
if user_uuid and user_uuid in topic_model_training_tasks:* b( k6 [) Y: o5 [) W( e
task = topic_model_training_tasks[user_uuid], c+ B6 \! S6 B1 e5 H; P
if task.nmf_training_progress.status_code == 2: 7 k, T0 ^0 o: j8 U! I0 ^1 n- ? background_task.add_task(task.topic_keyword_optimization, tko_params)6 X& V2 L2 r' ^3 m0 O
return {"message": "已添加主题关键词优化后台任务"} , m. m3 s$ F0 b' e* O# R else: $ N- ]% }0 ?0 p' ?/ R; G raise HTTPException(status_code=404, detail="请先等待NMF训练结束!")! O9 [ D( U- Z5 e- _. e- A
else:# f5 q5 q3 q$ k9 W# k$ Z6 X
raise HTTPException(status_code=404, detail="未找到相应的训练对象!")3 T" @) Q" u5 [$ ]
5 E9 |1 E2 @( S1 f. y' `0 v9 |) ~0 Z3 `5 I( t9 x+ [
@app.post( E3 T4 \9 ^2 v/ f' M4 j, q "/calculate/nmftraining/topicsplit/", 5 z; W- b4 V; f) ~) V, p2 f tags=["用户交互"]9 H! }& r9 T9 Q- U
)6 L' B; y" P4 K1 T
async def run_topic_split_task(ts_params: TopicSplitParams, 5 [0 W0 |/ t$ h1 P( u& P background_task: BackgroundTasks, - I& ~! L8 w3 C8 h! K+ B4 U response: Response, 1 w( Y0 u `& z1 f# R" ^' b/ n' m2 E user_uuid: str = Cookie(None)): W) L" B, j# l: h if not user_uuid:# @4 a1 }! \' e2 [
user_uuid = create_user_uuid_and_set_cookie(response) ; y: Z* \9 M4 `8 ~ # X) |, U+ P; O+ N1 k4 ?; n global topic_model_training_tasks* f8 s) q9 b) m
6 O1 c% p5 T) d# v- r
if user_uuid and user_uuid in topic_model_training_tasks: 9 Z8 v- R* o# \8 o2 u- x+ f task = topic_model_training_tasks[user_uuid]2 U! b6 v. Y$ ~/ J5 \& W
if task.nmf_training_progress.status_code == 2:- f) v: O( _, Q6 f7 T' U
background_task.add_task(task.topic_split, ts_params) 6 U9 z% {% N* ~; U: Q2 P6 w return {"message": "已添加主题拆分后台任务"} " A8 J$ f; Y J) {8 C: W1 t else: , M& Q/ m* ]+ K/ P, U4 D5 C5 x raise HTTPException(status_code=404, detail="请先等待NMF训练结束!")$ O& d4 e4 R K$ }5 m, O
else: 5 J2 I, u5 |7 Z/ B& o) p- X. f7 n S raise HTTPException(status_code=404, detail="未找到相应的训练对象!")* v" L; T4 A# w
- d) E( H4 \* V) B9 M9 K9 z / X9 v2 D( {$ ]% X$ O6 z1 x@app.post( 7 B) ^) A5 U$ ~# \ "/calculate/nmftraining/topicmerge/", # O, S4 W V1 Y; a" N- |! } tags=["用户交互"] 7 G% | g, y$ N, t)/ t. q; @' n' m/ ?( n# \
async def run_topic_merge_task(tm_params: TopicMergeParams,; E% y1 ^& ]8 f' x( f7 |
background_task: BackgroundTasks, ( Y9 c- X& a) m response: Response, " k& U8 Z; ]8 }0 {- } user_uuid: str = Cookie(None)): % L0 O& Y L( P1 b% [$ f. o if not user_uuid:# U8 @3 I" j6 t D$ m" V
user_uuid = create_user_uuid_and_set_cookie(response) # J, `$ ]# V. r+ h! P' q U3 J( f i1 T
global topic_model_training_tasks: d- A/ Q, H& k* q2 `' k/ r
5 k; E9 G2 B) b: w% ?8 P( C8 b if user_uuid and user_uuid in topic_model_training_tasks: + z# v8 G" P8 O, Q6 w6 G4 \ task = topic_model_training_tasks[user_uuid] ' |' R% g# S, w if task.nmf_training_progress.status_code == 2:/ `! S; \9 ^) H& u# N
background_task.add_task(task.topic_merge, tm_params)# g ?/ K1 Y6 s s
return {"message": "已添加主题合并后台任务"} " P8 ^7 G2 M( F& _$ p% J9 k& I& m$ E else: 9 w* e1 Q6 p7 `3 Y% |5 T: c raise HTTPException(status_code=404, detail="请先等待NMF训练结束!") 6 l9 W- n4 p: p; a1 ] else: - c0 g- f4 M: E3 R/ Q6 I# @ raise HTTPException(status_code=404, detail="未找到相应的训练对象!") * r- x* B% T# P/ J/ A# d7 w2 q" Z ?# v0 P
2 }* O( f/ m- e# e6 z" f
@app.post(* W* b: u# u+ o8 P, `
"/calculate/nmftraining/keywordinducedtopiccreate/",/ ~. o5 \" K; Z; B& ` C+ N7 k
tags=["用户交互"]* a/ B4 t: f; v6 `% e$ c, J
)1 R* ]5 O k2 @. x) G+ a
async def run_keyword_induced_topic_create_task(kitc_params: KeywordInducedTopicCreateParams, - V; V& L8 t: t- S background_task: BackgroundTasks, - ^$ `+ A* v0 k% u o: } response: Response, ! d4 m% i8 M1 }! Z+ h user_uuid: str = Cookie(None)): 4 S( e- I' C- R) u! k/ c7 S" j, Z if not user_uuid:& z: i8 _. I& L5 z
user_uuid = create_user_uuid_and_set_cookie(response)$ T& @# y6 x- ]7 ^: {/ v9 q
2 l6 C' C5 i1 s5 m9 |# [
global topic_model_training_tasks5 o' ]0 M" N; t: g. A. |# @5 J, x
+ s7 M' U0 r6 E5 r
if user_uuid and user_uuid in topic_model_training_tasks: ( x( f4 _& D) z' Z4 R- F/ T7 f0 _, f task = topic_model_training_tasks[user_uuid] - `; `! N) X/ G9 @! r* H& F if task.nmf_training_progress.status_code == 2: - g: U% ~1 N C' M5 T: V2 } background_task.add_task(task.keyword_induced_topic_create, kitc_params)2 z- a# u9 e9 {6 G& M6 l
return {"message": "已添加关键词诱导主题创建后台任务"} 8 B* V6 D* `, n& Q1 J1 G* g else: ( v0 g+ R, Y5 M6 ]! p6 _1 Q raise HTTPException(status_code=404, detail="请先等待NMF训练结束!")) @1 F8 F' D5 W2 L! p
else: * u) L7 Y8 j5 P4 a raise HTTPException(status_code=404, detail="未找到相应的训练对象!") % [! q# L2 ?* J3 \ ; m+ M% n) Z3 d- X# T) T( n6 T- H4 R, h, @# {! H4 ^
@app.post( 0 J4 S0 }" f, V' ?4 d "/calculate/nmftraining/documentinducedtopiccreate/", , F7 T, G+ P6 J0 u+ o/ `, C7 O tags=["用户交互"] : {0 F1 n9 b' e& ]& x, N1 g0 Z P); d; w/ U' K' Q. N) F$ a: G8 y
async def run_document_induced_topic_create_task(ditc_params: DocumentInducedTopicCreateParams, 9 B' n* i$ o$ m* v background_task: BackgroundTasks, 8 G/ c. [( r1 k' w3 Q response: Response,: W$ u+ V! d6 V# o
user_uuid: str = Cookie(None)): # K6 c4 [. T: `8 O0 ^/ }. e! R if not user_uuid:6 B B$ t, W+ s' u5 v0 n; e" ~# H6 E: W% m
user_uuid = create_user_uuid_and_set_cookie(response) - M V( E& b/ k, } @8 O 7 U/ @4 b7 E! s% i, ^6 ^6 h5 Q& [ global topic_model_training_tasks$ Q4 b% E: z0 v& ^
0 I: y: r: ]3 a; y
if user_uuid and user_uuid in topic_model_training_tasks: 8 C- ?$ B4 T% r task = topic_model_training_tasks[user_uuid]! ]9 k, q! L- z: Y+ c0 I* O
if task.nmf_training_progress.status_code == 2: $ |) k2 u9 K1 v background_task.add_task(task.document_induced_topic_create, ditc_params)1 Z- G0 x6 g9 r6 v6 X
return {"message": "已添加文档诱导主题创建后台任务"}0 B/ o" k. u4 H- j
else: 9 K* A) E V9 K/ j$ s- y6 D) E raise HTTPException(status_code=404, detail="请先等待NMF训练结束!")3 i0 g8 _; T3 i. m
else:/ Y: N0 j2 D. x& r3 T
raise HTTPException(status_code=404, detail="未找到相应的训练对象!") , R: T6 a3 g. `4 z% b5 {+ f% A3 U) z; y( R7 P8 b5 [
7 M3 S5 C: j7 n& y; w# a2 d@app.get( 2 Z$ W/ s4 J/ T' t$ S$ N: w1 m+ ~ "/calculate/nmftraining/newdoctopicdistributionpredict/",( }; n0 {0 {- f2 u+ t
tags=["主题预测"]7 x# P* Q3 k$ y6 Z% p3 _5 Y: h
) 9 y; t; K) M, Xasync def run_new_document_topic_distribution_predict_task( $ P9 v0 W1 P1 S# r$ _) w new_doc_text: str, ! ~; p+ v2 E) f. E r$ m background_task: BackgroundTasks,$ O# K( l9 x$ E" N) f8 [
response: Response,9 U% n% X" R+ h) m9 \/ \% d
user_uuid: str = Cookie(None)): 3 b2 ~: P9 Z; `1 `7 @6 J" B1 w if not user_uuid: 1 v2 K. X8 |+ m0 S" y user_uuid = create_user_uuid_and_set_cookie(response)/ ^5 C# r9 d( K% T5 U0 j
. N# Z: o0 @( a& O
global topic_model_training_tasks , N3 i( E+ i/ P: i. a; W, E x+ J- R2 v2 a
if user_uuid and user_uuid in topic_model_training_tasks:& O9 D9 f' w" ?6 e$ u) W4 I; O6 w1 t
task = topic_model_training_tasks[user_uuid] 1 S: J! t- o# N. V$ v$ B/ `' e if task.nmf_training_progress.status_code == 2: + |; K; g& D% ?% L background_task.add_task( # |$ ~5 k* F4 n k5 n task.new_doc_topic_distribution_predict, ' a+ e5 W$ w/ X- c7 n2 @ new_doc_text 6 T; E, n/ A+ i6 ^) u ) ( `3 {5 Q; p/ v. ~4 r7 Z, l, ?2 {0 ^ return {"message": "已添加新文档主题分布预测后台任务"} : {& L/ d: ^) {( U6 O else:# ?3 X* \. O0 L0 M
raise HTTPException(status_code=404, detail="请先等待NMF训练结束!")$ g+ A* h7 L; K7 b7 ?- i" E
else:0 d; j. K- Z. M3 S9 V
raise HTTPException(status_code=404, detail="未找到相应的训练对象!")( ~! K0 N5 P# H8 J! @
) ~1 d/ z9 B n
! q8 s# n8 v4 H, }2 ]" A* X# @
@app.get( 1 {: d3 L) T, p. S& T% i: k "/calculate/preprocessing/progress/",4 G# @% Z! a* q( O0 a3 `
tags=["计算模块数据接口"],5 q( v3 V7 U v( U( ]" l* Q
response_model=TextPreprocessingProgress 6 `* |( n7 z8 l) 4 z8 B8 Z( l2 @6 Q, Mdef get_text_preprocessing_task_progress(user_uuid: str = Cookie(None)):! G: _7 r( p- g
global topic_model_training_tasks- W. c, N/ f: X( z; \6 b
& C+ A+ i/ L; x if (not user_uuid) or (user_uuid not in topic_model_training_tasks): ) S( \. t5 H) b raise HTTPException(status_code=404, detail="未找到相应的训练对象!")3 ?5 C& M7 }& N6 b5 r0 Q, Z' |3 B
return topic_model_training_tasks[user_uuid].text_preprocessing_progress) j5 i- A O/ X7 i5 T
4 O6 `# S. B+ w6 B ( V* ~2 w( D: k8 n@app.get( $ K: F3 l( v. j4 E "/calculate/nmftraining/progress/",/ H* H: p; u1 d) o$ F6 {4 C
tags=["计算模块数据接口"], : {1 N$ a. `! D2 p7 D response_model=NMFTrainingProgress F. B) e. O6 B7 s): L. N# U' A! Y' M* I
def get_nmf_training_task_progress(user_uuid: str = Cookie(None)):5 D+ X+ O' h. q
global topic_model_training_tasks # B& Q' i/ t5 ?4 |. R: [) R0 X. d4 x d V6 n( p
if (not user_uuid) or (user_uuid not in topic_model_training_tasks):: _) L0 {, j5 [2 f7 Z7 M
raise HTTPException(status_code=404, detail="未找到相应的训练对象!")* y- E( H& a+ w0 I0 A
; D. A/ I- Q1 I8 S. F8 W
task = topic_model_training_tasks[user_uuid]+ R6 I2 ?- E- p+ Z% H
if task.text_preprocessing_progress.status_code == 2:& T. X# o% w0 e2 c* x8 L5 z
return task.nmf_training_progress 9 ]5 q% O1 c( Q7 P, S else: ( C/ ^; x) m( D3 Z7 n! A' n raise HTTPException(status_code=404, detail="请先进行文本预处理任务!") 5 G9 n7 t' |0 S+ t# r ?& {5 M' {! @4 m: V# z. I
/ f+ C% r, U- |$ m" G* s% w4 [: o@app.get(2 @$ k2 y# I; W" `2 r
"/calculate/umap/progress/", $ I5 c s; a% S" B n7 i' t tags=["计算模块数据接口"],- [& v# L" |& N+ J
response_model=UMAPProgress+ F; D5 o9 i' p. k ^( L I5 s
) y2 d# w7 J. K, }" I5 kdef get_umap_task_progress(user_uuid: str = Cookie(None)): # q1 u5 l! q* h& b global topic_model_training_tasks3 u/ w' i( D6 i3 ^) o: F
8 h2 O: g# _. G7 q7 K m if (not user_uuid) or (user_uuid not in topic_model_training_tasks): . T+ y! _; _3 c5 Z raise HTTPException(status_code=404, detail="未找到相应的训练对象!") 7 j4 O' f9 x8 k' B- i% ^1 [8 t0 Z6 g: \
task = topic_model_training_tasks[user_uuid]$ ?7 o8 I" M3 P8 m" E# j
if task.nmf_training_progress.status_code == 2: ! u$ S r9 D5 U6 }, m2 v return task.umap_progress3 L8 }9 V2 T2 E! A2 O% J9 Z8 x: I5 T
else: 4 x2 C; Z: p" d9 o5 d9 z' I, O% | raise HTTPException(status_code=404, detail="请先等待NMF训练结束!")$ C$ ]6 v. l% H" s% B7 I
I7 y1 t5 M! x( V9 B) e9 W2 ~3 g) l F! Q6 a
@app.get(5 x. m0 D* `+ G {' @- D
"/calculate/nmftraining/predict/progress/",( g3 X, L. J5 z, J Z
tags=["计算模块数据接口"], x- q1 Z/ k, w' o! w" m response_model=NewDocTopicDistributionPredictProgress ; }( e: v1 |* O; ?) h1 W; I) . h7 N7 v: g5 b7 U( j7 n' Vdef get_new_doc_topic_distribution_predict_task_progress(user_uuid: str = Cookie(None)):) q/ C3 |7 ?6 r
global topic_model_training_tasks( G( ^5 ?+ Z4 U/ f& }+ s
& E& e4 |& h* p if (not user_uuid) or (user_uuid not in topic_model_training_tasks):$ t `# C1 X& Z% x
raise HTTPException(status_code=404, detail="未找到相应的训练对象!") : ^. M1 t7 F8 ` 0 v$ n+ Q# j0 {5 Y task = topic_model_training_tasks[user_uuid] 1 ] V; H: @9 }" k if task.nmf_training_progress.status_code == 2: / r6 c* g3 H. c4 m4 v; a1 h/ `/ D9 j3 U return task.topic_distribution_predict_progress * a1 R0 n& T7 D5 q, l q else: # C) o3 A1 o3 _9 I B" L: X8 t0 h; R& W raise HTTPException(status_code=404, detail="请先等待NMF训练结束!")3 q% e; E' M" z. Q, d
* D$ j0 Y8 k9 q# w6 B ( e; k2 ^6 V7 b0 G@app.get(. a! t' O2 _* b8 E6 c2 K6 I
"/calculate/details/document/", 4 p T& [, Y- J tags=["计算模块数据接口"], . b2 f6 D' S! b# d response_model=DocumentDetails 9 \0 X0 o/ m! R4 c' t) * ^: Q" e% y D, @8 R. W( }2 u1 ^def get_document_details(doc_id: int, user_uuid: str = Cookie(None)): 6 r$ V1 y3 U3 t. o global topic_model_training_tasks 7 ~1 Z" k& u' ~' W1 r3 F7 O1 n1 I2 C9 x- ^/ |' K0 K+ a
if (not user_uuid) or (user_uuid not in topic_model_training_tasks):. X, w, q7 u4 @) `
raise HTTPException(status_code=404, detail="未找到相应的训练对象!") G0 e/ @" B7 ?7 W9 E' g 5 J6 |' H$ p' }4 J task = topic_model_training_tasks[user_uuid] , W* i3 m# `" t' H( ^ if task.nmf_training_progress.status_code == 2:$ T& A+ f5 p: r3 E# D Q
return task.get_document_details(doc_id)7 M9 Z+ c- l9 }- x- c
else:+ T( G% h9 z6 z" Q* R6 J0 r
raise HTTPException(status_code=404, detail="请先等待NMF训练结束!"), @4 I1 t4 x3 f1 m3 f
; A* P: ]/ I1 G ]1 S: d. X0 t& K. ? + y* H7 m/ T8 M) S& [" B@app.get() P) o% Q, q$ z0 k
"/calculate/details/topic/", ) z- g$ X- ^" L tags=["计算模块数据接口"],; U, L' B% y; o5 W
response_model=TopicDetails ' y+ S; }' Y3 L9 T" q+ L)4 S! b% ?7 ], ? y; p' i+ A
def get_topic_details(topic_id: int, user_uuid: str = Cookie(None)): 1 F' P* O2 S; B( T global topic_model_training_tasks 6 T$ v2 x4 q7 I2 R. M, a7 b + E) B3 C) I* e if (not user_uuid) or (user_uuid not in topic_model_training_tasks):- O+ ^' H: w; k
raise HTTPException(status_code=404, detail="未找到相应的训练对象!") 1 f( @ n7 t; m% Z2 C" u1 {" M0 V) M) `8 v' v' B+ e
task = topic_model_training_tasks[user_uuid] 1 [: C$ l: C9 G' ]# @2 b s if task.nmf_training_progress.status_code == 2:9 m e# a9 r2 H
return task.get_topic_details(topic_id)( L" q% V# K b2 [* n6 [
else:+ ?1 J# {) j1 F( ~9 _
raise HTTPException(status_code=404, detail="请先等待NMF训练结束!")0 W, _! e! v2 c* W {
( g L6 Z3 _8 w$ Z3 g/ [5 c |! l! d3 Q g2 \, X+ }6 }
@app.get(. c+ E) Q( O8 g, {& d5 `1 X
"/calculate/userinteraction/info/keyword/",3 x/ {' Z$ @% Z4 u+ `& d6 N) H/ ?3 I1 `
tags=["计算模块数据接口"], e) Y8 J8 B) E) s1 a
response_model=TopicKeywordInfo 7 B* N* ^/ A! h& S G" W)2 a) I& G+ L3 X
def get_topic_keyword_info(topic_id: int, user_uuid: str = Cookie(None)):9 \& X3 O" D6 K2 w6 `* R" L' P
global topic_model_training_tasks0 I' M: @: |+ h; B, R. L! v
6 Z$ [. Y4 X7 i: T8 i$ H3 \0 ^7 G7 |" m if (not user_uuid) or (user_uuid not in topic_model_training_tasks): 1 ~0 b' |2 I B/ w raise HTTPException(status_code=404, detail="未找到相应的训练对象!") 9 v6 h2 B! E. ?/ ?' `/ S& K0 Z' z- ]; }$ s. ?5 h6 x
task = topic_model_training_tasks[user_uuid]1 W" y( s- G/ A5 a6 Q% }: k7 l0 X
if task.nmf_training_progress.status_code == 2: : B6 \$ d3 h% E/ r return task.get_topic_keyword_info(topic_id) 5 D$ Y2 t% ^9 J& d6 l' p8 m else:' {6 ^# b$ z' ~
raise HTTPException(status_code=404, detail="请先等待NMF训练结束!") & Z' w, c: T2 i9 w6 U / @- y# T; C$ P- [ 6 x- Q3 m* E: v- q3 o3 K' w@app.get(7 e9 J4 [5 P; z) v+ @
"/calculate/userinteraction/info/topicmergekeyword/", : g( A# G: B K# T& ? Q V tags=["计算模块数据接口"],* `- t! a6 @9 z8 b
response_model=TopicMergeKeywordInfo1 \) L5 c+ U9 z+ N
) , x/ \' ~% d, b3 @" X# h/ F! A! gdef get_topic_merge_keyword_info(topic1_id: int, topic2_id: int, user_uuid: str = Cookie(None)):) T0 ]7 _ W( _; ~$ m9 ?
global topic_model_training_tasks" i7 N( `) |# G2 b9 l$ z
- w, q* h# r: e' J3 ?5 x! U0 C if (not user_uuid) or (user_uuid not in topic_model_training_tasks): 8 c0 w9 B/ B/ ~# A! G raise HTTPException(status_code=404, detail="未找到相应的训练对象!")5 V( t; y! f: X
" U2 m! z- u. }$ ~5 x
task = topic_model_training_tasks[user_uuid] / |4 C+ D" @9 a% u if task.nmf_training_progress.status_code == 2: o3 ` E: G0 l3 g5 j# y/ |
return task.get_topic_merge_keyword_info(topic1_id, topic2_id) ' V, E: }+ j' F5 R* Y# a. ^ else:9 i' @* u9 k. L5 `
raise HTTPException(status_code=404, detail="请先等待NMF训练结束!") 5 L$ i) a5 l: p; d4 s ( z+ {$ b1 x( V. u4 g0 l4 t" A " w& T% v0 F% f: I( c4 E" J0 O' n1 8 x0 W; ]& A+ W* Q" \8 e. {& f1 q5 F: }2 . x' f. [! @& T; r1 y! w5 f8 K3 5 O2 \1 ~ X9 i; |9 I: ?; ?4 B4$ V1 U9 d0 P- |' u n' `
5 9 p( W2 c9 _8 j7 g+ U7 G5 U64 o8 }# u2 ~: n% }
75 Q# T d! A! g3 k8 x' f: w
8 " H! \' @+ M# R# [. X9& Z5 Y+ W1 f5 g) Q" b0 e
10 9 K( M8 I( |; I0 u2 }0 V110 P. L; r* }6 ^! u
12 N# V9 Z2 q6 t1 }+ Q
13' j T% X8 i; g; Y( F1 D
14 ' x& J3 j a6 R% z8 b' [15 ' [7 Y6 t, \4 S7 N! p16- A/ ^1 z g3 D; y* H
17 7 g: Y2 ` i; P8 f( O18 I @3 E' ?( B9 \ D
194 H3 H+ E7 u5 D
20! e `4 M) R2 G1 i w" o0 B2 f$ Q
21 - T5 r* e* T, ~4 [' I( Z& c22 1 w# p6 n) p$ D# b2 @238 _$ k: H- v( v/ ]" \5 o8 a' h
242 H# g d( [. R+ I( c" Z% S3 x) L
25* L5 g4 I7 ?# A+ [% \( q5 H7 O
26 `5 k$ K+ @1 ?+ E- T
27! T! t5 G( ?0 x. Y
28 6 o6 a! ]9 D$ R! {, c# x290 ^( _! Q0 _+ p5 j9 B7 g- A
306 r4 b9 ?7 y+ [4 _: a* _ o
313 G% j r# i( L
32# j, X* E5 r" j0 f
336 V* S0 x% I' a! F* j7 w8 D
34$ p. o6 X. A0 W% C
35" q! ~7 Y7 ^+ n9 \
36! V: Y. t" Q9 E" n9 G
37) T1 W7 g1 |2 I+ Q
38 - t; {8 h0 h1 S1 @39 / f- C% \, Q# i) u/ _' T40 8 n/ Z( |: o; ~; h41, w2 p: g j" O8 U* C
42 : f2 ?8 b; u7 E- W3 V43 ) w' ~ k6 w' Z1 y' q44+ r$ Q7 r5 g" ~8 X1 I$ Y
45 8 O( {" C$ X) D+ M" ?3 u46 . D; t) [" e4 B47 & e" q2 f2 G3 i486 ~! |: x' U9 U% [: H+ i
49 1 e9 z$ |) q7 U9 V' c9 k, T2 b50 & \. Q6 j5 t( W, B5 H) m2 `0 i1 C7 N: Q51 $ B4 M8 c- ^) T0 v. W1 D K: I4 L52 & V" C" x8 D2 j. p7 O53" @' U% k- x' E% W w5 u
54 3 l0 V6 l+ {4 ?6 V557 b/ U6 F- M$ d* O
56 ( i5 Q7 h, H; C; d; R1 J0 \7 A57: ~" C( d; m* o8 c& `( S
582 M/ f/ [7 q+ c# C; h9 e( U! l( I
59% T0 b5 S8 j) k7 d7 n$ D
608 T [& L/ G: V& R, ]" c+ K
613 ~7 B2 x0 y3 Q& X0 H
62& b$ L' x4 K7 a* P- _ ~ ~
63 % E# ~' L/ G" p) b64- v0 v5 Y6 i# u A9 n
65 ( Y* |/ Z5 r8 I66% l" d# {$ y7 U0 M& l0 z# [
67 / p8 g5 N# Y* r( Z& m9 I2 g, R68 ! K1 T# X/ ^# y" n4 Y5 z69' e$ \% A) J% z# e6 ?1 P
70! ~( x0 n7 s8 m. {$ d' f# [
71 + c* S$ l6 J) C% ~8 p72 # j- ~$ ], ~+ J1 j8 D& l73: z0 Y4 }% P2 y4 I0 C
74! E) E. r: ~) D; G3 }# y+ \/ `
750 Z1 q& Z+ W4 S; t+ h
76 1 }: d5 V6 @9 M4 A% l; _77: Z! V! S# T) H2 o
78& w! {; O7 _. S5 d
79! H2 B7 p7 z }3 L. g
80 9 @; _ a [+ l7 G% r% M81 0 s2 \' X* ~( M. ?# R8 q82 & }- w3 C7 v) [' q- \83 + e" r* S' w/ ~. H$ ]84 6 a) g9 u' }. l: x7 j9 j$ P+ p9 Q- a858 ~8 s |& m" I+ i, U
86 1 [ O8 u& O9 c8 Y" Z87 + F8 W' v, h7 }6 ?88 8 G: F. M. T1 N* e8 F) Q89 2 {* f7 J" R. o* m90* u1 H {7 {2 u8 O
91, |' J% u) M% B7 C) ^: f# u
92 * L. L% l$ n7 {1 ~3 s2 g93- l0 o& P0 t7 |8 E! S, ^
940 Y0 q" E a0 q# S6 z
956 [7 ]/ V$ ]3 K& w* i# W
962 f; b/ c6 v) |* Z
97 , R8 M* E) f6 f" U K98 , T5 Q1 g1 B8 V2 ?/ Z: e997 Y. t" k( g$ u
100 & g! R9 @: r) x101- W8 b/ J: y% \9 Y! U' Y; u. G( G
102 ; \' X7 l H5 R1 J& Z% Z8 x* S1039 \$ w S! I) K
1040 N2 N& H% @0 ^9 k
105 ! D- p; M3 Y( {- i# U106 0 E7 m: R# Q1 t" U# K$ z107% U5 h" _# n# w; Z% L
108 ; x, G( W& `. J. `7 J; Y5 j+ ~9 W) A109 + |1 G B: m- b+ q+ N110 + @7 x* }1 E y$ z6 k. j% l3 k/ [' z111 5 ~+ W% K3 d5 @" e P1127 i' n% t+ Q$ D# I& O: \9 }# t$ l
113 8 i5 d" ?; x3 o+ a4 }1 d1148 L6 D) f6 y$ G9 f+ F
115 % {( j6 r: f9 {9 _0 [- i1 z116 , A' x+ B# S7 z4 N' M1170 ^" ^+ W" @: c7 K! D7 q
1181 @5 C. y. P0 }6 B
119 n: X" c* x: H8 y4 B6 {% E6 n
120: r. E3 i |6 U; ~' D2 X
121! ~! a1 s3 Z8 o4 |. I3 F
122 . Q( I: o. j2 r8 o& ~3 `) i( m123 $ y2 ^5 z9 @( C124% E$ N6 x3 p+ ?! w2 h
125* V" S& A/ i$ m0 ~0 z B
1260 B h' L" E& R( ^+ r
1273 q% X3 O/ L0 \2 K7 n# z
1287 U! `$ H! T: |
129 - \" m2 s, {) _130 - W" f& h5 P4 x131! b7 W% w! @; F/ m: T; p4 [5 w7 |
132/ H" N# o( s) N6 G
133 ' e0 f+ B3 X) n- }134 . s# p7 ~& z" g' `+ C2 `& G0 w# w: {135 1 e6 k7 G+ I% g6 z( a136 7 {9 y9 _- j2 T* {! C! _ u% G137 9 ^& f( F- i0 L$ \5 y A1380 e+ s" c! Q5 ?2 I7 [( f& x" X/ [
1395 ?& n8 P# D1 I0 ^
140 % o2 _/ F3 _8 ]4 [1 Q9 U141 7 `( z7 p2 [! {% g142/ A, Y$ D2 J8 t u% u, W
143" `9 C/ l, t+ a j2 f5 k
1449 _7 q+ A6 l ?( M0 t* j
145 % S c y/ z2 R5 R5 E) s146$ O6 Y4 N% _ U9 C5 L& g; r
147 , X8 j! z4 R- Q148' F8 L1 c: U/ a5 `3 e* W
149$ x9 A1 w+ l5 V: ?
150 ! c1 R8 @$ \! p/ T, U" Q) z151% c6 J T o* c# y/ n- b8 \& M2 q
152 , m7 S( q) t$ N o153 3 z1 {6 ^, h( \$ P+ d0 t% A154 ' r1 t5 {& \- d3 J% f. O155 4 h" ^5 M T- `( u8 n0 Y/ } k156 5 a0 s) t" }) h! D% `6 X& y157 8 C( D9 T. A! T5 y' s1580 x! E$ j. h$ T: Q) a0 o" C' p. V
159( c& X' g2 q! B9 h' h
160 % l; g8 ?3 e6 |+ x" {161 ' ?0 V5 ]4 V7 E2 `( D162& o$ H# S0 G8 b+ V5 z
163 1 |% J6 `5 A* o. m; y, a. Y7 h164 . f$ B" K6 n& v$ g# @: m* J: j165) n( G* B. v- P' N* `$ y
166 & M% c3 N$ w. m6 Y2 m( v1671 S& T0 q' w' g; ]
168& q8 j. v0 q: o( O: q
1696 }1 H, f" s f; G. B3 I
170 ' K @( y# X9 x: \/ @. u171. U$ j5 g9 ~9 s2 N+ O
1725 I% t5 l: M; K! d8 o4 b+ J( ^
1730 S& W/ }& ?, m" V8 ]7 l
174 & c7 P O+ ~) A' u; ?4 [1750 L, T9 r/ h6 y0 F% o
1765 G L1 D$ o7 P- E" g1 k. X
177 ! G5 X4 t. V9 }3 z" ` h178) j- E+ P' Y$ \( [
179$ c5 T8 ]. H5 Y5 R/ v! P$ y
180) T- e4 ~/ Y" n& _' Y! Z& B7 t% q
181 ( C) p- G- R' S182* z6 z: Q* {4 u/ Y
183 $ d* }( z% O# @" a, l184 , m+ `# d7 ^( H v1 ?4 f185; l) e4 o# `! a0 L* T
186 K/ q2 H+ F/ W! y3 V$ `187" N+ r* H7 v% m" a0 O3 L0 {
188 9 j# d" C; n5 [& {189- x1 @1 E" F# s# ]' |: s/ y
190 / H$ [ \9 |/ J6 I191. S5 f4 u, C+ t# [+ Q8 V7 s
192 ! s' v5 T$ b2 i' J193 4 i+ u+ H4 u* @4 Y- N# R1947 m3 u6 g0 V9 p% b# Z# u% y& E
195; S; J( W9 c4 N7 q! h
196 : v0 n9 [& E/ J: p' j197 / C% r* }+ a: H; }5 Q* V' O198 # `" X% u. Y; s0 s& l' b7 ]199 : N& B) V* S% A3 t n) N6 H9 h200+ N0 ?0 b1 U* Y& R6 V- s5 `
201 # Y: ~9 G/ F$ J& |, F: F202* }5 ]/ S. g7 S3 J1 d
2036 A: B2 t% O. } x: G
2046 @- p- ?( M3 a# J, e" z
205 , z G+ k2 w% \& {& q* B3 N2061 F+ R; C- @& i+ N
207 U8 N' f3 ]2 v4 t8 S5 m$ [; v. R6 y208 $ [! O: k: m+ O; Q209( g( v# F9 x7 O% F& j6 `
2106 T; P. l8 p) _$ M
211 9 r! m# c. a: i, _, d% x/ N3 o212 : t6 ?3 u, ^9 \9 b; n6 M+ ~' x213 " O3 v- {$ T& w/ ~, N+ t- Y214 " S7 u2 q. K& S2 F3 V; ~215+ T/ J* b- w% K t) P
216 7 E/ R) g" s* G9 G2171 {: n' @, I1 `3 j# E
218$ j/ W+ K X* P. Q3 S
219 . @% ^' P% H' U8 Q220 3 ^/ Z+ U' V; h- f" w, @2211 j5 @* M* [& N, g, q% a( c
222 , H. c$ [' _; P8 D2 `- W223. ^+ ?+ S0 }) d8 T& U( V
224 # R2 D" W* |! j* x5 [) |225 - q( q1 I. h" _! s6 d2 H! X226 6 l } c7 n1 x/ C( y" O; h1 _ n3 p- A227 0 R: S' w: w, Q) f* u4 S/ K" X5 s+ V228 ! i$ {' X$ Y2 G$ a( e6 U# u1 x229 ( Y' N9 L6 O* H230 " G# }: I; k7 i5 w- d6 Q231: Y- |( s9 t; M, D" C
232) g! n/ n1 e# k# ~/ k
233 ' E: K3 }( V8 m& t234 ! d* o2 `& j; w5 m; ~2 a* N235 * P5 I2 K2 s" D J: D2362 P' W3 Z/ @& }, Y- l2 l, q
237 ( ^" C+ d' I1 `6 v1 X0 d+ m238+ x+ @" n9 t# q6 w/ ~
239 2 X' d0 n! m- T9 }+ \( D* [240 0 J0 o/ h7 [9 }$ i/ |# E& R241+ J$ G2 n+ Q& N
2429 [1 s9 _* t B3 ~" h3 n
243 G% F3 L8 C' u2446 K* _+ G1 N9 z" m1 b
245 ; p1 z7 a) Z' T Z' [246 9 \! ^" T5 }+ J) ^2475 z v" I8 Y" ?. G4 ?" {
248 " ^/ t3 s( `5 {2 n$ b3 m: d249 + E: n2 m/ p+ X5 a( L250 ( ^2 U/ j: ?8 a; ~251 ) k; k8 P/ n7 h# |& a252 ! I/ W9 Z( Q4 I. T2 i2 v/ n253 _. x; }* }5 } b' R+ c% O254 P4 e1 `' n* I9 b
255 3 f, \1 W1 v- [& M2567 j: G' [& _3 r; s; I) D/ w) q
257 * x0 n5 e' ~& ` f6 j- E' b2 S5 v258 2 y3 Q1 h% w7 Q4 k3 B# b259 ) u& B5 z, B6 [* Q8 x2600 T: y% S; k5 W" O" s- H. l- M
261 . o$ }/ U- g2 ]1 ^& n& ]262 ' [) c. W/ p% o/ r7 L5 O D5 G263& `* b) ?! B$ I7 i0 p/ Y5 D
264- X. T; h. y5 P, C8 n* A& y
2655 e% x0 J; n. i7 E6 A @
266 # T7 j- i0 i& W& d# Q+ p" z267# K+ u2 |% C2 L0 y& l n% {
2680 L, v/ }! [* n
269) e3 G5 j1 f4 W
270 2 Y |8 W% s b5 z; x. Y! C271 2 a3 P4 @) w: p5 L" U9 B272( A2 @+ S9 {/ z, _- F+ u {
273 ' q7 F# _$ k/ Y( g- K# f# k: N2 @274* h$ c2 D: I4 s, o
275- W g. b# {& ^( c3 m1 @
276 ! A6 R! c& Q. |2 q V9 t277 - P4 m* |7 B r7 c" g278 % ^2 R2 U! \* l: l: T5 V279 # O+ O( Q1 K8 G8 M- ^0 d+ i. {6 R) m280 + Y7 _! F- T v8 @, n2 U$ g0 j281 $ g. F1 k2 e( |* O282. `! _6 P4 l1 m0 {0 i
283 L" d0 p9 K' t' P
284 1 x+ b: h. N8 {1 T) x- g0 n285+ G$ Z1 G7 Q! v8 s( i
286 8 P- p; x+ k( Z: j% `2876 K- j, p. W' E J. `! c
288' k$ x) i9 i0 e9 c3 M: P
2899 h8 h) d7 X" L+ U* E
290: g! h( w- J# k% P6 q3 G( @- Z7 D
2919 E! \/ U* F4 `8 K3 ^2 y) a
292 + d$ M* U( a* [$ n$ l( J293 ' u7 R. e6 o3 E/ K. T294) G2 C/ T( `5 N$ h7 h- a3 d9 k; t' c
2958 m" F! M8 Y4 U% o2 x
296 8 h. Q9 C+ M( z$ Y! r297 1 ~' y. ?7 I+ n. h3 X% ?298( ?. V( I9 h. g f
299; U! X/ ]+ T) x
300 5 y# p( }- y) N$ F301 ; `6 K8 I* b/ i8 L$ _3028 `- S9 ]* ^. S5 n7 L% y1 ]3 S
3034 u; f. \! v% m2 m, a
304 ( n# m0 q* e- c' I305! }; A0 k, X% a4 b0 k3 t, }
306 , ~) t% W' g1 {4 c n) M/ ~3 E307 + ~: o4 y7 \: @, N* K1 y308' S" v$ _+ G% E- t
309 9 `8 Y+ n2 A; S9 E9 L310, N& A, _8 L' c
311) q$ ^, J; P& d M
312 $ H% _4 x. [7 p/ }3 M% `( R313 / M, d3 W h" v314 U, y+ P; n H _/ h8 X
315 $ L! m& y+ r, @9 p7 v6 G316 ; Z/ U/ b3 w0 P S7 X! o, \/ N# T317+ |1 W" I& v+ c
318 $ d2 a" S0 }3 e! a) E319 U, b0 q# e6 o! a+ w* L
320$ I% C. {) y6 @9 c: w
3215 J( F: p* G6 B/ E7 M; [$ Q3 j8 L% H, Q
322) {& r6 _$ N' U+ D; I4 ^
323. Z& u' }, ?2 R- P! F, n: _
3242 n j4 P; T- N6 Z
325* H' l, B3 J' N C# M! B* r
3269 m4 n. W, `3 I# P: F
3272 j( W; w, O2 s9 j
328/ h$ l P, S1 [
329# `" _5 ~" A a' F/ Q
330 ; a* ~2 a( p ~/ t6 [331 ' _6 H; ^6 ]/ ^4 r+ Z332 # J8 l' v. r5 s& G; T% S" n# i333- N. n7 x5 C% b
334# v9 C& I7 x. S4 I/ y4 }
3350 H ]$ e0 I: I
336 % i3 ]& e4 S$ k3 U% |4 U: b337 ( z S! h" U6 ^& ^$ G1 A338' P' D$ C" o. C) Q8 ^
339+ u; G1 H% l y( p
340) z. ]2 }# d; h' z; e* T7 B
341 ) C% v! @/ f! P0 p6 \342 d; B1 ^! G5 v7 r) k343; x" w7 y- O) a* j
344 l: G% V Q0 h2 ]
3450 V% V; H9 T) W% g& H
346) x! d0 L, e0 s9 W
3475 [* c: C. ^3 M+ L/ L
3489 R- s7 i# x! u0 k G8 D
349 / A# X9 q F! ?" ~, P3504 R# I8 o! h% A- @" B8 P% [
351' F# ]; ?: @* ?& J& `8 z
352 ) z, P+ t+ h( g7 ?353 $ }7 d" v# o8 H9 d- j% T/ _4 V3541 y% V l S+ M
3556 h3 S- c# D4 _: V
356 ! x+ N/ e% E+ Q% R! ?3571 c& b2 v0 R9 |: w6 m
358 . C% _4 w8 }* _6 T7 [; e* B359 + P* Z$ ^! H& v/ H$ Y$ Z- r1 s1 h360 $ m& U1 S& G) S, J$ l& I6 X! c( d3618 B: F' V* u7 ^, o6 Q/ x3 ?
362; w X9 o/ w' K! h& K
363* ?" {, ^6 {) y4 S5 G
364 ; i: j8 ~5 Z& l7 t/ s1 `* L+ v3657 b3 O: g0 L3 V# M) w+ r2 d
366 3 y+ Z3 m- ?: F# h4 z367) H! Y# Y/ ]0 W6 b8 b6 O
3688 Y: t0 L! \8 j+ I
369 . A) K* z$ K4 E370' q* w Y* [0 R9 _6 ^
371, R" T g) n7 W3 v: l, `
3722 p q3 [8 b. g: p2 K- L+ ~( M
373) c) b# n3 {6 V5 L$ J
374( B7 T+ h0 l# t) \7 _. p
375 . p0 f$ e q- ]& j- o2 W3760 P5 Q3 M. @! o& ~) P1 |7 @3 K
377 % ?. k/ e& [$ ~0 o; L6 F# l378 * v0 X; z4 P8 ~: v/ v3 ?1 s379 % U1 E' e# s( y2 P, g380 , A3 q! }; k0 F8 r; e2 y381 . o- [# b& `' p ]; q& Y- {( D3829 X" J0 R- U% ]7 D$ N9 D0 S3 t2 P) i
383 ) J+ U% o/ y1 }- w! L5 _; r% B384, S( H0 }! z7 n% Y' X
385 " l2 f+ g9 x1 i' ^% {) m0 f9 j386 ( T" p, [( N* z387( d+ A2 M6 _8 I8 m- T
388 ! s& y& d* }- h& ?2 L) } x/ S9 d! _389: n2 n: e; m9 i0 |/ }* N
390% m. F- K) y# \1 i* U) U
391 " F& D/ L# X( A _" i3921 |' C0 b2 u- L5 ]0 Y- a
393 F. R2 V5 M+ i" O
394/ C# _- ^" c) A
395 3 A1 N" p' o7 ^: O396 7 `2 W; [6 O. L3970 ]. p; G" p8 a: M( m4 c
3985 a, t6 s' x- s1 a5 t) }8 `
399 9 I2 P; `, n1 ^: k# w. ?+ ?* z400 7 H2 i" R" m9 H' h401 3 k% i5 V8 b& Y1 _+ c; U402 6 O' `5 ]( x6 }: ^" n403 ) H" y7 M& j0 b404! ^6 `& Z" @/ M; b1 Y% z
405 ; Y5 j0 e& @+ K" F( h406 , U( _: \! C4 K: f( [( |3 O407 $ _5 r! q+ l+ d408 6 z, ?+ e. S0 S6 a3 p4093 C# \! S1 U3 B* z5 _) b
410) U7 |) h" ~9 p5 t8 G; M
411 3 \9 d( p) ~( @7 n8 D6 e! [4120 }" F' G) A* p
413. k4 z* R- x6 T3 f. C. w
4146 g x @+ c# u3 P0 P
4157 d( W8 c2 {8 s/ B% H) j6 ?
416: [: w# c% t6 i* Y: A
417 + t1 o" @% ]) R9 v4 H* K) F4182 U2 F6 H |; w; {, |
419 ' g# p0 J- A& N* M8 S420 ( n2 S2 C- T# ~421 5 r% V4 P( i+ z* d2 L( Z8 C422 9 U# |; O! x, R+ M5 l) ?423& {, D+ L& x) B l+ }* ]
424 ! \( U5 N) ~2 Z5 M8 f425 R! t6 c1 x5 ]# y426 : {# I9 L$ F9 s3 z4273 v- s u4 V, @3 Y2 N1 m- F
428% k: G9 ?( O+ ~: \. n
429 ! Q( Y8 S- c9 c% j$ L; Z2 A7 l430 1 o6 f2 H5 p l9 F431/ D0 ]6 L7 K) v2 r1 b7 p8 u
4325 b2 J5 ~2 i- c/ t
433 8 M" ?9 u, r7 O" [1 n. ^434( R5 Z# I! i' I* v& J
435 5 o ^- c3 Y- Z) ]! j/ U436$ l* ~1 D5 j; D0 C- h
4370 @2 Y, c! F4 s, W0 E
438: N( I6 `7 H0 z3 H
439 4 `( G5 {- Y }440+ t0 k( W8 ], S c4 t3 o
441+ ~& e- v& B: S2 _* ]! q% p4 J
442 6 y% A# `3 O) k }( f443+ m! H' R. d4 y) C- e0 B! S
444 1 `! `1 C7 h v# B445/ [6 [/ t8 ~3 D/ D- }) k
446' {( Q4 v8 j5 @' m% o. \* u1 x/ C* A
447 ( |) m' X* F/ K% K5 ?- R" ?" a$ W448 + c5 M K6 ?- }5 ?2 s449 $ |0 i }0 e, Y( R* q450 # b3 r' e6 H B# x! q. u0 q451 9 C7 k+ e' y: W0 D: N6 \4520 e. J0 l$ [% @1 Y+ n6 ~3 p# v
4532 o4 g* w( u6 n" J, m3 U
454 ( n! Q: B, R& \' `, H455( H; b3 X5 }9 S/ q4 O
456 4 Z* q7 f( s t: _" C457( q) W! e; b" a8 o6 o
458 * c/ z- U! [0 D! Z! |2 Z459 - O9 M. D4 H' r% d6 l7 H% u9 {460 " E, {: a6 o/ D461 + ?, i, D- ~$ F I+ ]0 a462 8 i, Y: e9 C+ a8 z6 O) D$ t7 ^463# g* m1 r5 g) p' ~* }
464 " c3 f4 R1 y7 F3 [* M9 A# v465 # S5 i- w0 a. g( E- g1 N466 3 D7 k3 I' N7 g p2 i/ L( ]4679 q8 l5 O0 [. t4 Y$ o( D
4683 |; f( H( j( J; @* W% |
469 K. M3 B6 p1 H5 b0 V$ y470# T1 Y" R b' x) e" d5 d- }$ H8 n
471 1 u; ?5 @4 c9 C- h: K1 a4721 B' ~$ M4 C' Y5 o" O9 ~
4731 `) ~* I O# b. u6 _ |* n6 `
4748 `5 k# k7 S3 s. z
475 7 X( N- ]/ _0 u7 {476 ! W2 x' o2 E/ m7 {5 W; F6 U0 _+ c1 S
+ X' Y2 A. H$ R2 R2 |+ w8 U% d
! Y! A2 A1 L+ ~6 M& G' \) Z! d! M; E) r0 d7 i
+ I+ _+ q0 m$ z. @3 E8 Y
; j2 K8 A) c" J) F: J5 S& n