matsuap commited on
Commit
1a2f833
·
1 Parent(s): 05dae99

住所処理機能を改善し、47都道府県のリストを追加。テキストから都道府県名を抽出する関数を実装し、前処理の流れを更新。Gradioタブに新しい機能を追加し、ユーザーが住所を入力できるようにした。

Browse files
Files changed (1) hide show
  1. app.py +123 -93
app.py CHANGED
@@ -37,6 +37,17 @@ VECTOR_SEARCH_COLLECTION_NAME_V2 = os.environ.get('VECTOR_SEARCH_COLLECTION_NAME
37
  MILVUS_CLIENT = MilvusClient(uri=VECTOR_SEARCH_ENDPOINT, token=VECTOR_SEARCH_TOKEN)
38
  print(f"Connected to DB: {VECTOR_SEARCH_ENDPOINT} successfully")
39
 
 
 
 
 
 
 
 
 
 
 
 
40
  # ----------------------------
41
  # Download mt_city_all.csv
42
  # ----------------------------
@@ -82,7 +93,6 @@ for lg_code in tqdm(lg_codes):
82
  # Download mt_rsdtdsp_rsdt_prefXX.csv
83
  # ------------------------------------
84
  pref_codes = list(set([('%06d' % lg_code)[0:2] for lg_code in lg_codes]))
85
- print('pref_codes', len(pref_codes))
86
 
87
  for pref_code in tqdm(pref_codes):
88
  rsdt_url = f'https://catalog.registries.digital.go.jp/rsc/address/mt_rsdtdsp_rsdt_pref{pref_code}.csv.zip'
@@ -185,22 +195,19 @@ def remove_filler(input_text: str) -> str:
185
 
186
  return cleaned_text
187
 
 
 
 
 
 
 
 
188
  def preprocess(input_text):
189
- output_text = replace_circle(input_text)
 
190
  output_text = remove_filler(output_text)
191
  return output_text
192
 
193
- # 47都道府県のリスト
194
- prefs = [
195
- '北海道', '青森県', '岩手県', '宮城県', '秋田県', '山形県', '福島県',
196
- '茨城県', '栃木県', '群馬県', '埼玉県', '千葉県', '東京都', '神奈川県',
197
- '新潟県', '富山県', '石川県', '福井県', '山梨県', '長野県', '岐阜県',
198
- '静岡県', '愛知県', '三重県', '滋賀県', '京都府', '大阪府', '兵庫県',
199
- '奈良県', '和歌山県', '鳥取県', '島根県', '岡山県', '広島県', '山口県',
200
- '徳島県', '香川県', '愛媛県', '高知県', '福岡県', '佐賀県', '長崎県',
201
- '熊本県', '大分県', '宮崎県', '鹿児島県', '沖縄県'
202
- ]
203
-
204
  class InferenceEndpointErrorCode(Enum):
205
  INVALID_STATE = 400
206
  SERVICE_UNAVAILABLE = 503
@@ -276,7 +283,7 @@ def get_addresses_with_parcel(pref, county, city, ward, oaza_cho, chome, koaza):
276
  lg_code = get_lg_code(pref, county, city, ward)
277
  parcel_city_file = TARGET_DIR / 'parcel' / f'mt_parcel_city{lg_code:06d}.csv'
278
  if not os.path.exists(parcel_city_file):
279
- raise gr.Error('Too many lg_code')
280
  parcel_city_df = pd.read_csv(parcel_city_file)
281
 
282
  cities = parcel_city_df['city'].fillna('')
@@ -296,6 +303,9 @@ def get_addresses_with_parcel(pref, county, city, ward, oaza_cho, chome, koaza):
296
  koaza_mask = koazas == koaza
297
  parcel_city_df_filtered = parcel_city_df[city_mask & town_mask & koaza_mask]
298
 
 
 
 
299
  cities = parcel_city_df_filtered['city'].fillna('')
300
  wards = parcel_city_df_filtered['ward'].fillna('')
301
  oaza_chos = parcel_city_df_filtered['oaza_cho'].fillna('')
@@ -314,59 +324,8 @@ def get_addresses_with_parcel(pref, county, city, ward, oaza_cho, chome, koaza):
314
  cities, wards, oaza_chos, chomes, koazas, prc_num1s, prc_num2s, prc_num3s
315
  )
316
  ]
