vumichien commited on
Commit
fe6002b
·
1 Parent(s): 747827c

upload sample

Browse files
.gitignore CHANGED
@@ -8,4 +8,6 @@ wheels/
8
 
9
  # Virtual environments
10
  .venv
11
- meisai-check-ai/
 
 
 
8
 
9
  # Virtual environments
10
  .venv
11
+ meisai-check-ai/
12
+ uploads/
13
+ outputs/
data/sampleData.csv ADDED
The diff for this file is too large to render. See raw diff
 
data/sample_name_sentence_embeddings(cl-nagoya-sup-simcse-ja-base).pkl ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:37d23eb2818b20c0ca22c227260378a325207ccc37f0a3567a9ecfe89fb87c2e
3
+ size 17768611
data/sample_name_sentence_similarities(cl-nagoya-sup-simcse-ja-base).pkl ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:a50b8dd5d6625d23fdf960eaaecf550fd3119c9267ef5e7408dae99c1a16577f
3
+ size 133819030
data/subjectData.csv ADDED
@@ -0,0 +1,128 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ 科目,正解の科目
2
+ 共通仮設費,共通仮設費
3
+ 直接仮設,直接仮設
4
+ 土工,土工
5
+ 地業,地業
6
+ 鉄筋,鉄筋
7
+ コンクリート,コンクリート
8
+ 型枠,型枠
9
+ 鉄骨,鉄骨
10
+ 既製コンクリート,既製コンクリート
11
+ 防水,防水
12
+ 木工,木工
13
+ 屋根及びとい,屋根及びとい
14
+ 金属,金属
15
+ 左官,左官
16
+ 建具,建具
17
+ ガラス,建具
18
+ 塗装,塗装
19
+ 内外装,内外装
20
+ ユニット及びその他,ユニット及びその他
21
+ 追加反映事項,ユニット及びその他
22
+ 石,石
23
+ タイル,タイル
24
+ 金属製建具,建具
25
+ 木製建具,建具
26
+ ユニット及びとい,ユニット及びその他
27
+ 囲障,囲障
28
+ 構内舗装,構内舗装
29
+ 屋外排水,屋外排水
30
+ 植栽,植栽
31
+ その他工作物,その他工作物
32
+ 擁壁工,擁壁工
33
+ 歩道切り下げ,構内舗装
34
+ 発生材処分,発生材処理
35
+ 躯体解体,とりこわし
36
+ 仕上撤去,とりこわし
37
+ 幹線設備,とりこわし
38
+ 発生剤処理,とりこわし
39
+ 撤去工事,とりこわし
40
+ 発生材処理,発生材処理
41
+ 外構解体,とりこわし
42
+ 昇降機,昇降機
43
+ 既存公会堂地下躯体解体撤去,とりこわし
44
+ 管理室解体撤去,とりこわし
45
+ 舗装他解体撤去,とりこわし
46
+ コンクリート,コンクリート
47
+ 免震,免震
48
+ 既製コンクリート,既製コンクリート
49
+ タイル,タイル
50
+ ユニット及びその他,ユニット及びその他
51
+ 屋外,屋外排水
52
+ 歩道部撤去改修,構内舗装
53
+ 新本庁舎昇降機工事,昇降機
54
+ 尾道市役所解体撤去(K-1),とりこわし
55
+ 発電設備解体撤去(K-2),とりこわし
56
+ 便所解体撤去(K-3),とりこわし
57
+ 駐輪場解体撤去(K-4),とりこわし
58
+ 駐輪場解体撤去(K-5),とりこわし
59
+ 舗装他解体撤去(G),とりこわし
60
+ アスベスト調査、処分費,とりこわし
61
+ 機器、器具設備,機械設備
62
+ 配管設備,機械設備
63
+ 電気設備工事,電気設備
64
+ 電気設備,電気設備
65
+ 思いやり駐車場庇,附属棟
66
+ 車寄せ庇,附属棟
67
+ 直接仮設工事,直接仮設
68
+ 土工事,土工
69
+ 地業工事,地業
70
+ 鉄筋工事,鉄筋
71
+ コンクリート工事,コンクリート
72
+ 型枠工事,型枠
73
+ 鉄骨工事,鉄骨
74
+ 既製コンクリート工事,既製コンクリート
75
+ 防水工事,防水
76
+ タイル工事,タイル
77
+ 屋根及びとい工事,屋根及びとい
78
+ 金属工事,金属
79
+ 左官工事,左官
80
+ 建具工事,建具
81
+ カーテンウォール,カーテンウォール
82
+ 塗装工事,塗装
83
+ 内外装工事,内外装
84
+ ユニット及びその他工事,ユニット及びその他
85
+ 建設副産物処理費,とりこわし
86
+ 木工事,木工
87
+ 1ユニット及びその他工事,ユニット及びその他
88
+ 1内外装工事,内外装
89
+ 排水,屋外排水
90
+ 石工事,石
91
+ 解体工事,とりこわし
92
+ 木,木工
93
+ 屋根及び樋,屋根及びとい
94
+ サイン,ユニット及びその他
95
+ 改修,改修
96
+ 大口径気送管設備,機械設備
97
+ 小荷物搬送用昇降機,昇降機
98
+ 下請諸経費,諸経費
99
+ 舗装工事,構内舗装
100
+ 囲障工事,囲障
101
+ 排水工事,屋外排水
102
+ 植栽工事,植栽
103
+ その他工事,ユニット及びその他
104
+ 撤去,とりこわし
105
+ 躯体改修,改修
106
+ 外壁改修,改修
107
+ 建具改修,改修
108
+ 内装改修,改修
109
+ 塗装改修,改修
110
+ 発生材,とりこわし
111
+ 防水改修,改修
112
+ 解体,とりこわし
113
+ 電機設備,電気設備
114
+ 機械設備,機械設備
115
+ エレベーター設備,昇降機
116
+ 免震装置,免震
117
+ 区画工事,
118
+ 樹木撤去工事,とりこわし
119
+ 既存杭撤去,とりこわし
120
+ 昇降機設備,昇降機
121
+ とりこわし,とりこわし
122
+ PC合成床板,PC
123
+ 外構,構内舗装
124
+ 旧別館基礎,とりこわし
125
+ 旧議会庁舎基礎,とりこわし
126
+ 建築,鉄筋
127
+ 上屋工事,附属棟
128
+ 設備工事解体工事と連絡通路など,とりこわし
main.py CHANGED
@@ -1,21 +1,109 @@
1
  import sys
