Skip to content

Commit 4dbe5be

Browse files
Merge pull request #26 from CTUbase/feat/ai
Add ai api
2 parents 5f2d6fa + b874697 commit 4dbe5be

34 files changed

Lines changed: 4565 additions & 0 deletions
5 KB
Binary file not shown.
2.06 KB
Binary file not shown.

ai_api/analyze_data.py

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
import requests
2+
from pyvi import ViTokenizer, ViPosTagger
3+
import string
4+
from utils.utils import *
5+
from utils.crawl import *
6+
7+
def create_tokens(doc) -> list:
8+
doc = ViTokenizer.tokenize(doc)
9+
doc = doc.lower()
10+
tokens = doc.split()
11+
table = str.maketrans('', '', string.punctuation.replace("_", ""))
12+
tokens = [w.translate(table) for w in tokens]
13+
tokens = [word for word in tokens if word]
14+
stopwords = get_tokens_from_file('./sample/stopwords.txt')
15+
tokens = [word for word in tokens if word not in stopwords]
16+
return tokens
17+
18+
19+
20+
21+
def count_tokens(check_tokens, tokens):
22+
count = 0
23+
for token in tokens:
24+
if token in check_tokens:
25+
count += 1
26+
return count
27+
28+
def count_partial_tokens(check_tokens, tokens):
29+
count = 0
30+
for token in tokens:
31+
for check_token in check_tokens:
32+
if check_token in token:
33+
count += 1
34+
break # Stop checking other check_tokens for this token
35+
return count
36+
37+
def first_appearance_index(test_token_list, context):
38+
for idx, test_token in enumerate(test_token_list):
39+
count = count_tokens(test_token, context)
40+
if count > 0:
41+
return idx+1
42+
return 0
43+
44+
def appearance_array(test_token_list, context):
45+
appearance = []
46+
for test_token in test_token_list:
47+
count = count_tokens(test_token, context)
48+
appearance.append(count)
49+
return appearance
50+
51+
52+
def remove_tokens(tokens, check_tokens):
53+
for token in tokens:
54+
if token in check_tokens:
55+
tokens.remove(token)
56+
return tokens
57+
58+
59+
def create_input(article):
60+
61+
# Lấy token từ url tương ứng trên repo github
62+
people_death_tokens = get_tokens_from_file('./sample/people_death_keywords.txt')
63+
people_injuries_tokens = get_tokens_from_file('./sample/people_injuries_keywords.txt')
64+
large_property_tokens = get_tokens_from_file('./sample/property_large_keywords.txt')
65+
average_property_tokens = get_tokens_from_file('./sample/property_medium_keywords.txt')
66+
small_property_tokens = get_tokens_from_file('./sample/property_small_keywords.txt')
67+
serious_keyword_tokens = get_tokens_from_file('./sample/serious_keywords.txt')
68+
69+
# Khởi tạo dữ liệu ban đầu
70+
data = {
71+
'deaths': 0,
72+
'injuries': 0,
73+
'property': [],
74+
'keyword': 0
75+
}
76+
77+
tokens = create_tokens(article)
78+
79+
# Xử lý số
80+
number_conversion = {
81+
"trăm": 100,
82+
"ngàn": 1000,
83+
"nghìn": 1000,
84+
"vạn": 10000,
85+
"triệu": 1000000,
86+
"tỷ": 1000000000,
87+
"trăm_ngàn": 100000,
88+
"chục_ngàn": 10000,
89+
"chục": 10,
90+
"mươi": 10,
91+
"nhiều": 2
92+
}
93+
94+
for idx, token in enumerate(tokens):
95+
if token in number_conversion:
96+
tokens[idx] = str(number_conversion[token])
97+
98+
99+
people_token_list = [people_death_tokens, people_injuries_tokens]
100+
property_token_list = [large_property_tokens, average_property_tokens, small_property_tokens]
101+
102+
for token in tokens:
103+
104+
if token.isdigit():
105+
left_context = tokens[max(0, tokens.index(token) - 2):tokens.index(token)]
106+
check_value = first_appearance_index(people_token_list, left_context)
107+
if (check_value != 0):
108+
if check_value == 1:
109+
data['deaths'] += int(token)
110+
else:
111+
data['injuries'] += int(token)
112+
remove_tokens(tokens, left_context)
113+
continue
114+
115+
116+
right_context = tokens[tokens.index(token) + 1:tokens.index(token) + 2]
117+
check_value = first_appearance_index(people_token_list, right_context)
118+
if (check_value != 0):
119+
if check_value == 1:
120+
data['deaths'] += int(token)
121+
else:
122+
data['injuries'] += int(token)
123+
remove_tokens(tokens, right_context)
124+
continue
125+
126+
127+
128+
check_value = appearance_array(property_token_list, tokens)
129+
data['property'] = check_value
130+
131+
filtered_tokens = [word for word in tokens if len(word) > 2]
132+
length = len(filtered_tokens)
133+
data['keyword'] = count_tokens(serious_keyword_tokens, filtered_tokens)/length
134+
135+
return data