317
-
318
- pref_names = [
319
- '北海道',
320
- '青森県',
321
- '岩手県',
322
- '宮城県',
323
- '秋田県',
324
- '山形県',
325
- '福島県',
326
- '茨城県',
327
- '栃木県',
328
- '群馬県',
329
- '埼玉県',
330
- '千葉県',
331
- '東京都',
332
- '神奈川県',
333
- '新潟県',
334
- '富山県',
335
- '石川県',
336
- '福井県',
337
- '山梨県',
338
- '長野県',
339
- '岐阜県',
340
- '静岡県',
341
- '愛知県',
342
- '三重県',
343
- '滋賀県',
344
- '京都府',
345
- '大阪府',
346
- '兵庫県',
347
- '奈良県',
348
- '和歌山県',
349
- '鳥取県',
350
- '島根県',
351
- '岡山県',
352
- '広島県',
353
- '山口県',
354
- '徳島県',
355
- '香川県',
356
- '愛媛県',
357
- '高知県',
358
- '福岡県',
359
- '佐賀県',
360
- '長崎県',
361
- '熊本県',
362
- '大分県',
363
- '宮崎県',
364
- '鹿児島県',
365
- '沖縄県'
366
- ]
367
-
368
  def get_pref_code(pref):
369
- return pref_names.index(pref) + 1
370
 
371
  def get_addresses_with_rsdtdsp(pref, county, city, ward, oaza_cho, chome, koaza):
372
  pref_code = get_pref_code(pref)
@@ -387,6 +346,9 @@ def get_addresses_with_rsdtdsp(pref, county, city, ward, oaza_cho, chome, koaza)
387
 
388
  rsdtdsp_df_filtered = rsdtdsp_df[city_mask & town_mask & koaza_mask]
389
 
 
 
 
390
  cities = rsdtdsp_df_filtered['city'].fillna('')
391
  wards = rsdtdsp_df_filtered['ward'].fillna('')
392
  oaza_chos = rsdtdsp_df_filtered['oaza_cho'].fillna('')
@@ -463,10 +425,48 @@ def normalize_address(query_address):
463
  # =========================
464
  # Gradio tabs definition
465
  # =========================
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
466
  def create_endpoint_test_tab():
 
 
 
 
 
 
 
 
 
 
 
467
  def create_replace_circle_tab():
468
  with gr.Tab("replace_circle"):
469
  in_tb = gr.Textbox(label='インプット', placeholder='テキストを入力してください')
 
470
  out_tb = gr.Textbox(label='アウトプット')
471
  exe_button = gr.Button(value='実行', variant='primary')