2
  import os
3
  import time
4
- from fastapi import FastAPI
 
5
  import uvicorn
6
  import traceback
 
 
 
 
 
7
 
8
- # Điều chỉnh đường dẫn để import từ thư mục meisai-check-ai
9
  current_dir = os.path.dirname(os.path.abspath(__file__))
10
  sys.path.append(os.path.join(current_dir, "meisai-check-ai"))
11
 
12
  from sentence_transformer_lib.sentence_transformer_helper import (
13
  SentenceTransformerHelper,
14
  )
15
- from data_lib.base_data import BaseData
16
  from data_lib.input_name_data import InputNameData
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
17
 
18
- app = FastAPI()
 
 
 
 
19
 
20
 
21
  @app.get("/")
@@ -28,18 +116,68 @@ async def health_check():
28
  return {"status": "ok", "timestamp": time.time()}
29
 
30
 
31
- @app.get("/test-dependencies")
32
- async def test_dependencies():
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
33
  try:
34
- # Kiểm tra các dependencies đã được import thành công
35
- transformer_helper = SentenceTransformerHelper()
36
- return {"status": "success", "message": "All dependencies loaded successfully"}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
37
  except Exception as e:
38
- return {
39
- "status": "error",
40
- "message": str(e),
41
- "traceback": traceback.format_exc(),
42
- }
43
 
44
 
45
  if __name__ == "__main__":
 
1
  import sys
2
  import os