ai_api/app.py

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
# app.py
2+
from fastapi import FastAPI
3+
from pydantic import BaseModel
4+
from utils.crawl import *
5+
from utils.analyze_data import *
6+
import joblib
7+
from joblib import Parallel, delayed
8+
from analyze_data import *
9+
import numpy as np
10+
import pandas as pd
11+
from perceptron import Perceptron
12+
13+
app = FastAPI()
14+
15+
# Khai báo mẫu request data
16+
class InputData(BaseModel):
17+
keyword: str
18+
num_pages: int
19+
20+
@app.post("/getinfo")
21+
def run_prediction(data: InputData):
22+
data = find_vnexpress(data.keyword, data.num_pages)
23+
24+
model = joblib.load('models/trained_perceptron_model.joblib')
25+
26+
location_urls = {}
27+
def process_url(url):
28+
29+
analyzed_data = analyze(url)
30+
if analyzed_data is not None:
31+
prediction = model.predict([analyzed_data['ratio']])
32+
if prediction[0] == 1:
33+
locations = find_location(analyzed_data['article'])
34+
return url, locations
35+
return url, []
36+
37+
data = Parallel(n_jobs=-1)(delayed(process_url)(url) for url in data)
38+
39+
40+
location_to_url = {}
41+
for url, locations in data:
42+
for loc in locations:
43+
# Chỉ thêm nếu location chưa từng xuất hiện
44+
if loc not in location_to_url:
45+
location_to_url[loc] = url
46+
47+
# Chuyển dict sang list (location, url)
48+
result = [(loc, url) for loc, url in location_to_url.items()]
49+
return result
50+
51+
@app.get("/ping")
52+
def ping():
53+
return "pong"
54+
55+
56+
class InputData1(BaseModel):
57+
article: str
58+
59+
@app.post("/predict")
60+
def predict(data: InputData1):
61+
article = data.article
62+
data = create_input(article)
63+
64+
model = joblib.load('models/best_decision_tree_model.joblib')
65+
66+
data_df = pd.DataFrame([{
67+
'death': data['deaths'],
68+
'injuries': data['injuries'],
69+
'property_large': data['property'][0],
70+
'property_medium': data['property'][1],
71+
'property_small': data['property'][2],
72+
'keyword': data['keyword']
73+
}])
74+
75+
# Nếu bạn muốn trả về DataFrame cho mục đích debug
76+
result = data_df.to_dict(orient="records")
77+
78+
# Ép kiểu dữ liệu numpy.int64 về int (nếu có)
79+
for row in result:
80+
for k, v in row.items():
81+
if isinstance(v, np.integer):
82+
row[k] = int(v)
83+
84+
prediction = model.predict(data_df)
85+
return int(prediction[0])

ai_api/create_datasets.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import csv
2+
from utils.crawl import *
3+
from utils.utils import *
4+
from utils.analyze_data import *
5+
6+
with open('input.txt', 'r') as file:
7+
urls = [line.strip() for line in file.readlines()]
8+
9+
for url in urls:
10+
# Crawl dữ liệu từ url
11+
12+
data = analyze(url)
13+
14+
article = data['article']
15+
ratios = data['ratio']
16+
17+
# Write the ratios to a CSV file
18+
with open('datasets/datasets.csv', 'a', newline='', encoding='utf-8') as csvfile:
19+
fieldnames = ['region', 'bao_lu', 'dich_benh', 'label']
20+
writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
21+
22+
# Write the header only if the file is empty
23+
if csvfile.tell() == 0:
24+
writer.writeheader()
25+
26+
writer.writerow({
27+
'region': ratios[0],
28+
'bao_lu': ratios[1],
29+
'dich_benh': ratios[2],
30+
'label': 0
31+
})
32+
33+
print("Succcessfully write datasets!")
34+