472
  exe_button.click(
@@ -477,6 +477,7 @@ def create_endpoint_test_tab():
477
  def create_remove_filler_tab():
478
  with gr.Tab("remove_filler"):
479
  in_tb = gr.Textbox(label='インプット', placeholder='テキストを入力してください')
 
480
  out_tb = gr.Textbox(label='アウトプット')
481
  exe_button = gr.Button(value='実行', variant='primary')
482
  exe_button.click(
@@ -487,6 +488,7 @@ def create_endpoint_test_tab():
487
  def create_preprocess_tab():
488
  with gr.Tab("preprocess"):
489
  in_tb = gr.Textbox(label='インプット', placeholder='テキストを入力してください')
 
490
  out_tb = gr.Textbox(label='アウトプット')
491
  exe_button = gr.Button(value='実行', variant='primary')
492
  exe_button.click(
@@ -497,6 +499,7 @@ def create_endpoint_test_tab():
497
  def create_compare_two_addresses_tab():
498
  with gr.Tab("compare_two_addresses"):
499
  in_tb1 = gr.Textbox(label='住所1 (顧客が発言した住所)', placeholder='住所を入力してください')
 
500
  in_tb2 = gr.Textbox(label='住所2 (CRM 内に格納されている住所)', placeholder='住所を入力してください')
501
  out_tb = gr.Textbox(label='アウトプット')
502
  exe_button = gr.Button(value='実行', variant='primary')
@@ -508,6 +511,7 @@ def create_endpoint_test_tab():
508
  def create_normalize_address_tab():
509
  with gr.Tab("normalize_address"):
510
  in_tb = gr.Textbox(label='住所', placeholder='住所を入力してください')
 
511
  out_tb = gr.Textbox(label='アウトプット')
512
  exe_button = gr.Button(value='実行', variant='primary')
513
  exe_button.click(
@@ -525,41 +529,67 @@ def create_endpoint_test_tab():
525
  inputs=[in_tb],
526
  outputs=[out_tb],
527
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
528
 
529
  with gr.Tab("関数テスト"):
 
530
  create_compare_two_addresses_tab()
 
 
 
531
  create_replace_circle_tab()
532
  create_remove_filler_tab()
533
  create_preprocess_tab()
534
- create_normalize_address_tab()
535
  create_split_address_tab()
536
 
537
- examples = [
538
- '私の住所は京都府京都市右京区太秦青木元町4-10です。',
539
- '京都府京都市右京区太秦青木元町4-10',
540
- '京都府京都市右京区太秦青木元町4-10ダックス101号室',
541
- '京都府宇治市伊勢田町名木1-1-4ダックス101号室',
542
- '東京都渋谷区道玄坂1-12-1',
543
- '私の住所は東京都渋谷区道玄坂1-12-1です。',
544
- '私の住所は東京都しぶや道玄坂1の12の1です。',
545
- '東京都渋谷区道玄坂1の12の1で契約しています。',
546
- '秋田県秋田市山王四丁目1番1号です。',
547
- '東京 墨田区 押上 1丁目1',
548
- '三重県伊勢市宇治館町',
549
- '住所は 030-0803 青森県青森市安方1丁目1−40になります。',
550
- '東京都大島町差木地 字クダッチ',
551
- '前橋市大手町1丁目1番地1',
552
- '東京都渋谷区表参道の3の5の6。',
553
- '琉球圏尾張町3の5の6に住んでます。',
554
- '3254987の場所です。',
555
- '大阪府でした。',
556
- '1940923の東京都渋谷区道玄坂一丁目。渋谷マークシティウェスト23階です。',
557
- '名前は山田太郎です。',
558
- 'はい。名古屋、あ、愛知県名古屋市南里2の3の4だと思います。',
559
- 'ー',
560
- '少し待ってください。',
561
- ]
562
-
563
  def create_digital_agency_tab():
564
  with gr.Tab("デジ庁API"):
565
  with gr.Row():
 
37
  MILVUS_CLIENT = MilvusClient(uri=VECTOR_SEARCH_ENDPOINT, token=VECTOR_SEARCH_TOKEN)
38
  print(f"Connected to DB: {VECTOR_SEARCH_ENDPOINT} successfully")
39
 
40
+ # 47都道府県のリスト
41
+ prefs = [
42
+ '北海道', '青森県', '岩手県', '宮城県', '秋田県', '山形県', '福島県',
43
+ '茨城県', '栃木県', '群馬県', '埼玉県', '千葉県', '東京都', '神奈川県',
44
+ '新潟県', '富山県', '石川県', '福井県', '山梨県', '長野県', '岐阜県',
45
+ '静岡県', '愛知県', '三重県', '滋賀県', '京都府', '大阪府', '兵庫県',
46
+ '奈良県', '和歌山県', '鳥取県', '島根県', '岡山県', '広島県', '山口県',
47
+ '徳島県', '香川県', '愛媛県', '高知県', '福岡県', '佐賀県', '長崎県',
48
+ '熊本県', '大分県', '宮崎県', '鹿児島県', '沖縄県'
49
+ ]
50
+
51
  # ----------------------------
52
  # Download mt_city_all.csv
53
  # ----------------------------
 
93
  # Download mt_rsdtdsp_rsdt_prefXX.csv
94
  # ------------------------------------
95
  pref_codes = list(set([('%06d' % lg_code)[0:2] for lg_code in lg_codes]))
 
96
 
97
  for pref_code in tqdm(pref_codes):
98
  rsdt_url = f'https://catalog.registries.digital.go.jp/rsc/address/mt_rsdtdsp_rsdt_pref{pref_code}.csv.zip'
 
195
 
196
  return cleaned_text
197
 
198
+ def remove_left_of_pref(text):
199
+ for pref in prefs:
200
+ pref_index = text.find(pref)
201
+ if pref_index != -1:
202
+ return text[pref_index:] # 都道府県名の位置から右側の文字列を返す
203
+ return text # 都道府県名が見つからない場合は元のテキストを返す
204
+
205
  def preprocess(input_text):
206
+ output_text = remove_left_of_pref(input_text)
207
+ output_text = replace_circle(output_text)
208
  output_text = remove_filler(output_text)
209
  return output_text
210
 
 
 
 
 
 
 
 
 
 
 
 
211
  class InferenceEndpointErrorCode(Enum):
212
  INVALID_STATE = 400
213
  SERVICE_UNAVAILABLE = 503
 
283
  lg_code = get_lg_code(pref, county, city, ward)
284
  parcel_city_file = TARGET_DIR / 'parcel' / f'mt_parcel_city{lg_code:06d}.csv'
285
  if not os.path.exists(parcel_city_file):
286
+ raise gr.Error('Not found: ', parcel_city_file)
287
  parcel_city_df = pd.read_csv(parcel_city_file)
288
 
289
  cities = parcel_city_df['city'].fillna('')
 
303
  koaza_mask = koazas == koaza
304
  parcel_city_df_filtered = parcel_city_df[city_mask & town_mask & koaza_mask]
305
 
306
+ if len(parcel_city_df_filtered) == 0:
307
+ return [pref + county + city + ward + oaza_cho + chome + koaza]
308
+
309
  cities = parcel_city_df_filtered['city'].fillna('')
310
  wards = parcel_city_df_filtered['ward'].fillna('')
311
  oaza_chos = parcel_city_df_filtered['oaza_cho'].fillna('')
 
324
  cities, wards, oaza_chos, chomes, koazas, prc_num1s, prc_num2s, prc_num3s
325
  )
326
  ]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
327
  def get_pref_code(pref):
328
+ return prefs.index(pref) + 1
329
 
330
  def get_addresses_with_rsdtdsp(pref, county, city, ward, oaza_cho, chome, koaza):
331
  pref_code = get_pref_code(pref)
 
346
 
347
  rsdtdsp_df_filtered = rsdtdsp_df[city_mask & town_mask & koaza_mask]
348
 
349
+ if len(rsdtdsp_df_filtered) == 0:
350
+ return [pref + county + city + ward + oaza_cho + chome + koaza]
351
+
352
  cities = rsdtdsp_df_filtered['city'].fillna('')
353
  wards = rsdtdsp_df_filtered['ward'].fillna('')
354
  oaza_chos = rsdtdsp_df_filtered['oaza_cho'].fillna('')
 
425
  # =========================
426
  # Gradio tabs definition
427
  # =========================
428
+ examples = [
429
+ '私の住所は京都府京都市右京区太秦青木元町4-10です。',
430
+ '京都府京都市右京区太秦青木元町4-10',
431
+ '京都府京都市右京区太秦青木元町4-10ダックス101号室',
432
+ '京都府宇治市伊勢田町名木1-1-4ダックス101号室',
433
+ '東京都渋谷区道玄坂1-12-1',
434
+ '私の住所は東京都渋谷区道玄坂1-12-1です。',
435
+ '私の住所は東京都しぶや道玄坂1の12の1です。',
436
+ '東京都渋谷区道玄坂1の12の1で契約しています。',
437
+ '秋田県秋田市山王四丁目1番1号です。',
438
+ '東京 墨田区 押上 1丁目1',
439
+ '三重県伊勢市宇治館町',
440
+ '住所は 030-0803 青森県青森市安方1丁目1−40になります。',
441
+ '東京都大島町差木地 字クダッチ',
442
+ '前橋市大手町1丁目1番地1',
443
+ '東京都渋谷区表参道の3の5の6。',
444
+ '琉球圏尾張町3の5の6に住んでます。',
445
+ '3254987の場所です。',
446
+ '大阪府でした。',
447
+ '1940923の東京都渋谷区道玄坂一丁目。渋谷マークシティウェスト23階です。',
448
+ '名前は山田太郎です。',
449
+ 'はい。名古屋、あ、愛知県名古屋市南里2の3の4だと思います。',
450
+ 'ー',
451
+ '少し待ってください。',
452
+ ]
453
+
454
  def create_endpoint_test_tab():
455
+ def create_remove_left_of_pref_tab():
456
+ with gr.Tab("remove_left_of_pref"):
457
+ in_tb = gr.Textbox(label='インプット', placeholder='テキストを入力してください')
458
+ gr.Examples(examples=examples, inputs=[in_tb])
459
+ out_tb = gr.Textbox(label='アウトプット')
460
+ exe_button = gr.Button(value='実行', variant='primary')
461
+ exe_button.click(
462
+ fn=remove_left_of_pref,
463
+ inputs=[in_tb],
464
+ outputs=[out_tb],
465
+ )
466
  def create_replace_circle_tab():
467
  with gr.Tab("replace_circle"):
468
  in_tb = gr.Textbox(label='インプット', placeholder='テキストを入力してください')
469
+ gr.Examples(examples=examples, inputs=[in_tb])
470
  out_tb = gr.Textbox(label='アウトプット')
471
  exe_button = gr.Button(value='実行', variant='primary')
472
  exe_button.click(
 
477
  def create_remove_filler_tab():
478
  with gr.Tab("remove_filler"):
479
  in_tb = gr.Textbox(label='インプット', placeholder='テキストを入力してください')
480
+ gr.Examples(examples=examples, inputs=[in_tb])
481
  out_tb = gr.Textbox(label='アウトプット')
482
  exe_button = gr.Button(value='実行', variant='primary')
483
  exe_button.click(
 
488
  def create_preprocess_tab():
489
  with gr.Tab("preprocess"):
490
  in_tb = gr.Textbox(label='インプット', placeholder='テキストを入力してください')
491
+ gr.Examples(examples=examples, inputs=[in_tb])
492
  out_tb = gr.Textbox(label='アウトプット')
493
  exe_button = gr.Button(value='実行', variant='primary')
494
  exe_button.click(
 
499
  def create_compare_two_addresses_tab():
500
  with gr.Tab("compare_two_addresses"):
501
  in_tb1 = gr.Textbox(label='住所1 (顧客が発言した住所)', placeholder='住所を入力してください')
502
+ gr.Examples(examples=examples, inputs=[in_tb1])
503
  in_tb2 = gr.Textbox(label='住所2 (CRM 内に格納されている住所)', placeholder='住所を入力してください')
504
  out_tb = gr.Textbox(label='アウトプット')
505
  exe_button = gr.Button(value='実行', variant='primary')
 
511
  def create_normalize_address_tab():
512
  with gr.Tab("normalize_address"):
513
  in_tb = gr.Textbox(label='住所', placeholder='住所を入力してください')
514
+ gr.Examples(examples=examples, inputs=[in_tb])
515
  out_tb = gr.Textbox(label='アウトプット')
516
  exe_button = gr.Button(value='実行', variant='primary')
517
  exe_button.click(
 
529
  inputs=[in_tb],
530
  outputs=[out_tb],
531
  )
532
+ def create_vector_search():
533
+ def f(query_address, top_k):
534
+ with measure('preprocess'):
535
+ preprocessed = preprocess(query_address)
536
+ with measure('vector_search'):
537
+ hits = vector_search(preprocessed, top_k=top_k)
538
+ return pd.DataFrame(hits, columns=['Top-k', '類似度', '住所', '都道府県', '郡', '市区町村', '政令市区', '大字・町', '丁目', '小字'])
539
+ with gr.Tab("vector_search"):
540
+ in_tb = gr.Textbox(label='住所', placeholder='住所を入力してください')
541
+ gr.Examples(examples=examples, inputs=[in_tb])
542
+ top_k_input = gr.Slider(minimum=1, maximum=100, step=1, value=5, label='検索数top-k')
543
+ out_df = gr.Dataframe(label="アウトプット", wrap=True)
544
+ exe_button = gr.Button(value='実行', variant='primary')
545
+ exe_button.click(
546
+ fn=f,
547
+ inputs=[in_tb, top_k_input],
548
+ outputs=[out_df],
549
+ )
550
+ def create_get_addresses_with_parcel_tab():
551
+ def f(query_address):
552
+ with measure('preprocess'):
553
+ preprocessed = preprocess(query_address)
554
+ with measure('vector_search'):
555
+ hits = vector_search(preprocessed, top_k=1)
556
+ with measure('split_address'):
557
+ splits = {
558
+ 'pref': hits[0][3],
559
+ 'county': hits[0][4],
560
+ 'city': hits[0][5],
561
+ 'ward': hits[0][6],
562
+ 'oaza_cho': hits[0][7],
563
+ 'chome': hits[0][8],
564
+ 'koaza': hits[0][9],
565
+ }
566
+ with measure('get_addresses_with_parcel'):
567
+ addresses = get_addresses_with_parcel(
568
+ splits['pref'], splits['county'], splits['city'], splits['ward'],
569
+ splits['oaza_cho'], splits['chome'], splits['koaza'])
570
+ return pd.DataFrame(addresses, columns=['住所'])
571
+ with gr.Tab("get_addresses_with_parcel"):
572
+ in_tb = gr.Textbox(label='住所', placeholder='住所を入力してください')
573
+ gr.Examples(examples=examples, inputs=[in_tb])
574
+ out_df = gr.Dataframe(label="アウトプット", wrap=True)
575
+ exe_button = gr.Button(value='実行', variant='primary')
576
+ exe_button.click(
577
+ fn=f,
578
+ inputs=[in_tb],
579
+ outputs=[out_df],
580
+ )
581
 
582
  with gr.Tab("関数テスト"):
583
+ create_normalize_address_tab()
584
  create_compare_two_addresses_tab()
585
+ create_get_addresses_with_parcel_tab()
586
+ create_vector_search()
587
+ create_remove_left_of_pref_tab()
588
  create_replace_circle_tab()
589
  create_remove_filler_tab()
590
  create_preprocess_tab()
 
591
  create_split_address_tab()
592
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
593
  def create_digital_agency_tab():
594
  with gr.Tab("デジ庁API"):
595
  with gr.Row():