% e5 H" Q2 |2 {6 M: o0 afrom fastapi import Depends, FastAPI, BackgroundTasks, Response, Cookie, HTTPException 5 w: ], v, `! h3 z/ j& g9 afrom fastapi.middleware.cors import CORSMiddleware N" X$ R; _2 @from sqlalchemy.orm import Session 3 \7 c: t5 A( @: Gfrom typing import Optional, Dict 6 s2 W3 \$ N) E0 g/ M1 Eimport crud, models, schemas; w+ N: J: M, Y
from database import SessionLocal 2 [. z5 R% K+ ]/ o% x* B$ qfrom TopicModelTrainingTask import *5 U4 w! ~) u/ M* Y& T: z' k
import uuid * k) y+ X2 x/ Q2 e+ s 5 r" g8 ~! `# Q/ Q, M' Zapp = FastAPI() . J$ M; f0 \" E' G. b+ q, L# u( {* S5 ~2 V- V' y' E0 o
# 配置跨域问题 1 g p% U( @6 ^6 n) L( vorigins = [ a& Q0 R" E7 M% l "http://localhost:8000", & a, @0 O& V' H! k: X "http://localhost:3000" & Q5 D* ^6 N0 F- W# G' B5 @] % {6 i% u/ s0 Y" f6 p6 u2 S' e# R; Z$ ^" s
# 全局主题模型训练对象 8 E. `6 J% Y: p8 p: _; A# ntopic_model_training_tasks: Dict[str, TopicModelTrainingTask] = {}) V8 B E" N& F) B
% n1 N0 R: c0 X# o& o% gapp.add_middleware( \3 A) B( S3 D7 K8 ]) F1 d+ d
CORSMiddleware, % H6 K* [% ~3 c allow_origins=origins,. n! \' A* t4 Q: r
allow_credentials=True, 9 b7 P4 F2 p# Q0 |9 {, `+ ] allow_methods=["*"], 0 G1 M( k+ U6 R+ K) [, O3 u allow_headers=["*"], $ q4 Q7 \9 R6 i7 r3 p4 h) + f: k* i# G+ ?! s) F) D3 P ; t+ J% b) k; n. S' ~& M6 k! R0 i' j0 ~% {) r) ], u
# 数据库连接依赖 $ [3 F7 }2 b9 H2 w4 Ldef get_db():0 f7 X% r; c9 f$ f! {& v
try:* S; y% G, R, p) K
db = SessionLocal()* v7 }/ L) z$ P# n: X+ G( @
yield db' T0 f' b) @4 x( N. }
finally:+ w; p& Y& O* t1 ]) v+ m* z) q- I
db.close()3 T% I" x' ~, h/ I3 d' i! s* O! f
2 L( G. R# |. H! w0 ]) N8 |) ] 5 a1 n: k) |2 c" a@app.get(% A; u9 Y5 w2 F7 L6 ^6 w% F9 X
"/bilibilivideos/"," J6 R g) b' o" @5 l3 |& R
response_model=List[schemas.BilibiliVideo], : z& B4 ^* g( ~2 v3 W tags=['bilibili视频评论语料库数据接口']9 }) B" B# c I4 G: n/ I$ }4 h
) ( |1 k3 K, z- O/ Q9 H; q \def get_bilibili_videos(db: Session = Depends(get_db)): - K6 L3 ^0 q1 t4 {5 @ db_videos = crud.get_bilibili_videos(db) - m. A: B4 x5 S6 i return db_videos! ^. W2 T& F3 ^1 y/ X
7 `8 ? D5 s) ~2 S( t% ~7 A" S & t* F! M! Z Y4 F6 L@app.get(! h$ z+ d4 e8 y. C3 K1 l1 [
"/bilibilivideos/{vid}/", ; `, r' D+ f1 L& x, p response_model=schemas.BilibiliVideo, ; a9 b& W$ t& H/ y g# k4 p tags=['bilibili视频评论语料库数据接口'] 6 o' i0 c1 o. }, ~* z3 P, Y2 _$ {) ; b, S- X- R z+ Y9 \5 }# V4 W' {def get_bilibili_videos_by_vid(vid: int, db: Session = Depends(get_db)): 2 K# b& o% ^- k' @1 s4 z3 L db_video = crud.get_bilibili_videos_by_vid(vid, db)$ Z% Y! [$ o* ]" c3 \3 W. ]
return db_video ; {! n! T7 n7 @- ]- K ) \* l8 F Y3 u( N. a2 p' n/ M, R$ d( T7 ~+ ]$ F3 g
@app.get(9 c" \# V0 Q3 r# u
"/bilibilivideos/{vid}/comments/"," E& O8 |2 ^% b8 p* ~
response_model=List[schemas.BilibiliVideoComment],0 q3 r0 H# ~, \" `! {+ \( y
tags=['bilibili视频评论语料库数据接口']1 e4 `3 N* F2 S d3 ~- p
) - R* K: t* N! f! S+ P$ |3 |def get_bilibili_video_comments_by_vid(vid: int, db: Session = Depends(get_db)): ! s& P4 N$ Z u* _8 t db_comments = crud.get_bilibili_video_comments_by_vid(vid, db)* T) f: }, d( }8 M
return db_comments 6 g R( ^! z) R; u7 Q7 z- N9 B4 v) u. \
4 Y8 ]( X8 n+ D. d+ Y# W@app.get(; I; W5 D0 f: ^% z" {& A0 n
"/onlineShoppingReviews/", 5 q7 p- j! \; H5 g5 G7 | response_model=List[schemas.OnlineShoppingReview],# m/ t( F/ o$ }6 m+ K' Q( t
tags=['电商购物评价语料库数据接口'] : n/ a( r. \$ J8 m) Z3 y)2 n; @1 j5 D' a/ C
def get_online_shopping_reviews(db: Session = Depends(get_db)): & t" `) {1 ]* c8 i5 B db_reviews = crud.get_online_shopping_reviews(db) o8 g9 X' i) `
return db_reviews) I! k, U! T2 f1 n
# V x$ w; f( x$ _ 9 Z2 t4 ?8 e+ r4 G- b1 d4 ~@app.get(* q% R9 u4 c5 H6 D2 G/ G: J
"/takeawayReviews/",9 j5 K/ Z" W6 [7 c+ W: l6 H0 I
response_model=List[schemas.TakeawayReview], ) i2 D% v# K' B$ U: M+ ^3 j2 o |( K( E tags=['外卖评价语料库数据接口'] + Z, p3 P. u: h' T( |$ {) 3 z* m" a+ e( r Gdef get_takeaway_reviews(db: Session = Depends(get_db)):& x0 N" \! d+ N2 X
db_reviews = crud.get_takeaway_reviews(db) - b* r B# k- d+ y return db_reviews 6 v+ m5 W9 c5 s9 c" ]5 X2 y" l( G% o* A* S) e( B- T
! C- ]$ B' K# M0 q' M5 t# y@app.get( L- T" ^7 P, @ "/chineseLyrics/",9 `; F% A6 @& [/ q+ j
response_model=List[schemas.ChineseLyrics], ! U2 L: k3 b0 M7 a tags=['中文歌歌词语料库数据接口'] 8 v9 ^- _2 ]/ k2 F7 B). h0 X- I& Q }7 o5 T) {
def get_chinese_lyrics(db: Session = Depends(get_db)): * r8 F0 U5 Y& b" n db_reviews = crud.get_chinese_lyrics(db). R; i3 t9 b) D, s
return db_reviews ; ^' }# V8 ]3 p C; p0 z. _; E; c5 Q4 D! g/ I
z. y& m5 E7 F@app.get() V! X; \. Z& ]; k# G! @$ W" {) C6 a
"/COVID19News/", ) \) P8 }. X" o. S3 v1 d0 @, N response_model=List[schemas.COVID19News], ' @$ ^6 U- x6 @& A0 l tags=['新冠病毒新闻语料库数据接口']6 a7 T9 c3 b; p0 m
) ' G$ ^9 U; ?8 K" Tdef get_COVID19_news(db: Session = Depends(get_db)):3 x) Y4 K) E; L/ `' U" q0 D. l0 A) _
db_reviews = crud.get_COVID19_news(db) - B# @$ N& [. m' L* m8 M return db_reviews 5 k+ L8 g }. m4 b, `+ K8 R+ S3 v- O0 ^7 l6 R% Y
8 }% @4 r' }5 h
# 为每个用户设置uuid标识符,并存入Cookie: {3 S3 c4 c O" Y$ b
def create_user_uuid_and_set_cookie(response: Response): 7 W6 I7 H/ H# k8 c) f5 |1 W$ z' ?6 a user_uuid = str(uuid.uuid1()) 6 F+ P0 c* P! r. ~1 i) V) e response.set_cookie(key="user_uuid", value=user_uuid)2 W5 ~: O' z( k# b
return user_uuid# T% d! A8 C. X8 k+ f9 B1 s
% m$ E m2 X1 e! j$ \) @1 x! g: k' P- s
@app.post(- @2 ^) A; x0 ^: k
"/calculate/preprocessing/",+ S( A! o1 h) ?6 W
tags=["计算模块数据接口"] 1 q$ L) d- V1 f5 k) C6 [# z z+ w1 Y/ g S" H5 |async def run_text_preprocessing_task(text_preprocessing_params: TextPreprocessingParams,! g$ |+ B+ m2 Z) n1 X6 _4 P: t
background_task: BackgroundTasks,, x) {( k1 \ A& ?1 j
response: Response, # a$ K3 Q+ Y( F! r user_uuid: str = Cookie(None)): 3 \( s* ^. ]. }) ` if not user_uuid: $ }& z4 U7 T5 ^ user_uuid = create_user_uuid_and_set_cookie(response) T- F G2 Y8 J+ M/ x% F( ~" X
# e, n; ^% z+ A" ?# H! l
global topic_model_training_tasks0 z3 c8 b! u; j, I" E& P9 [) Y4 H) A
task = TopicModelTrainingTask(text_preprocessing_params) 8 H& K, }" }/ D- t4 @5 Q$ z( Q topic_model_training_tasks[user_uuid] = task1 }6 G" b$ w( r! N. }8 H2 h/ `2 x
7 b( I& p& |5 I+ v( E/ d% Z7 q4 i background_task.add_task(task.preprocessing) & c5 g* X6 I A2 ~3 B return {"message": "已添加文本预处理后台任务"}" }' R0 c5 c8 G8 `/ T I
: N: ?" ^' A e* J. d 8 B5 M6 c+ _: s@app.post(; X3 D* e1 {% L9 g% ~
"/calculate/nmftraining/",1 _: W( d& A7 i. J9 Z, p
tags=["计算模块数据接口"] ! `/ t8 }- \/ O( c4 c9 d; H) 0 C8 H# ^, j- T% u, B7 oasync def run_nmf_training_and_tsne_task(nmf_training_params: NMFTrainingParams, * T. o: J% |2 [- |1 _" E background_task: BackgroundTasks,+ t* o( \7 o+ ^ ~; m
response: Response, 7 Q' @8 W! w& E user_uuid: str = Cookie(None)): ! G4 b1 J% T) s) I" k if not user_uuid: & Q; A: p2 ]; B/ ] C/ E user_uuid = create_user_uuid_and_set_cookie(response) " T: d$ i6 n# X5 N1 t% v6 I6 x- |- \8 L$ T, u* [
global topic_model_training_tasks0 g* m$ M1 u5 r1 t) M# x
$ d7 F- T+ b+ w6 G; [
if user_uuid and user_uuid in topic_model_training_tasks: 0 B8 c: U. R6 C# i, X- u task = topic_model_training_tasks[user_uuid]" ?5 j1 z$ p6 N/ \& m9 K G( C
if task.text_preprocessing_progress.status_code == 2: ) ]3 i5 w/ g/ m/ F" ~ background_task.add_task(task.nmf_training, nmf_training_params)/ u+ {, R, o3 k/ }# s' p- T4 Z7 o9 ]
return {"message": "已添加NMF主题模型训练后台任务"} ; c# n* w% f. g5 p3 u! }9 J else:9 t% n0 @( z. ^4 {
raise HTTPException(status_code=404, detail="请先进行文本预处理任务!")$ b! U* D3 B5 J6 [4 j0 x7 k3 u
else:# C9 b) U- I$ j2 g& O% O8 n
raise HTTPException(status_code=404, detail="未找到相应的训练对象!") 8 z) {% [$ X- z2 D! E' x* R: R, L% `
: h4 m% C( V3 w2 r7 R+ @@app.get(6 X ?8 Q8 }( E/ _
"/calculate/nmftraining/keywordsearch/",6 V8 ?3 a1 |8 F3 _* L* B- t
response_model=KeywordSearchResult,; @3 v9 v* w+ z0 }" R% T/ ]
tags=["用户交互"] " _8 j% b! {, v( ~- W" b)% N+ {0 N2 @5 a8 C+ j0 v* G
async def search_keyword(search_text: str,$ ~1 J; C" |$ J1 W7 F! [3 ^
response: Response, ( z; z+ q) X, \# f, S& e; h/ B user_uuid: str = Cookie(None)):9 e1 ~# N+ B0 z/ _, x
if not user_uuid:9 n, g3 D& \9 n. e8 c9 F# [
user_uuid = create_user_uuid_and_set_cookie(response) ' S: T; A; H& X1 S1 @+ r2 p' j5 r ! K) R" d5 I6 ^- G global topic_model_training_tasks- ]( a6 b2 d5 ?9 C0 U/ U+ c* }& H
2 H9 o0 n) `+ ?7 u" Z5 d
if user_uuid and user_uuid in topic_model_training_tasks: * t- i+ [3 t% U5 b. M- A task = topic_model_training_tasks[user_uuid]( f/ g4 G: D2 M6 \, L" M3 a" ?" X
if task.text_preprocessing_progress.status_code == 2: 2 _. J4 _5 y; J( y search_text = search_text.lower() * j. J- u! J* d bag_words = task.text_preprocessing.bagWords 7 r. g; F' E! ] keyword_search_result = KeywordSearchResult() 5 v4 Q# \8 N9 l2 {1 k9 }. l6 ?; G for wi, word in enumerate(bag_words): # ~: e. u3 v* ]7 z if search_text in word: 2 H* r9 e; Z9 [( r+ N4 u keyword_search_result.word_id_list.append(wi)' N# Y% Y: B/ M/ ~. T! u
keyword_search_result.word_list.append(word) 8 a3 u, ?! h7 ?7 P5 e% K+ s return keyword_search_result + h0 j% \( w% Q else: / l5 ~/ |8 f- p& P raise HTTPException(status_code=404, detail="请先进行文本预处理任务!")3 C) ~' ^- a3 X/ o6 O2 X! M
else: 4 J* `$ G' N* J# {* Q* } raise HTTPException(status_code=404, detail="未找到相应的训练对象!")3 r' ~3 [) n* {9 l9 |
) R P! ?- B$ W/ Q: w1 d$ f2 j
) Z) a8 S9 x9 w2 F! |@app.post(3 Q+ R/ m% t' r; G) J# I9 o! c
"/calculate/nmftraining/topickeywordoptimization/",7 p8 r6 B6 F+ ~1 Z6 g/ b# `4 o- b" `
tags=["用户交互"] $ B% ]# c7 M5 i8 c6 {8 ~7 }: D# g)8 a& P+ s# y/ @4 e
async def run_topic_keyword_optimization_task(tko_params: TopicKeywordOptimizationParams, : h6 ^+ {% i( d/ W# ] background_task: BackgroundTasks,5 w" L7 S' g I9 D% R: a
response: Response, ?+ x5 T4 e3 U
user_uuid: str = Cookie(None)): B( {0 E( Z; R% f( V5 ~, @$ t if not user_uuid: * b; ]+ b d8 C5 K% `9 a user_uuid = create_user_uuid_and_set_cookie(response)' _( w2 @0 s0 _9 }2 \, ~0 H
7 `* g3 f/ @1 D6 d
global topic_model_training_tasks - O: V" K! M8 u/ f+ w- c/ ]4 Q1 q/ T* D9 r: H$ [" r
if user_uuid and user_uuid in topic_model_training_tasks:( p# z. z( |3 `+ Q+ S5 y
task = topic_model_training_tasks[user_uuid]6 X1 R5 w& X( L" X5 l8 ^% P* Z& ?
if task.nmf_training_progress.status_code == 2: W& h4 n2 o3 ^+ y3 e background_task.add_task(task.topic_keyword_optimization, tko_params)# ~/ H1 C9 y- ~% _! J
return {"message": "已添加主题关键词优化后台任务"} 1 m; B1 a0 {* Y$ w else:4 I0 a9 P& S5 |; z. ]
raise HTTPException(status_code=404, detail="请先等待NMF训练结束!")4 B% Q4 t s& B
else:. ~) A: f, n7 Q" c5 Q |4 z2 }/ f
raise HTTPException(status_code=404, detail="未找到相应的训练对象!")+ T" l1 _* E3 A" B1 i
2 O3 n) D% n8 z: S5 d( S, Z
5 \6 X- a @( u! ~8 V. F5 ~+ j@app.post( 2 d5 j7 ~) x" Z4 S( n "/calculate/nmftraining/topicsplit/",4 Y( O# f7 e5 p* K
tags=["用户交互"] 1 F* f1 y; S/ F& R9 X! \/ w) $ ~4 W, c) j0 Xasync def run_topic_split_task(ts_params: TopicSplitParams,/ F# G& H& Q! v, C2 |7 y
background_task: BackgroundTasks, ( R5 ^* ]6 p2 p response: Response, $ ^" X' D3 Z, M user_uuid: str = Cookie(None)): , G: l& o: N3 _, l- ^: E if not user_uuid:( s2 z! S# o9 d( |
user_uuid = create_user_uuid_and_set_cookie(response)) G, i3 t8 ^- v
, \0 Q4 L- d: Q6 D, o global topic_model_training_tasks5 p8 j. |$ r# A. T; c: U
# e: r5 I& g e4 T( {2 h
if user_uuid and user_uuid in topic_model_training_tasks:7 t2 b+ t8 c6 o* k; B& k/ B: m
task = topic_model_training_tasks[user_uuid] 3 M9 d3 v& X+ L+ F4 p- r4 H if task.nmf_training_progress.status_code == 2:4 _# ]# |) E( `- Y( Q7 y2 I" Y( O
background_task.add_task(task.topic_split, ts_params) ! [# s% e) I5 g/ b+ c return {"message": "已添加主题拆分后台任务"} ~: G3 j8 y3 T* }/ |) M3 [ else:0 `2 l7 h2 A6 x$ w6 _% Z/ S
raise HTTPException(status_code=404, detail="请先等待NMF训练结束!")- D- T0 m8 D7 x9 _7 _- a+ v, F
else:7 L& G: [' s. h% E2 r
raise HTTPException(status_code=404, detail="未找到相应的训练对象!")& Z; W* P& H- o( P3 ]
& D2 v! q3 K' ]' J+ ]% \3 t* s5 d/ v
@app.post( . V- \% g5 M6 S/ [5 u: z9 l "/calculate/nmftraining/topicmerge/",8 d) ~$ A3 b$ _$ l) i3 n
tags=["用户交互"]; E+ W6 }: v' y0 z! s6 o
)4 ]; |8 Y) W8 n2 `
async def run_topic_merge_task(tm_params: TopicMergeParams,% q8 i; g0 H# i2 J- K* l8 x
background_task: BackgroundTasks,. I5 O7 W. Y8 D+ k- S+ n; }( e' Q
response: Response, 5 S% K( e j" ~3 U8 n user_uuid: str = Cookie(None)): 7 Q1 S9 J- V1 w+ I5 T7 R if not user_uuid: 4 p( A1 b3 v. R: n- ]: d" o user_uuid = create_user_uuid_and_set_cookie(response) 2 n B2 @7 x9 `/ l7 Q 7 V" g) c4 ?1 \- ^7 A global topic_model_training_tasks 4 v V; [. x8 d- q3 _& c C: C" f$ C" ]/ G' b
if user_uuid and user_uuid in topic_model_training_tasks:- W+ W( B( ?3 D* b5 X0 @
task = topic_model_training_tasks[user_uuid]( T u/ f7 Y2 P4 N2 m; |' F$ U
if task.nmf_training_progress.status_code == 2:6 S; y' K& O) P6 n& a( c
background_task.add_task(task.topic_merge, tm_params) z( [/ H# @; m- j. b
return {"message": "已添加主题合并后台任务"} " s3 }, z8 C/ \ i( ? else: R% S, H$ v7 P8 _! ?( ?# r raise HTTPException(status_code=404, detail="请先等待NMF训练结束!") $ h* a. e/ d( ^* l- i }& F else: 4 |, Y# {6 c C4 v raise HTTPException(status_code=404, detail="未找到相应的训练对象!") - b5 x C/ ` P# c9 X b q' \. v2 A $ z* A# l5 y( U+ _. j, C9 o4 ?2 P7 b, t# n" ?! y5 o
@app.post( # F8 h9 U0 Q& Q# y "/calculate/nmftraining/keywordinducedtopiccreate/",4 m L' Y+ g# M9 H2 K3 _
tags=["用户交互"]0 f" Y* b: ^7 l, O& M9 x8 Z
). i$ K2 o! [9 J3 X8 B# Q) x* B2 M
async def run_keyword_induced_topic_create_task(kitc_params: KeywordInducedTopicCreateParams,' B+ R) N) e. ^# |% f
background_task: BackgroundTasks, - c) N. G; [$ N3 _& O* a# r& Z response: Response,+ Y, J0 t# j: V) e! V d" K
user_uuid: str = Cookie(None)): & }9 p5 O; n+ ? if not user_uuid: * Z9 y: p5 g+ J% r$ k user_uuid = create_user_uuid_and_set_cookie(response)/ W# E- H6 Z* ?+ P$ y5 {, m4 G
9 M' ~1 ^* W4 K7 t/ U- F
global topic_model_training_tasks # I# U3 A8 p) R) [% ]: u8 P9 y* S6 A+ f. `7 s+ a$ P. j
if user_uuid and user_uuid in topic_model_training_tasks: 5 h8 j5 P+ X6 i% \( [ task = topic_model_training_tasks[user_uuid] , Q: S. G7 Z( X! M4 S if task.nmf_training_progress.status_code == 2: 8 x4 r% ]! G- M0 K" A& z0 j" l background_task.add_task(task.keyword_induced_topic_create, kitc_params) + A7 \: Y. Y: g- j8 e, A return {"message": "已添加关键词诱导主题创建后台任务"} 9 W7 `# S1 s0 W% ? else: 7 ~, n; s, N; q2 Y: [ raise HTTPException(status_code=404, detail="请先等待NMF训练结束!") : ?+ y( |9 u" T5 v4 O* ` else:9 q2 r; S& |9 H5 U) L: b
raise HTTPException(status_code=404, detail="未找到相应的训练对象!") # a$ @. \7 \ G: k4 i- o# L# j* `! c5 G8 X; l
6 x$ `3 p* |* @+ D H@app.post( " e! i0 K U# q9 a "/calculate/nmftraining/documentinducedtopiccreate/", 3 i+ S( a0 `! @& U2 b+ `! J) I tags=["用户交互"]2 x, R R( _8 c" |$ |1 B
)) T, l& A/ E/ F' K: t' Z% W+ o
async def run_document_induced_topic_create_task(ditc_params: DocumentInducedTopicCreateParams,, E3 |4 S- E* W" k0 @
background_task: BackgroundTasks, y9 E! f. {; F6 H response: Response, - ?+ E2 W2 N8 W user_uuid: str = Cookie(None)):/ [* Y7 ~) ~4 g1 g1 {& n: \
if not user_uuid: ! ^8 d* J" ~1 I" W user_uuid = create_user_uuid_and_set_cookie(response): e2 A2 o [; f! ?# K
2 X6 u* v5 U+ M/ w% Q3 S3 r
global topic_model_training_tasks4 s0 M1 _, c! [9 n
/ X& |& g, ] {8 ~
if user_uuid and user_uuid in topic_model_training_tasks: [% V3 H7 J& L0 b& J# r task = topic_model_training_tasks[user_uuid]3 l) g' ~* b; d
if task.nmf_training_progress.status_code == 2: 9 Q- ?: T# Z8 b9 |% { background_task.add_task(task.document_induced_topic_create, ditc_params) & `8 C$ _2 t" D9 L return {"message": "已添加文档诱导主题创建后台任务"} ) l( h/ V# C7 Q3 @4 w else:5 N! B/ H8 V1 F& e
raise HTTPException(status_code=404, detail="请先等待NMF训练结束!") , c# p. C" d1 i else:0 K" @# B; F; Z3 h) r
raise HTTPException(status_code=404, detail="未找到相应的训练对象!") ' B0 ^6 K( |( Z* \- f) W+ |" Q% A/ j' a: _. Q. ~3 o8 m
! J1 l" C, R/ Q, s% O' B
@app.get( 6 t2 A; U) n) Q7 O% L# Z "/calculate/nmftraining/newdoctopicdistributionpredict/", : j$ G# M0 C) M7 m& _* h tags=["主题预测"]$ g5 w& ]3 F/ j: F) W0 n
)& o p7 E3 @& U, [! b# k
async def run_new_document_topic_distribution_predict_task(; K6 j- C; o- J0 p' _* Z# ^
new_doc_text: str, 5 n2 [ ^- F7 z# Z( s: Z6 v: h$ b background_task: BackgroundTasks, * Q6 L; A, k7 c/ ]5 @" q response: Response,! t* o1 e. F' e2 p: g' M4 W
user_uuid: str = Cookie(None)):6 [1 P, R+ ]9 w: [% I+ T8 B4 L( ?
if not user_uuid:* U( e3 C# [3 I' R1 Y
user_uuid = create_user_uuid_and_set_cookie(response)5 L/ x6 O) E- h0 r* H
7 x+ I6 l& V5 |* K7 p! l
global topic_model_training_tasks+ O$ F0 q2 C8 ^
; S& O( F1 I8 F# B$ C
if user_uuid and user_uuid in topic_model_training_tasks: 5 j8 p$ v8 g+ f0 V task = topic_model_training_tasks[user_uuid]; ^! E: ^ x% B/ `# S. d) y8 O+ W
if task.nmf_training_progress.status_code == 2:8 T9 M" v( w5 C8 m9 m& C
background_task.add_task(! g7 I! c; ^$ H& M3 R8 f! i
task.new_doc_topic_distribution_predict,% Y% j9 o- l$ v* ]% p3 d
new_doc_text8 |& y0 |* x# d( j I
) . _, o8 O: ^+ ]0 v return {"message": "已添加新文档主题分布预测后台任务"}# D8 e4 W! I3 z. @; B/ c9 `/ n B
else: 7 n3 Z% R" c6 b raise HTTPException(status_code=404, detail="请先等待NMF训练结束!") w1 Y- N# { X3 C; V7 F! @ else:- M1 z& t1 Y' }# x5 m
raise HTTPException(status_code=404, detail="未找到相应的训练对象!") 3 G5 |) v4 h4 x3 F5 l( H: Z! O7 n/ S+ `7 [8 L3 u8 n
: g' X% I2 C( Z" v" A7 `
@app.get(4 Y* U3 a* [* c" y
"/calculate/preprocessing/progress/"," w4 x. i% J0 o
tags=["计算模块数据接口"], " Y4 N& V; P9 [5 C6 v* w3 r$ F response_model=TextPreprocessingProgress 4 g8 J( \. Q9 X1 U3 {)! i5 v* N1 f! \; A
def get_text_preprocessing_task_progress(user_uuid: str = Cookie(None)):8 q* {+ } W( |0 ~/ x$ S. i2 h
global topic_model_training_tasks6 B# G) L+ w* K1 e% X
. V0 d/ q! `8 s" I% @: C if (not user_uuid) or (user_uuid not in topic_model_training_tasks): 0 J% I* D8 m% j: v7 o, q" c+ } raise HTTPException(status_code=404, detail="未找到相应的训练对象!")9 W8 P% X D& s
return topic_model_training_tasks[user_uuid].text_preprocessing_progress% e3 ?1 n8 C" l3 k# |, }
$ Z0 h5 j. o" Z- G. z G
3 K& h, d; ~& Z- `@app.get(3 K# _9 t, w/ {9 b" }. ?
"/calculate/nmftraining/progress/",+ ^( y; G2 ?; B7 H6 a5 J
tags=["计算模块数据接口"],) _$ i, G: g; W$ L, [
response_model=NMFTrainingProgress . g3 G2 l2 v3 j2 A0 }* j! t* x)* |/ k( Y4 J, D5 d6 w* m0 E
def get_nmf_training_task_progress(user_uuid: str = Cookie(None)):! @9 i! ^; T; J4 V( g- Z1 G9 N
global topic_model_training_tasks ; {" U4 ^8 Z# F 0 E O! D1 N" O if (not user_uuid) or (user_uuid not in topic_model_training_tasks): 4 p( p9 T- n6 C" f! q raise HTTPException(status_code=404, detail="未找到相应的训练对象!") ' o& p' t( M& X6 k6 x& h, O ' s& d- a: i- j' c- [9 C0 y task = topic_model_training_tasks[user_uuid] & q2 ~6 L8 b L7 P/ w/ K4 T! [ if task.text_preprocessing_progress.status_code == 2:9 Q& E* S" X3 f2 e3 x2 l( D
return task.nmf_training_progress+ H( U8 \5 q9 e+ g) m
else:* T! U% ]* r# Z, l2 o3 @
raise HTTPException(status_code=404, detail="请先进行文本预处理任务!") + c- V- Y7 A( }- l$ P ( z5 B3 @4 ?/ ~! w4 c ( J: h: W) [# N9 J7 Y" R' n l@app.get(6 s; n. ?8 ?# |2 R7 j+ L) U6 q& ?7 V
"/calculate/umap/progress/",, q" }' C0 c4 x. Q- x) [7 H8 q
tags=["计算模块数据接口"], ' N6 X8 l2 a+ k1 b response_model=UMAPProgress( y' T' U; }# f# \7 t. ^
) ' e' S5 n% c' ?0 ~8 ^def get_umap_task_progress(user_uuid: str = Cookie(None)):+ j' u0 W* I" j ?6 X6 a& u k1 q4 K7 M
global topic_model_training_tasks I8 X# o0 o$ i' d' f1 V$ `
" M) O3 q( M& n2 a if (not user_uuid) or (user_uuid not in topic_model_training_tasks): 8 ]) T4 E' A: b! k Y raise HTTPException(status_code=404, detail="未找到相应的训练对象!"): {, B# G& G: j$ M1 U
# e' I2 b8 Y5 C
task = topic_model_training_tasks[user_uuid] * ~; P6 T6 t* G8 ` if task.nmf_training_progress.status_code == 2:% H1 p, b" w+ q3 s3 C3 v
return task.umap_progress $ q' x6 B7 w( I1 d else:2 P. u" q' L3 z+ E
raise HTTPException(status_code=404, detail="请先等待NMF训练结束!") 1 ]) C# J/ M( P / J0 q6 }% V+ p4 X , i$ J0 I$ s& Y5 }9 r0 \) n@app.get(* }, [8 o% E6 B
"/calculate/nmftraining/predict/progress/", # H4 t2 x. c; P: A+ n- k tags=["计算模块数据接口"],( ?0 x+ I% G5 E# a% x0 o* K
response_model=NewDocTopicDistributionPredictProgress ' v7 f% m2 O3 ~! }# H& N* u. c, Z) * J& M" r# }' A* E8 o" L4 m* u( T$ @def get_new_doc_topic_distribution_predict_task_progress(user_uuid: str = Cookie(None)): : |. [, V/ U7 r1 Z8 t( [2 _# E global topic_model_training_tasks: E8 _ p6 y6 j. ?; l
3 D8 N) C( z5 r if (not user_uuid) or (user_uuid not in topic_model_training_tasks):! Q$ r4 P, p9 U
raise HTTPException(status_code=404, detail="未找到相应的训练对象!")( R2 g( _- y1 X. W( a4 \
! D. \3 R2 e- A* \8 s5 [3 D1 _ task = topic_model_training_tasks[user_uuid]6 k* W* K: e! }8 \
if task.nmf_training_progress.status_code == 2: - P5 C- @) w$ E( q return task.topic_distribution_predict_progress 5 L! j+ x6 B+ C& h$ e" Q7 X else: # ~5 [" w }8 H5 @' `5 \0 v9 p raise HTTPException(status_code=404, detail="请先等待NMF训练结束!")2 T ]9 z& I o6 I0 d2 d
+ k3 \% d& |) E1 Z' j( O, f& a$ X$ X4 i) l
@app.get( + G5 H3 ~: V; y. l9 O" U# m* B "/calculate/details/document/", % q: p& j* d. D) _1 n2 @ tags=["计算模块数据接口"], / ~" K8 y% v( s; E response_model=DocumentDetails ) S/ }8 Q/ g A- J- M)! H) S# F% v" M$ n1 Q
def get_document_details(doc_id: int, user_uuid: str = Cookie(None)):5 W4 t9 X' J; S4 z
global topic_model_training_tasks$ h5 s' y* r" m7 V
' r0 t6 F0 V: J6 G5 [ if (not user_uuid) or (user_uuid not in topic_model_training_tasks): & s* M) D& P5 ?1 r; ^ raise HTTPException(status_code=404, detail="未找到相应的训练对象!")& M7 d: A b; [$ i
" X! U( t4 K7 L' P/ m
task = topic_model_training_tasks[user_uuid] 6 U! g0 q) H1 X0 P if task.nmf_training_progress.status_code == 2:# n7 ?" \! O6 q2 K1 |2 j; s
return task.get_document_details(doc_id) 6 S8 r8 b+ F2 E else:9 o5 @$ ^2 w; Z0 R" D4 o4 m
raise HTTPException(status_code=404, detail="请先等待NMF训练结束!")9 d6 Y; s. C5 o1 \' K- C* E5 | s
+ x* S* _3 R+ j& M |, \0 K
2 H8 M1 D$ B. y' F@app.get(2 G: q. m Q" i; y2 g: U; |' y
"/calculate/details/topic/",) {* c5 R! c: G x/ D
tags=["计算模块数据接口"], 9 T1 K% I2 z$ @, P& h response_model=TopicDetails / Q6 }- h# T5 N, J5 F)7 t3 L2 D, Q7 J1 \, Q
def get_topic_details(topic_id: int, user_uuid: str = Cookie(None)):+ N4 d9 V) |8 Z4 s9 ]9 a' |" o% S4 W
global topic_model_training_tasks . H- a+ H- N: ^# w* F* [* q% @$ A$ v4 L# O
if (not user_uuid) or (user_uuid not in topic_model_training_tasks): : R0 M$ R* Q4 r, M% [# p raise HTTPException(status_code=404, detail="未找到相应的训练对象!") 1 H3 P- g1 B% _- u% d% B 8 Q+ h( j4 Q2 b, h% D2 N7 d task = topic_model_training_tasks[user_uuid] 5 u2 H: n# p# C if task.nmf_training_progress.status_code == 2:( b8 y4 X) k2 Q6 U
return task.get_topic_details(topic_id) 0 J: r% O- J2 v9 }9 t! H else:: F3 m X# P: d% f2 L9 o- K
raise HTTPException(status_code=404, detail="请先等待NMF训练结束!")" y7 ]7 O8 [8 U& I F5 G
6 o5 D' R! h* a# s( R3 u3 G; P" C0 m3 Q1 i# f; g
@app.get(" P2 Q1 z) Y% P e: G5 v' p
"/calculate/userinteraction/info/keyword/", 9 g1 J8 H2 |. Q tags=["计算模块数据接口"],& y& L- K2 x" d% q! j, d) U, S
response_model=TopicKeywordInfo+ w: g0 p) P4 y, _$ l, [+ J* E
) # U: W/ a9 M* H- Udef get_topic_keyword_info(topic_id: int, user_uuid: str = Cookie(None)): x" H/ x& V" p0 r' _4 }, l
global topic_model_training_tasks) F" O: Y1 x% T* b; a1 e# i
8 N0 o- z D* O& ? if (not user_uuid) or (user_uuid not in topic_model_training_tasks):0 t9 K9 B; G2 |) O! N, w5 |
raise HTTPException(status_code=404, detail="未找到相应的训练对象!")0 D, S& X% F b8 T; Z% S
' r7 Y8 C7 W8 r2 E1 m task = topic_model_training_tasks[user_uuid]: B+ z* H5 F4 f9 s; s
if task.nmf_training_progress.status_code == 2:0 c5 Z* M, @; y; w; s' z! v
return task.get_topic_keyword_info(topic_id)4 B$ N3 E2 j) \0 C \
else:4 I4 n' O; J8 j, ?. f
raise HTTPException(status_code=404, detail="请先等待NMF训练结束!")% e" Y) Z( m$ l% D$ [" o* V+ \4 b0 D. |
) \* [; G" S; t. D
. \3 |( d) Q& P6 _% e
@app.get( 6 R: G! p1 Q7 ~5 c( } "/calculate/userinteraction/info/topicmergekeyword/", ) H0 G/ p2 o9 a4 x M" o- b0 A9 h tags=["计算模块数据接口"], * j& x$ z l3 ^* d- B- Q7 V& u response_model=TopicMergeKeywordInfo7 Z* H6 G/ y; N& e( r1 r
)) l* b& |3 J) G0 S1 Y+ ]( n, H
def get_topic_merge_keyword_info(topic1_id: int, topic2_id: int, user_uuid: str = Cookie(None)):+ }- h' r! w. s' ~ ?* c
global topic_model_training_tasks: D/ M' K8 Q i
/ X4 i7 p; W1 O, l: f9 @7 V if (not user_uuid) or (user_uuid not in topic_model_training_tasks): - N1 D$ b1 i9 m/ g. c0 X9 O raise HTTPException(status_code=404, detail="未找到相应的训练对象!") # ^- a9 S* |6 I0 v, O5 S! M 5 M" D! k5 D3 T4 g& ?! Z" w task = topic_model_training_tasks[user_uuid] : M; w, z* ~7 j! A) T7 h( ] if task.nmf_training_progress.status_code == 2:4 G: b; l' {" a% x2 P7 G+ S
return task.get_topic_merge_keyword_info(topic1_id, topic2_id) g! b& l: M. z C$ z. S else: ' h; x* }" j& U raise HTTPException(status_code=404, detail="请先等待NMF训练结束!"). E0 `) c5 S* n( m3 l d
. ^3 N+ \4 K% D k 2 H: z: ]) p# R, c; Q, X& o& j1 0 X, W3 j9 \. g! P3 _24 A T/ |% ]( W9 q2 i. @, f
3 % ^- X$ ^" ?6 t6 v9 s4 , ^+ E3 \* k4 [4 Z* F! v/ u57 r, p% z. F6 Z' j+ e/ i8 g
6: _4 N; ]: [ J( l
72 Z" P6 ?& P, x% A8 O" C9 {
8 9 a; Q% O2 K( q9 U; p9 / r0 D9 I7 Z2 O0 w; P: c: H10 4 b. L2 y9 o4 I/ ~4 ]5 ^4 x111 a+ `( F" J' _ ^* n9 [
12/ D7 Y% A) ~5 L1 m3 g% n& g
13/ o4 o9 t& Y; w2 @& P2 a/ i- b
14 . \/ E# [9 ^3 g- o( u" {2 D2 M+ D% v# N15 2 }" i5 v3 m0 l16$ p% N2 w: S1 Z
17 8 h* s5 k, z' n, \2 } r% L18. T) P7 u8 I! I" K3 ^
19& E+ T; K# D2 g- n8 \+ ]. H7 |
20 9 t A3 T9 ~1 f: j21 * P2 I, Y/ b4 r22 7 G8 T1 m: R6 p! Q( z2 v( P23 6 P" V7 v$ d. ` P. b. V! y; f24 2 S0 C# B+ W* J2 v: }7 a- u! f( ~* k25 ! c r2 O0 E& e/ _ Y/ h/ f26 # {, _% }- Y2 m+ M- v27/ W6 u1 |& t8 k' Q3 ?0 u$ Z
28 9 E! P; C3 N+ q( i& @! I% J. \29 - W! J* w% i- H" Z! R30 , ?) Y: m5 F; v31 " M* A1 g. }# c' G$ p/ ~32( V& h5 O% I# r
337 j1 U+ T& L5 J" i% {) j
34 ; o* N) d& E5 V% H35 4 Y$ U( `9 g" k" v+ R( C3 [; N36" t7 T& q9 H% y- A
37 , M2 X! A8 D3 X9 A381 s' o( H [% B* O4 ]
39 1 R# b" n* q' U$ W4 i) {1 F" }9 ]40 ! c# l L: |3 O( K h5 X$ z41; Z7 b& T0 U% T# \4 s
427 F3 I+ ]6 j* }' r8 U- e' T2 ?
43 4 @* H' y. C7 @, N8 v1 q8 F447 ~6 W0 G- r8 d J0 e" N- {
45 ; T1 H5 ~6 j# V2 N; Z, p8 P. r46; u% d5 R* I4 D
47 " v0 \! u: v1 }48+ {, i+ q% G0 I+ X$ U
49/ N1 t& s/ @# M2 @& L2 d2 W# J
50 ( A8 Z3 i5 S7 J2 F513 @. i0 [+ }" u- I3 a" h, w4 L
52! b8 G/ b7 x; a/ [# i5 l- T% {
53 8 X- S( v" h( |! w1 M549 w- q. x1 _& z0 p- g, X
55 ; F% y1 E! i3 b$ u( r# ~56 & p% q1 z# \! R* @" K* p/ n57 : h- J9 T6 t( M6 w8 v581 q) D( X r! l% e1 o0 [3 b+ y0 M
59& t+ F6 c% W9 r
60& b5 c% F8 H+ c( l' t
61+ d1 c! H( g6 N9 i
62 ( y, \: g/ m' y5 y2 I1 j5 @638 R* K0 T3 X) G- {
645 A1 [) u) v+ B i4 C- o
65 9 o. O3 u% ]* N7 a$ B" y$ ^66 7 K. k; B' D2 G8 Q% I' ~67 / r2 I. ]; J- M! D; L, f686 e# L. x5 e! b1 g( Y, {. t
69 ! Z" U" z" H; @4 d/ H3 f/ y7 T$ n70 8 a) H3 M1 {0 A# Y( }( R71 ) a2 x* y- g1 W+ O: P72 # }& J$ A! M9 |# Z3 I2 \6 M1 T' I73 % D# _3 R9 V/ T, T0 j74& r0 y: ?. Y9 T
75! Q. n, S0 F, N; e+ m: |. z7 q# g
76. I+ d H) }8 ]( G5 J0 a
77 8 f- R7 r- ^1 a+ g k# Q y& ~# I78 9 J% X7 e" Q# t" r4 B794 z/ l3 r5 _0 G8 p6 k
80! z5 j/ c& e# F G# @) G3 z
81* M4 f! l8 {" }- ]. s Z. [9 w
82 * v/ L; ^+ _1 D, L' i3 ~, X83 / S5 u. f; A. a Y7 S: V84 , d7 h, p5 o6 r. q4 |$ I" h! m8 b% e85 & N0 r7 ]* Y4 x2 c86$ i+ ]' m- o7 a- M; M- ]2 ~
87 / n G% l# R) X5 ?1 _: H ]88 7 f7 j, G w+ k9 O: r# ]' T [89 # g$ P) I# j& f# D90. m1 ?1 d9 e, G2 D9 a1 ~) J; j
914 M \0 B; v3 Y& S
92 * l* s+ c$ a1 @4 j$ T93 7 _" V6 F: ^% j9 p8 v/ q' N944 S m0 Q: e! M$ b3 t' K9 d$ Q
95 & V" J& x# X" O+ ^9 n0 u* F {. Q1 ~968 O+ \! k/ C0 _$ \; }# S, b& f/ M# r
97 s2 r F- o( P. q/ ?) x4 Q( L$ ^98/ f j" N+ L4 {
99. K0 _! T& F# d) X: q5 v- K- v
100 / R2 l8 ^6 w( b101 1 u" {8 C s0 ^3 P* \5 w2 b) t1025 R; J/ E7 T! J' m. q
103$ W+ {. L3 W& G7 b# r W1 i
104 & X* ^+ P( }% {: o1 o; z+ p105 - ?2 V# \& V6 l/ ]- E$ r106 , W2 K/ I. V+ p7 P107 , }3 o# D+ ~# F9 W1 N8 a108 " y8 k8 J) V. ?3 R% |109 ) F! r: q2 ]6 Y* \# Y) R+ L110/ R# l) ~0 z, H! {* o
111 7 _* ?( U! x! y+ s# m( G& F112, _& u% G! _" v+ X9 ~6 I' v
113/ q/ }1 |/ }; X
114" a; E1 g7 ]+ Q8 ?! }/ b: {8 a- _# M
1153 G& R4 n; l, h$ ~: d
116 7 Y1 T8 p! Y! y117 . V7 l* m5 L7 ^118# v: H. u8 ]5 t& R* J0 C6 I: `
119; n& n4 T/ M+ c6 k
1208 @# T1 D& P* R" C& Y
121& j: ?; D0 l/ S
122 9 V! C! t0 d t! t( ~1230 o' S* J7 M& W
124" T- j( L5 s3 m& C" f% x
125 $ U7 M! T& k% j" f2 ]/ R126! ^0 e8 F5 }+ M; A/ b5 L
127# b6 f( Q: \, c$ Q3 G' H3 `
128 ) o- f* f- h j! x* r9 F; R, n* C. ]2 I1292 }1 c' ~+ [6 Q; l+ Q
1300 D* D9 H) ~6 y$ E8 K' K
131 / b& G+ A+ `: T. r4 k9 Y; }$ @1328 K4 J1 \5 G. i& Q1 i9 D9 Y7 |) @
133) v8 T7 V2 F1 v. S* d: O9 I
134; B8 J: D. g( C
135 % A8 {$ J4 g) Z4 B; w+ K* n136 8 S5 m5 N1 |$ r137 , I! V& l( |. C8 q* T) m138 4 l$ T2 k7 l3 f, E+ r- o7 S4 z139 * g6 F5 G; m8 ~140 ( E0 W0 W( u9 E$ _0 ]" Q6 E* U. |141 1 \4 k- B, R! P( r+ c Y5 P142 H( B6 S" P% I& n( Q* ~
1435 c; F7 \3 a* P) J
144 6 I1 w: H/ n6 a7 w; E- I1 N145 + o! g+ j4 F ^5 r' b146 1 g! f+ L: i$ `147+ W V$ H: B/ `% U+ s e# k2 v5 o
148 " j8 K |( c$ q# O" }149 & @. n6 c& V6 c7 v( V150 7 ~7 E7 z7 ^# U" o151 ) P+ y/ h/ n( z$ N3 F: S1529 e$ q* {) |' C$ D' }
153 3 V+ n7 I* H' f6 k( O6 ^1544 x8 D4 r1 _) w' E0 z
155 7 x% v. k$ ~( P/ V. l# I! p( j8 f9 R. T156 : b/ w1 p' [; r157 2 P! ^+ K$ @5 P* S158. ^/ [/ }! K( h9 M9 c7 z
159 9 r" S, h- D1 v3 g160% o! c P4 ?9 r/ |" s' V
161# o, Q& a' Z' v2 z
1629 p% Z4 W e' p [
163 ( L2 w2 t! ^" x$ `5 F, G164# @3 z& K7 {9 e. ]
165' M* L7 l7 g6 b0 ~* F
166) K+ l& b) h" R b4 S
167 6 z! p9 u' L: m2 G$ Q6 U168 3 [- f4 M! o4 F) p1695 r7 [, p1 B N+ u, R0 @% a+ U# H
170( C( r0 H/ u/ F
171 " k* V( c. b( ]; y) |" T& s172 , a) A1 _8 C. {6 q3 C& }, E# W. Q; Y173' k" q7 Y1 I- o, R
174 5 k3 K+ F8 n5 i% [2 ?8 i) C$ y175; Y2 N0 V0 d6 x# U; K, u7 t
176! @( z* S0 t! E! P
177 / s- V5 ]7 @) B+ W& K7 }- B178/ q* F6 j, q0 k5 c
1797 ^2 ~: Z( f3 _4 s) `) p
180& k0 `9 S3 B! J; M, @
181 . v' H3 P: z$ n- v6 z2 ?182! ?8 w! m5 J' J6 n, l ?" J1 F* S
183 - p4 A# y: `: D# \& A2 i. Y$ g184 S. [" ^* R0 D" R. n185% E7 w" r7 I; C
1868 b8 }' s. R1 T. \' T' J
187$ g; P) s" `) o& [
188 * v. m. e3 \5 \: l6 ?6 X4 F1895 a6 R" [0 n. h6 O) [
1900 e: I6 o0 V; {/ Q
191 2 u$ U" F9 U) n1927 a- t5 m& ]3 r$ m$ S
193 3 Y# ~. R' r' f$ I6 D- w* u194 7 m% ]; d2 J, u) g. @& b3 E195 R0 R( P9 s) |5 F2 `7 {
196 1 T; F) p( G" F7 V& v1973 U$ |2 R' b6 M. G: J
198 / \5 ?" o5 j+ f+ t6 L$ { t7 @199. H7 [0 V7 r( }: c; E/ a; U; |9 x
200 " h5 c$ v2 J2 `- V3 g3 G201 - c4 Y4 d8 Q7 c+ P9 |/ |6 L202 $ H* c- ?2 F6 c: w; ?203/ D' I* }( m: o
204 7 J6 j2 [$ S' _2 c205# b; }5 Z) G: l1 Y, s# {
206 ' h. ]9 E+ @3 g' m( e0 Y& l6 ~2070 k0 w- L( a* j' }( U: e4 u
208" L% e2 G, o- X' |) [0 q( n8 d' _/ [
209. X( ]6 H. s/ e8 A+ G: o
210 + R6 g9 W) k6 @% b* N) S" w211 $ l/ @) u8 _, A3 [1 u: k212 2 v( W- r3 m! k$ o6 K# R/ W213 7 H" F* B9 E1 a4 f214 7 O- h3 v) Y$ X2 w215' ]1 d# z6 k4 h* w1 \" S' k( j' z
216 ; R' W/ x+ A& e2 w9 D- i8 `& T4 A217 9 y8 g1 a8 x0 G6 }& U' D3 `8 N218 , [ X* L, ^/ z) Y' b2 n @5 O ?219 8 Y# N( b2 Z" R; s2207 _7 ?' O: G# d: S k1 n
2210 p6 q7 R/ x1 g/ L- O$ `& ?1 q
222) f% s y: w* J' I; [+ s
223 # c$ U4 G8 |, F% A224 & v8 \4 u. U4 a225& x5 h* V% p) a
2269 ]! w0 C4 }* `+ y Z* H
227# I. \0 e' N0 K. o7 X
228+ w& c6 g9 v4 O, i l7 h/ @
229. L$ M, {, t# E G+ \) |* @* p
230& C! c9 u4 G/ R6 I# ?
2316 f# E0 Y# S7 p+ Y7 p, _$ L
232 $ R+ A9 [% Q* v0 m: S' I4 s- X2331 X7 X* C o ^$ u4 ^0 z/ @" M
234 1 D* [# w& C5 V) J _1 {# W+ T! y235, T6 o' \4 _' m, P0 w
2360 T' Y2 P. N7 i8 a0 e$ a* u
237 % M' O# l: t8 `$ t# v( y238 / ]( b$ s( }0 Q# A8 U239 ) ?# R) p! G; |3 P' [& h3 B2404 t, ~# O. y4 F& A8 S0 Z8 n
241$ y4 m1 E- L+ |
242 ; @4 U" M) V6 V; S2438 U& V, c, Z" Q0 ~0 j6 U
244 " j5 v" j5 c. B0 H245& t+ o- R! G+ T# n+ I: g3 \6 }
246 P) ?) |* D1 `& |, U% F
247. s+ f! c: b |* i: N
248! ^8 k& F7 ?- S9 @% M. @0 L. Q
249) d W( d7 [% i, ?& P0 F0 m+ U: T
250% E9 A, }% M3 Q* h l- {
251 : }# d% z, Z9 y0 Z( X252( g- t) `# _8 h8 O. z
253 + s0 p/ U9 x1 u254; t. o( N( ]4 z! Q+ x" B! P, _
255 / c( A: |: c1 i! w- t256 2 r7 ~: T" g2 w8 ?0 g) ?5 N2579 E4 O# b$ e$ S$ F" H- Y
258# s* H7 }1 Y' g+ Q" n
2595 g& `( j+ o- z! k w9 V
260 2 t" ]1 m* o8 u2 j1 V; W261 / X t7 c' H4 B6 G262* _& v L" D. ]3 N' R
2638 `! V, ]: }* D% b, }2 z8 `
264 ! I0 |$ |' U- `& P# Q/ L2651 ?- l; E/ A' \! s E' ^8 V
266 ! X C6 L, Q- G) d/ C& C267 % H' H$ Z3 ?/ O' w9 ]2688 H9 j5 Y) Q4 c( s/ s( f" \
269 + y) Q- @& p- }+ B270; K2 b- Z$ h4 K; e' |
271% v6 m6 c6 U6 `) e: E
272" T1 r5 a( `4 K- d
273 + V" g8 O! j; j- _274. J; m7 c2 J8 O5 A8 d& ~* n& d
275 : K& {; m4 O5 b& t$ B, V276 / m6 I3 Z2 v7 B: c5 a# R/ A277( K' q% n% d( q: A- {
278 7 U, j* j" S8 y9 Q/ l* D9 F- @279 9 ?" x3 ?, r9 s280 0 H, C8 m" _: {5 H0 A& g5 P7 s% W; H5 u5 p281 7 U2 d5 R; S0 N" G; d+ U282 $ \4 V& [! L1 `) L% {1 D283$ I4 p- k& u% x( i1 B
284! Z) t9 |1 t( U% j; J
285 + T' z& L4 q" c: i286 ! n$ @) H x! c! v' \1 H287$ }+ I" w$ R/ t$ ^' t `2 b; V
288$ ~1 S; }$ E4 T
2892 D! h" F }; g/ l7 X- c% Q
290 : y% g1 H- E8 ~291: Z$ I2 {4 X0 G, Q8 n8 T8 ?1 P4 W4 l6 D
292 2 Z6 ^0 @2 U" O. h0 o2937 P5 w8 S' `2 R2 `. V4 Q: h
294) a* d. R; ^1 X- U" D2 `: b4 X4 |/ O
2951 ?% g" }* u/ k/ ~
296 . k: o. F6 a( { M% n297' K! C" ]+ h* O
2984 y& V0 J0 K+ | C+ d7 j& m! Z. G
299 ( F' N( t- g! T7 q3008 ?1 b$ h9 Q* |. W L9 [4 d
301& _# ? N+ d& g1 S
302 3 F' T: x+ d9 E303 ; d* M* J6 H) I" n* i3049 [ J7 W0 h7 ?
305 . g$ R- k& r( L, ^! K7 J- B0 V306 # o) A, y5 ?! S# {7 }/ B3076 \, S6 z( [2 |/ g- m* }
3085 X* C. M5 T! I! ]
309- i' T: R( u4 Z) E6 _7 t
310 $ l) R: D* g5 S! K: l7 H311( ?" t) b$ F: ^3 e- {3 E2 h
312* p1 B/ N6 {4 i" _- H: H- Q
313 * J" w+ w3 }8 m4 \1 _' a314 # l2 b4 Q4 x' k$ j" u9 |, v315/ C( e6 Z/ h$ }3 |5 g
316 4 C1 X% T4 j1 b c* A) b4 H3179 O0 @( m1 a h4 I0 Q* C/ c2 W
318$ A# o# m8 ?& n8 m7 r F
3199 `: ^7 @0 }# C8 q6 t
320 9 W, S, g- l& E7 x8 a" g; v. K, K" q2 O321 * X: ]9 h W, ]6 ?322 W4 @) K% j/ B! u$ V! K' P- m323 6 o! i7 ~2 U3 u4 y# G3 ?- {6 t" T6 E324, B! n3 r1 Q2 B) T( X' T% C8 W$ o
325 * W* ^5 ?2 B1 N' N326) f5 l' i8 @' q8 Y! p, O
3276 n! w, x' f% ]/ c
328 . e# A9 q r0 e& k) n/ m5 [329, g3 \/ v7 [& [
330 # X' H. n5 Y G/ Z331* z& o9 F- A2 k2 h* o
332 - E4 |+ a- U) }# d7 K0 [333 7 l# Z1 k% i* F! y+ J0 n3 o334' p9 b1 h: n( V8 f2 P
335( f- I- N3 U. Q* r: N7 J
336" E0 E6 q3 Q$ D$ T! s6 J6 O
337) i9 o/ o. s' m% C1 [$ k- ~& _/ Z
338" m7 M. _- T' \! h+ a) E2 B% q
339) y" P9 G& x! z9 x) ^ U6 w* B! }
3403 o$ k$ I% H/ Z1 b1 H1 e0 V
3412 P" I9 o0 R7 w c- W$ @
342 5 U$ A1 y. J1 e3 m; T! D I+ N) B* t343 4 u( {+ k- c! l& c5 b" S3449 y+ R* o3 A3 x- l+ A* \- J% v
345 . `8 o( k4 a- W, w346 4 g; J8 H" g2 H4 ?+ D1 D347 + X8 P" y( h: ^' x4 ~: v348 2 ?; O7 n8 r0 K6 {. \3494 C3 f; t; x9 I2 `& E2 s
350 3 d/ n% A, Y& K351 % _5 `* l. d! P' c1 c4 x352! ]' L% r# g+ q1 {
353 / R6 I0 S" H* c1 b" E1 B" {354 8 C+ C! j4 f+ |' U, q, t, x355 / F1 x5 d, n- H; Z3 T2 f356 W4 U, C* M- J3 W" W6 J6 I0 }% J
3574 u: v& e# m2 ?4 |
358 ' `/ P' e% X1 y359 9 r( F+ M4 B$ ~- y g360. o B- J! M- O @
3617 K% `( z" V* B/ p" ]
362' |6 Y! I `; c. n- A/ Z3 i1 E
3630 \8 {# Y3 s2 P- E' B9 p! v& c5 H
364 ( t/ V% m/ i: t365/ k! ]' f( ?! W" z
366" e1 I) g8 ~ c& C2 j! Z
367% `4 O6 W: A8 F! Q
368' a1 P7 }- Q2 j) }9 |# d) u
3690 F! \# v3 t9 o; J7 L; G+ k) o5 u4 U
370 / f4 R5 a. @2 W8 o; w371$ d; i9 I+ w+ p3 d$ G
372) _( g. b( T# K1 x9 Y" _/ m& X' r
373 - F, H8 t; F5 A% L; O374 1 p9 }! f8 z: p+ u' v- P375& I4 J, m& G+ I/ x1 I9 Y2 A
376 7 V- F7 X# g+ m: p/ R0 u377' n5 V9 U- P( `
378 ! K) h& _- k# v379 5 k& W1 n( Q9 F; E' F o% \7 [380! s* d8 c! f, M! J7 B7 \2 I9 B
381 ' Y5 H, T6 T5 [6 O382 $ t2 x5 R0 a; s9 z6 s: \/ V4 K0 ^383 ( F, U5 w9 ~) e. q/ ^384* V0 z4 I6 ^+ Q8 ]# z3 B
385 $ C6 ~0 m2 e6 `3864 H) R) E) y% w; Y, v1 ?1 g; w* T8 R
3875 `; c" `! K x7 N$ j8 }
388: N- Y4 W5 P( d, D8 y
389) U3 l. A0 S6 G- P5 o# Y
390 1 [0 h3 w: E# I- }391; \' Q2 y7 U# u7 P* b+ R( ?& @
392$ M0 i9 w) F+ d9 ]( |2 e$ F
393 2 d0 C' ~: s5 S' Z394& l: E0 O5 S, M/ {9 l, r! z
395 6 P0 m0 p: c3 o2 n. C396- x/ _9 ^* Z$ Q. C$ g0 L
397 9 @! i2 O$ z' [$ { P6 n3983 Q% U2 a) h; x0 l. f4 P; ^ G
399 - E; ~7 N& L8 H1 I5 b4008 I& s# I+ i2 I
401 4 ~5 I. v( G7 X( [402 , U3 b. h/ ?- T) A, E, I% }, b403 e9 Z, k# k/ u, Y8 G' O4 d, P
404 / k; d* Q4 {5 O6 }. o/ D- I/ F, ~405 ! @6 c! W- p0 `3 z0 Y% Y406 7 F% Q- v7 @# l, s0 N+ L6 k" W407 5 v1 k0 [2 x2 ?1 Z) `408 $ _& S$ x% K- D4 `0 P409- h- Z" d' ?- `
410 / \7 d7 C7 k6 e2 X$ s- o; R411- s: s4 L$ X! G6 \1 p3 \0 I2 B( O
412" e& T1 j7 v/ c
413 1 Z; \ Y0 H! J9 q6 s8 V! b4144 s, A: g. d+ X2 K8 n9 i
415 R( U1 S3 b3 t6 N4 R
4165 H1 u0 M. v( |; G4 p, l0 \. n
417 2 [0 P- D5 L% \# p j+ E7 f7 V9 z; X4186 ^& r8 w: ~( K' K7 d. A
419 5 F6 m& q! \/ N7 I f$ O9 F8 L4209 N j: b+ a" L$ D' `- |
421- R( X2 s% C! }3 W
422 3 R! y& f* F7 A% Y2 W: Y+ K423 $ {" I" o e0 B! H. ]424% v) O( Z3 S- ~# m- \. T
4250 t0 ~; G5 ]. M
426 ( a4 Y' S6 ?& p/ l2 D7 k8 W: c4271 T+ q4 Q3 S) Y; m( h6 g' e
4281 l* o4 k7 v$ ~# m
429' X0 k6 H5 o+ E
430 % j6 ?% w$ I5 M431 ) H! I1 ^9 B( M. S) U432 / c8 ^- `& @: V n% q5 Y) N/ l433. T% g2 @) t: N+ g8 z
434 ) f* M8 z/ |6 k% W+ }& t4350 Y" _$ v. e/ E2 r9 K2 }
4361 m* g6 ? m( s2 u3 ?! v, k a
437& T9 M' N2 S5 S% d3 J1 Z
438; @# u1 B9 ^' k$ {1 Z
439" V7 @! G) w) ^
440 ! X- u E, j0 ~441 / `5 s0 |9 C9 Z; @442 , p2 n2 i( F! D2 _( ~1 G0 m4437 T8 n N o9 E
444 $ M8 x, u4 j5 p* C" M5 [4452 L. ?" A) `- I$ r6 ]
446 3 r4 A# s. X. m& P' Q: P447' H4 ?( t7 h* B
448 , a5 A3 A2 x1 X$ H8 `4 c% S449 7 }* `* l5 `5 a( Z: y7 m9 |( C# C450 $ o+ O# L! ~( Z2 J. t/ R451 , n( [. i# c7 L% n452 8 d1 T, q' |; i# W- H1 [0 s m453 O9 Q0 x& ^2 q2 Q2 r8 o7 O0 D# w
4549 V" ]& @( N* j2 u$ O
455# h: W% H X7 M/ h/ v
4568 t2 q+ T( b8 }; f
457 ' |/ m' o# Z. T, o* u4 R458 * d2 e- O0 H4 l( R, Q% ~, P459 0 H! Y0 D$ E3 b% g460 3 O2 ^0 E1 _7 N8 R* d( L. k461 6 [9 h& q2 s2 {, W; J6 x. x462+ W1 f# k% i9 d! f. z7 r
463 4 J& J- a# q& l' h464 ! z9 I6 f) i7 O, k% B \465 ' F) d4 _: x9 O3 {' D, h1 c466 2 q( ?: i8 {: J, u467 % T+ m+ `6 Q" G/ d468 o- w9 O3 F# [8 H# [4691 ~5 e/ b- }4 E! q1 l
470 x+ L& J0 i+ {2 o3 O# H
4710 J& V8 T2 @5 F% B. d; r% Y* F0 Y) G, l
4726 [: n3 f! A+ O% X
473 6 d/ D6 B+ \. I: O$ _7 e) |474# f$ h+ V1 F+ N, ~; K* c t
475 5 G1 W0 x# o; m9 }476 & s9 R0 h5 T8 H( u. v) }' s- ]7 E$ m) V' P( G8 U% K
( f) e y# @: e6 b3 S- F* _. R; z4 o
$ N! C$ Y7 o H. x
; K8 P; j3 B2 K3 }- y9 b/ _3 L6 ]1 G