ai_api/datasets/datasets.csv

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
region,bao_lu,dich_benh,label
2+
0.0056179775280898,0.1910112359550561,0.0926966292134831,0
3+
0.0539215686274509,0.1470588235294117,0.1372549019607843,0
4+
0.1925133689839572,0.0641711229946524,0.213903743315508,1
5+
0.0824742268041237,0.134020618556701,0.134020618556701,1
6+
0.0048076923076923,0.0528846153846153,0.0240384615384615,0
7+
0.0210526315789473,0.0912280701754386,0.2245614035087719,0
8+
0.1778523489932885,0.2080536912751678,0.1006711409395973,1
9+
0.0273972602739726,0.1598173515981735,0.0593607305936073,0
10+
0.1794019933554817,0.2491694352159468,0.0631229235880398,1
11+
0.0045045045045045,0.0945945945945946,0.063063063063063,0
12+
0.0608695652173913,0.2260869565217391,0.0695652173913043,1
13+
0.0054644808743169,0.0983606557377049,0.081967213114754,0
14+
0.0572687224669603,0.092511013215859,0.2819383259911894,1
15+
0.1212121212121212,0.0484848484848484,0.2121212121212121,1
16+
0.1506849315068493,0.2547945205479452,0.1013698630136986,1
17+
0.0186046511627906,0.0542635658914728,0.2403100775193798,0
18+
0.0303951367781155,0.1580547112462006,0.2796352583586626,1
19+
0.0258620689655172,0.2327586206896551,0.0560344827586206,0
20+
0.0216606498194945,0.1028880866425992,0.2220216606498194,0
21+
0.0878661087866108,0.209205020920502,0.0753138075313807,1
22+
0.0834724540901502,0.0684474123539232,0.0400667779632721,0
23+
0.1010719754977029,0.1822358346094946,0.0704441041347626,1
24+
0.1780821917808219,0.0639269406392694,0.2146118721461187,1
25+
0.0602409638554216,0.2048192771084337,0.0602409638554216,1
26+
0.0631229235880398,0.1428571428571428,0.0398671096345514,1
27+
0.0040485829959514,0.1781376518218623,0.0607287449392712,0
28+
0.0022172949002217,0.1529933481152993,0.0709534368070953,0
29+
0.0573770491803278,0.1967213114754098,0.0163934426229508,1
30+
0.0108695652173913,0.1304347826086956,0.0326086956521739,0
31+
0.0262295081967213,0.1081967213114754,0.2950819672131147,1
32+
0.0102389078498293,0.1331058020477815,0.0238907849829351,0
33+
0.0246913580246913,0.2037037037037037,0.0802469135802469,0
34+
0.08,0.136,0.08,1
35+
0.0465116279069767,0.0598006644518272,0.2624584717607973,1
36+
0.0713324360699865,0.2395693135935397,0.0592193808882907,1
37+
0.2705570291777188,0.0928381962864721,0.1777188328912466,1
38+
0.0226876090750436,0.0907504363001745,0.1884816753926701,0
39+
0.0446428571428571,0.1860119047619047,0.0982142857142857,0
40+
0.0115942028985507,0.2057971014492753,0.1130434782608695,0
41+
0.2697674418604651,0.2162790697674418,0.127906976744186,1
42+
0.1524008350730689,0.1962421711899791,0.0855949895615866,1
43+
0.076595744680851,0.251063829787234,0.1617021276595744,1
44+
0.1183294663573085,0.2923433874709977,0.1345707656612529,1
45+
0.050314465408805,0.1488469601677149,0.2075471698113207,0
46+
0.0150093808630394,0.0769230769230769,0.0675422138836773,0
47+
0.211864406779661,0.173728813559322,0.1101694915254237,1
48+
0.0465686274509803,0.196078431372549,0.0318627450980392,1
49+
0.1142191142191142,0.2773892773892774,0.0932400932400932,1
50+
0.0249110320284697,0.1423487544483986,0.2348754448398576,1
51+
0.0171428571428571,0.0714285714285714,0.2342857142857143,0
52+
0.0071428571428571,0.2642857142857143,0.0571428571428571,0
53+
0.0155902004454342,0.1648106904231625,0.0534521158129175,0
54+
0.1243144424131627,0.1992687385740402,0.1371115173674588,1
55+
0.0050251256281407,0.1206030150753768,0.1055276381909547,1
56+
0.1380368098159509,0.0613496932515337,0.2239263803680981,1
57+
0.0818858560794044,0.1910669975186104,0.0446650124069478,1
58+
0.0225225225225225,0.1171171171171171,0.0315315315315315,0
59+
0.0710382513661202,0.1475409836065573,0.0655737704918032,1
60+
0.0163265306122449,0.1306122448979592,0.0775510204081632,0
61+
0.0833333333333333,0.1842105263157894,0.0745614035087719,1
62+
0.0,0.0215827338129496,0.0287769784172661,0
63+
0.0577427821522309,0.1181102362204724,0.0866141732283464,1
64+
0.1147540983606557,0.2513661202185792,0.1912568306010929,1
65+
0.0681818181818181,0.1409090909090909,0.0727272727272727,0
66+
0.0454545454545454,0.0848484848484848,0.109090909090909,0
67+
0.1872509960159362,0.0796812749003984,0.095617529880478,1
68+
0.3027522935779816,0.0672782874617737,0.1376146788990825,1
69+
0.0656716417910447,0.2835820895522388,0.1940298507462686,1
70+
0.0489296636085626,0.0764525993883792,0.0397553516819571,0
71+
0.15,0.175,0.0416666666666666,1
72+
0.1142191142191142,0.2773892773892774,0.0932400932400932,1
73+
0.0620272314674735,0.2602118003025718,0.0423600605143721,1
74+
0.0234234234234234,0.2108108108108108,0.0342342342342342,0
75+
0.0,0.0526315789473684,0.0526315789473684,0
76+
0.0546875,0.1015625,0.0390625,0
77+
0.1338289962825278,0.1078066914498141,0.1672862453531598,1
78+
0.0588235294117647,0.1176470588235294,0.0647058823529411,0
79+
0.0437956204379562,0.2992700729927007,0.0510948905109489,1
80+
0.0496453900709219,0.226950354609929,0.0319148936170212,0
81+
0.2696335078534031,0.0785340314136125,0.1544502617801047,1
82+
0.0397553516819571,0.1345565749235474,0.2996941896024465,1
83+
0.0,0.0918918918918919,0.1243243243243243,0
84+
0.0744680851063829,0.2279635258358662,0.0623100303951367,1
85+
0.0477326968973747,0.2529832935560859,0.1360381861575179,0
86+
0.0196078431372549,0.2794117647058823,0.088235294117647,0
87+
0.0583333333333333,0.225,0.0916666666666666,1
88+
0.0237580993520518,0.0302375809935205,0.0367170626349892,0
89+
0.026615969581749,0.0342205323193916,0.2585551330798479,0
90+
0.0730337078651685,0.2247191011235955,0.1404494382022472,1
91+
0.0682730923694779,0.0642570281124498,0.0040160642570281,0
92+
0.0161527165932452,0.1468428781204111,0.1071953010279001,1
93+
0.044776119402985,0.0762852404643449,0.2255389718076285,0
94+
0.0546875,0.1015625,0.0390625,0
95+
0.0057471264367816,0.0459770114942528,0.1408045977011494,0
96+
0.0585480093676815,0.0983606557377049,0.0140515222482435,0
97+
0.0699588477366255,0.1440329218106996,0.1810699588477366,0
98+
0.1071428571428571,0.0357142857142857,0.0892857142857142,0
99+
0.0394736842105263,0.2467105263157894,0.0361842105263157,1
100+
0.056390977443609,0.1578947368421052,0.1165413533834586,0
101+
0.0109890109890109,0.1062271062271062,0.1684981684981685,0
102+
0.0289017341040462,0.0809248554913294,0.3121387283236994,1
103+
0.029090909090909,0.2945454545454545,0.069090909090909,1
104+
0.0772946859903381,0.1473429951690821,0.0893719806763285,1
105+
0.0111940298507462,0.1791044776119403,0.0634328358208955,0
106+
0.0729166666666666,0.2125,0.0875,1
107+
0.0,0.0817610062893081,0.1446540880503144,0
108+
0.0319148936170212,0.2712765957446808,0.0292553191489361,1

ai_api/dockerfile

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
FROM python:3.9-slim
2+
3+
# Thiết lập thư mục làm việc
4+
WORKDIR /app
5+
6+
# Sao chép file requirements
7+
COPY requirements.txt /app/requirements.txt
8+
RUN pip install --no-cache-dir -r requirements.txt
9+
10+
# Sao chép toàn bộ code
11+
COPY . /app
12+
13+
# Mở port
14+
EXPOSE 9000
15+
16+
# Lệnh chạy API bằng uvicorn
17+
CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "9000"]

ai_api/image/model1.png

46.6 KB
Loading

ai_api/input.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
https://vnexpress.net/con-bao-toc-do-560-km-moi-gio-tren-sao-moc-4163572.html

0 commit comments

Comments
 (0)