3
  import time
4
+ from fastapi import FastAPI, UploadFile, File, HTTPException
5
+ from fastapi.responses import FileResponse
6
  import uvicorn
7
  import traceback
8
+ import pickle
9
+ import shutil
10
+ from pathlib import Path
11
+ from contextlib import asynccontextmanager
12
+ import pandas as pd
13
 
 
14
  current_dir = os.path.dirname(os.path.abspath(__file__))
15
  sys.path.append(os.path.join(current_dir, "meisai-check-ai"))
16
 
17
  from sentence_transformer_lib.sentence_transformer_helper import (
18
  SentenceTransformerHelper,
19
  )
 
20
  from data_lib.input_name_data import InputNameData
21
+ from data_lib.subject_data import SubjectData
22
+ from data_lib.sample_name_data import SampleNameData
23
+ from clustering_lib.sentence_clustering_lib import SentenceClusteringLib
24
+ from data_lib.base_data import (
25
+ COL_STANDARD_NAME,
26
+ COL_STANDARD_NAME_KEY,
27
+ COL_STANDARD_SUBJECT,
28
+ )
29
+ from mapping_lib.name_mapping_helper import NameMappingHelper
30
+
31
+ # Initialize global variables for model and data
32
+ sentenceTransformerHelper = None
33
+ dic_standard_subject = None
34
+ sample_name_sentence_embeddings = None
35
+ sample_name_sentence_similarities = None
36
+ sampleData = None
37
+ sentence_clustering_lib = None
38
+ name_groups = None
39
+
40
+ # Create data directory if it doesn't exist
41
+ os.makedirs(os.path.join(current_dir, "data"), exist_ok=True)
42
+ os.makedirs(os.path.join(current_dir, "uploads"), exist_ok=True)
43
+ os.makedirs(os.path.join(current_dir, "outputs"), exist_ok=True)
44
+
45
+
46
+ @asynccontextmanager
47
+ async def lifespan(app: FastAPI):
48
+ """Lifespan context manager for startup and shutdown events"""
49
+ global sentenceTransformerHelper, dic_standard_subject, sample_name_sentence_embeddings
50
+ global sample_name_sentence_similarities, sampleData, sentence_clustering_lib, name_groups
51
+
52
+ try:
53
+ # Load sentence transformer model
54
+ sentenceTransformerHelper = SentenceTransformerHelper(
55
+ convert_to_zenkaku_flag=True, replace_words=None, keywords=None
56
+ )
57
+ sentenceTransformerHelper.load_model_by_name(
58
+ "Detomo/cl-nagoya-sup-simcse-ja-for-standard-name-v1_0"
59
+ )
60
+
61
+ # Load standard subject dictionary
62
+ dic_standard_subject = SubjectData.create_standard_subject_dic_from_file(
63
+ "data/subjectData.csv"
64
+ )
65
+
66
+ # Load pre-computed embeddings and similarities
67
+ with open(
68
+ f"data/sample_name_sentence_embeddings(cl-nagoya-sup-simcse-ja-base).pkl",
69
+ "rb",
70
+ ) as f:
71
+ sample_name_sentence_embeddings = pickle.load(f)
72
+
73
+ with open(
74
+ f"data/sample_name_sentence_similarities(cl-nagoya-sup-simcse-ja-base).pkl",
75
+ "rb",
76
+ ) as f:
77
+ sample_name_sentence_similarities = pickle.load(f)
78
+
79
+ # Load and process sample data
80
+ sampleData = SampleNameData()
81
+ file_path = os.path.join(current_dir, "data", "sampleData.csv")
82
+ sampleData.load_data_from_csv(file_path)
83
+ sampleData.process_data()
84
+
85
+ # Create sentence clusters
86
+ sentence_clustering_lib = SentenceClusteringLib(sample_name_sentence_embeddings)
87
+ best_name_eps = 0.07
88
+ name_groups, _ = sentence_clustering_lib.create_sentence_cluster(best_name_eps)
89
+ sampleData._create_key_column(
90
+ COL_STANDARD_NAME_KEY, COL_STANDARD_SUBJECT, COL_STANDARD_NAME
91
+ )
92
+ sampleData.set_name_sentence_labels(name_groups)
93
+ sampleData.build_search_tree()
94
+
95
+ print("Models and data loaded successfully")
96
+ except Exception as e:
97
+ print(f"Error during startup: {e}")
98
+ traceback.print_exc()
99
+
100
+ yield # This is where the app runs
101
 
102
+ # Cleanup code (if needed) goes here
103
+ print("Shutting down application")
104
+
105
+
106
+ app = FastAPI(lifespan=lifespan)
107
 
108
 
109
  @app.get("/")
 
116
  return {"status": "ok", "timestamp": time.time()}
117
 
118
 
119
+ @app.post("/predict")
120
+ async def predict(file: UploadFile = File(...)):
121
+ """
122
+ Process an input CSV file and return standardized names
123
+ """
124
+ global sentenceTransformerHelper, dic_standard_subject, sample_name_sentence_embeddings
125
+ global sample_name_sentence_similarities, sampleData, name_groups
126
+
127
+ if not file.filename.endswith(".csv"):
128
+ raise HTTPException(status_code=400, detail="Only CSV files are supported")
129
+
130
+ # Save uploaded file
131
+ timestamp = int(time.time())
132
+ input_file_path = os.path.join(current_dir, "uploads", f"input_{timestamp}.csv")
133
+
134
+ # Change output file to Excel format
135
+ output_file_path = os.path.join(current_dir, "outputs", f"output_{timestamp}.xlsx")
136
+
137
+ try:
138
+ with open(input_file_path, "wb") as buffer:
139
+ shutil.copyfileobj(file.file, buffer)
140
+ finally:
141
+ file.file.close()
142
+
143
  try:
144
+ # Process input data
145
+ inputData = InputNameData(dic_standard_subject)
146
+ inputData.load_data_from_csv(input_file_path)
147
+ inputData.process_data()
148
+
149
+ # Map standard names
150
+ nameMappingHelper = NameMappingHelper(
151
+ sentenceTransformerHelper,
152
+ inputData,
153
+ sampleData,
154
+ sample_name_sentence_embeddings,
155
+ sample_name_sentence_similarities,
156
+ )
157
+ df_predicted = nameMappingHelper.map_standard_names()
158
+
159
+ # Create output dataframe and save to CSV - Fix SettingWithCopyWarning by creating a copy
160
+ columns_to_keep = ["ファイル名", "シート名", "行", "科目", "名称"]
161
+ output_df = inputData.dataframe[columns_to_keep].copy()
162
+
163
+ # Use .loc to avoid SettingWithCopyWarning
164
+ output_df.loc[:, COL_STANDARD_SUBJECT] = df_predicted[COL_STANDARD_SUBJECT]
165
+ output_df.loc[:, COL_STANDARD_NAME] = df_predicted[COL_STANDARD_NAME]
166
+
167
+ # Save as Excel file instead of CSV for better Japanese character support
168
+ output_df.to_excel(output_file_path, index=False, engine="openpyxl")
169
+
170
+ # Return the Excel file as a download
171
+ return FileResponse(
172
+ path=output_file_path,
173
+ filename=f"output_{Path(file.filename).stem}.xlsx",
174
+ media_type="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
175
+ )
176
+
177
  except Exception as e:
178
+ print(f"Error processing file: {e}")
179
+ traceback.print_exc()
180
+ raise HTTPException(status_code=500, detail=str(e))
 
 
181
 
182
 
183
  if __name__ == "__main__":
requirements.txt CHANGED
@@ -15,4 +15,7 @@ oauth2client
15
  wandb
16
  scikit-learn
17
  fastapi
18
- uvicorn
 
 
 
 
15
  wandb
16
  scikit-learn
17
  fastapi
18
+ uvicorn
19
+ matplotlib
20
+ openpyxl
21
+ pandas