From e1b2d2e1b28ced2727a045726318a4a1173fd9a6 Mon Sep 17 00:00:00 2001 From: ssoxong Date: Sat, 9 Nov 2024 19:22:13 +0900 Subject: [PATCH 01/12] feat: requirements --- Dockerfile | 1 + crud/pronounce.py | 22 ++++++++++++++++------ requirements.txt | 11 +++++++++++ test.py | 5 ----- 4 files changed, 28 insertions(+), 11 deletions(-) delete mode 100644 test.py diff --git a/Dockerfile b/Dockerfile index 4d745dd..79736a2 100644 --- a/Dockerfile +++ b/Dockerfile @@ -3,6 +3,7 @@ FROM python:3.9 WORKDIR / +RUN pip freeze > requirements.txt COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt diff --git a/crud/pronounce.py b/crud/pronounce.py index 590717f..4d41247 100644 --- a/crud/pronounce.py +++ b/crud/pronounce.py @@ -1,5 +1,6 @@ from pecab import PeCab import crud +import crud.difficulty pecab = PeCab() def analysis_pronounce_crud(text): @@ -7,7 +8,8 @@ def analysis_pronounce_crud(text): return { "구개음화": analysis_gugaeumhwa(text, dec), "비음화": analysis_beumhwa(text, dec), - "유음화": analysis_yueumhwa(text, dec) + "유음화": analysis_yueumhwa(text, dec), + "연음화": analysis_yeoneumhwa(text, dec) } def analysis_gugaeumhwa(text, dec): @@ -51,11 +53,19 @@ def analysis_yueumhwa(text, dec): def analysis_yeoneumhwa(text, dec): yeoneumhwa=[] + pos = pecab.pos(text) - for i, r in enumerate(dec): - r = [col for col in r if col.strip()] - if len(r)!=3: continue - if r[2]=='ㄹ' and dec[i+1][0]=='ㄹ': - yeoneumhwa.append(text[i:i+2]) + # 모음(ㅇ)으로 시작되는 조사, 어미, 접미사인 경우 연음화 + josa = ['JKS', 'JKC', 'JKG', 'JKO', 'JKB', 'JKV', 'JKQ', 'JX', 'JC', 'EP', 'EF', 'EC', 'ETN', 'ETM', 'XSN','XSV','XSA'] + for i, (word, tag) in enumerate(pos): + wdec = crud.difficulty.decomposition(word) + if wdec[-1][0] != 'ㅇ': continue + if tag not in josa: continue + forward = pos[i-1][0] + fdec = crud.difficulty.decomposition(forward) + fdec = [col for col in fdec[-1] if col.strip()] + if len(fdec)!=3: continue + yeoneumhwa.append(forward+word) + # 받침 뒤에 ㅏ, ㅓ, ㅗ, ㅜ, ㅟ로 시작하는 실질 형태소가 오는 경우 return yeoneumhwa \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index eee1d48..d225a66 100644 --- a/requirements.txt +++ b/requirements.txt @@ -5,17 +5,28 @@ certifi==2024.8.30 click==8.1.7 colorama==0.4.6 distro==1.9.0 +emoji==1.2.0 exceptiongroup==1.2.2 fastapi==0.115.4 h11==0.14.0 httpcore==1.0.6 httpx==0.27.2 idna==3.10 +iniconfig==2.0.0 jiter==0.7.0 +mecab==0.996.5 +numpy==2.0.2 +packaging==24.1 +pecab==1.0.8 +pluggy==1.5.0 +pyarrow==18.0.0 pydantic==2.9.2 pydantic_core==2.23.4 +pytest==8.3.3 python-dotenv==1.0.1 +regex==2024.11.6 sniffio==1.3.1 starlette==0.41.2 +tomli==2.0.2 typing_extensions==4.12.2 uvicorn==0.32.0 diff --git a/test.py b/test.py deleted file mode 100644 index 398b8ed..0000000 --- a/test.py +++ /dev/null @@ -1,5 +0,0 @@ -from pecab import PeCab -pecab = PeCab() - -text= "옷이 구겨졌어요. 꽃이 예뻐요" -print(pecab.pos(text)) \ No newline at end of file From ade7362984a3ce53a3045a9231c7cea9137a85ee Mon Sep 17 00:00:00 2001 From: ssoxong Date: Sat, 9 Nov 2024 19:25:41 +0900 Subject: [PATCH 02/12] feat: modify docker --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 79736a2..266e791 100644 --- a/Dockerfile +++ b/Dockerfile @@ -3,7 +3,7 @@ FROM python:3.9 WORKDIR / -RUN pip freeze > requirements.txt +# RUN pip freeze > requirements.txt COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt From 9ffdc468adc8b3bba9e5ff7e3549bdef4eb4f8c2 Mon Sep 17 00:00:00 2001 From: ssoxong Date: Sat, 9 Nov 2024 19:28:11 +0900 Subject: [PATCH 03/12] =?UTF-8?q?feat:=20=EA=BC=AC=EC=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Dockerfile | 1 - 1 file changed, 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 266e791..4d745dd 100644 --- a/Dockerfile +++ b/Dockerfile @@ -3,7 +3,6 @@ FROM python:3.9 WORKDIR / -# RUN pip freeze > requirements.txt COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt From 6a8f0af6f513a8f106affe9c6b217a7213c289cb Mon Sep 17 00:00:00 2001 From: ssoxong Date: Sat, 9 Nov 2024 19:39:50 +0900 Subject: [PATCH 04/12] feat: docker ignore --- .dockerignore | 16 ++++++++++++++++ Dockerfile | 7 ++++--- main.py | 2 +- requirements.txt | 1 - ...31638027518579_66b9f0945dd57334d0755ca4.jpeg | Bin 77621 -> 0 bytes 5 files changed, 21 insertions(+), 5 deletions(-) create mode 100644 .dockerignore delete mode 100644 static/103826131638027518579_66b9f0945dd57334d0755ca4.jpeg diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..78ba008 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,16 @@ +# Ignore Python cache +__pycache__/ +*.pyc +*.pyo + +# Ignore virtual environment +venv/ + +# Ignore environment file +.env + +# Ignore Git files +.git/ +.gitignore +bada + diff --git a/Dockerfile b/Dockerfile index 4d745dd..90ad277 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,10 +1,11 @@ # Dockerfile -FROM python:3.9 +FROM python:3.9-slim -WORKDIR / +WORKDIR /app/bada-py COPY requirements.txt . -RUN pip install --no-cache-dir -r requirements.txt +RUN pip install --no-cache-dir --upgrade pip && \ + pip install --no-cache-dir -r requirements.txt COPY . . diff --git a/main.py b/main.py index 7f9ef48..a409e0c 100644 --- a/main.py +++ b/main.py @@ -98,7 +98,7 @@ async def root(): if __name__ == "__main__": import uvicorn - uvicorn.run("main:app", host="0.0.0.0", port=8000, reload=True) + uvicorn.run("main:app", host="127.0.0.1", port=8000, reload=True) # uvicorn main:app --reload diff --git a/requirements.txt b/requirements.txt index d225a66..a2b57e9 100644 --- a/requirements.txt +++ b/requirements.txt @@ -14,7 +14,6 @@ httpx==0.27.2 idna==3.10 iniconfig==2.0.0 jiter==0.7.0 -mecab==0.996.5 numpy==2.0.2 packaging==24.1 pecab==1.0.8 diff --git a/static/103826131638027518579_66b9f0945dd57334d0755ca4.jpeg b/static/103826131638027518579_66b9f0945dd57334d0755ca4.jpeg deleted file mode 100644 index f64341914d57038c77726e914726cbfec0a66131..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 77621 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�SM7y+ayE87iYuA%w&NkA(Mj;1f-kp0tF`{8mVs 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 KGIh%R_xnG3qcL~@ From bf9849012fff45cce51cdb9f2c1f229449d4b987 Mon Sep 17 00:00:00 2001 From: ssoxong Date: Tue, 12 Nov 2024 16:02:05 +0900 Subject: [PATCH 05/12] feat: pronounce rule --- crud/difficulty.py | 2 +- crud/pronounce.py | 94 +++++++++++++++++++++++++++++++++++++++++++++- main.py | 3 +- requirements.txt | 2 +- test.py | 5 +++ 5 files changed, 100 insertions(+), 6 deletions(-) create mode 100644 test.py diff --git a/crud/difficulty.py b/crud/difficulty.py index c70d5a5..f195172 100644 --- a/crud/difficulty.py +++ b/crud/difficulty.py @@ -18,6 +18,6 @@ def decomposition(korean_word: str): res.append([CHOSUNG_LIST[ch1], JUNGSUNG_LIST[ch2], JONGSUNG_LIST[ch3]]) else: res.append([w]) - print (res) + # print (res) return res \ No newline at end of file diff --git a/crud/pronounce.py b/crud/pronounce.py index 4d41247..821a63f 100644 --- a/crud/pronounce.py +++ b/crud/pronounce.py @@ -9,7 +9,10 @@ def analysis_pronounce_crud(text): "구개음화": analysis_gugaeumhwa(text, dec), "비음화": analysis_beumhwa(text, dec), "유음화": analysis_yueumhwa(text, dec), - "연음화": analysis_yeoneumhwa(text, dec) + "연음화": analysis_yeoneumhwa(text, dec), + "경음화": anaylsis_gyeonumhwa(text, dec), + "겹받침 쓰기": doubleb_analysis(text, dec), + "거센소리": geosensori_analysis(text, dec) } def analysis_gugaeumhwa(text, dec): @@ -19,6 +22,7 @@ def analysis_gugaeumhwa(text, dec): for i, r in enumerate(dec): r = [col for col in r if col.strip()] if len(r)!=3: continue + if i+1>=len(dec): continue if not (r[2]=='ㄷ' or r[2]=='ㅌ'): continue print(r) if (text[i+1]=='이' or text[i+1]=='히'): @@ -33,6 +37,8 @@ def analysis_beumhwa(text, dec): for i, r in enumerate(dec): r = [col for col in r if col.strip()] if len(r)!=3: continue + if i+1>=len(dec): continue + if r[2] in payeoleum and dec[i+1][0] in beeum: beumhwa.append(text[i:i+2]) @@ -44,6 +50,8 @@ def analysis_yueumhwa(text, dec): for i, r in enumerate(dec): r = [col for col in r if col.strip()] if len(r)!=3: continue + if i+1>len(dec): continue + if r[2]=='ㄹ' and dec[i+1][0]=='ㄴ': yueumhwa.append(text[i:i+2]) elif r[2]=='ㄴ' and dec[i+1][0]=='ㄹ': @@ -68,4 +76,86 @@ def analysis_yeoneumhwa(text, dec): yeoneumhwa.append(forward+word) # 받침 뒤에 ㅏ, ㅓ, ㅗ, ㅜ, ㅟ로 시작하는 실질 형태소가 오는 경우 - return yeoneumhwa \ No newline at end of file + return yeoneumhwa + +def anaylsis_gyeonumhwa(text, dec): + gyeongumhwa = [] + pos = pecab.pos(text) + + # 받침 뒤 + b1list = ['ㄱ','ㄷ','ㅂ', 'ㄲ','ㅋ','ㄳ','ㄺ','ㅅ','ㅆ','ㅈ','ㅊ','ㅌ','ㅍ','ㄼ','ㄿ','ㅄ'] + b2list = ['ㄼ', 'ㄾ'] + + n1list = ['ㄱ','ㄷ','ㅂ','ㅅ','ㅈ'] + n2list = ['ㄱ','ㄷ','ㅅ','ㅈ'] + for i, r in enumerate(dec): + r = [col for col in r if col.strip()] + if len(r)!=3: continue + if i+1>=len(dec): continue + + # 받침 ㄱ,ㄷ,ㅂ 뒤 ㄱㄷㅂㅅㅈ + if r[2] in b1list and dec[i+1][0] in n1list: + gyeongumhwa.append(text[i:i+2]) + # 어간 받침 ㄼ, ㄾ 뒤 ㄱ, ㄷ, ㅅ, ㅈ + if r[2] in b2list and dec[i+1][0] in n2list: + gyeongumhwa.append(text[i:i+2]) + + # 용언의 어간 받침 ㄴ, ㅁ 뒤 ㄱ, ㄷ, ㅅ, ㅈ + # VV(동사)[2] + for i, (word, tag) in enumerate(pos): + if tag == 'VV': + wdec = crud.difficulty.decomposition(word) + if wdec[-1][2] not in ['ㄴ','ㅁ']: continue + sdec = crud.difficulty.decomposition(pos[i+1][0]) + if sdec[-1][0] not in n2list: continue + gyeongumhwa.append(word+pos[i+1][0]) + + + # 관형사형 어미 -(으)ㄹ 뒤 ㄱ, ㄷ, ㅂ, ㅅ, ㅈ + # ETM + for i, (word, tag) in enumerate(pos): + print(tag) + if 'ETM' in tag: + wdec = crud.difficulty.decomposition(word) + if wdec[-1][2] not in ['ㄹ']: continue + sdec = crud.difficulty.decomposition(pos[i+1][0]) + + if sdec[0][0] not in n1list: continue + gyeongumhwa.append(word+pos[i+1][0]) + + # 한자어 ㄹ 받침 뒤 ㄷ, ㅅ, ㅈ + return gyeongumhwa + +def doubleb_analysis(text, dec): + # 겹받침 + + doubleb = [] + doubleblist = ['ㄳ', 'ㄵ', 'ㄶ', 'ㄺ', 'ㄻ', 'ㄼ', 'ㄽ', 'ㄾ', 'ㄿ', 'ㅀ', 'ㅄ'] + for i, r in enumerate(dec): + r = [col for col in r if col.strip()] + if len(r)!=3: continue + if i+1>=len(dec): continue + + # 받침 ㄱ,ㄷ,ㅂ 뒤 ㄱㄷㅂㅅㅈ + if r[2] in doubleblist: + doubleb.append(text[i:i+2]) + + return doubleb + +def geosensori_analysis(text, dec): + geosensori=[] + geosensorilist = ['ㅎ','ㄶ','ㅀ'] + trigger = ['ㄱ', 'ㄷ', 'ㅂ', 'ㅈ', 'ㄵ', 'ㄺ', 'ㄼ'] + + for i, r in enumerate(dec): + r = [col for col in r if col.strip()] + if len(r)!=3: continue + if i+1>=len(dec): continue + + # 받침 ㄱ,ㄷ,ㅂ 뒤 ㄱㄷㅂㅅㅈ + if r[2] in geosensorilist and dec[i+1][0] in trigger: + geosensori.append(text[i:i+2]) + if r[2] in trigger and dec[i+1][0] in geosensorilist: + geosensori.append(text[i:i+2]) + + return geosensori \ No newline at end of file diff --git a/main.py b/main.py index a409e0c..efc42ec 100644 --- a/main.py +++ b/main.py @@ -112,5 +112,4 @@ def difficulty_dec(s: str): m_list.append(i[1]) if len(i) == 3: b_list.append(i[2]) - return b_list, m_list - + return b_list, m_list \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index a2b57e9..931a668 100644 --- a/requirements.txt +++ b/requirements.txt @@ -14,7 +14,7 @@ httpx==0.27.2 idna==3.10 iniconfig==2.0.0 jiter==0.7.0 -numpy==2.0.2 +numpy==2.0.2docker packaging==24.1 pecab==1.0.8 pluggy==1.5.0 diff --git a/test.py b/test.py new file mode 100644 index 0000000..97dccfa --- /dev/null +++ b/test.py @@ -0,0 +1,5 @@ +from pecab import PeCab +pecab = PeCab() + +text = "밥을 담고 할 사람? 열정있게" +print(pecab.pos(text)) From 92c0deca791a9084bb4d93b4ebc0eeb385a8d48e Mon Sep 17 00:00:00 2001 From: So Hyeon Date: Wed, 13 Nov 2024 19:21:34 +0900 Subject: [PATCH 06/12] =?UTF-8?q?feat:=20=EA=B2=B9=EB=B0=9B=EC=B9=A8=20(#6?= =?UTF-8?q?)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- crud/pronounce.py | 12 ++++++------ main.py | 11 +++++++++-- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/crud/pronounce.py b/crud/pronounce.py index 821a63f..cb83227 100644 --- a/crud/pronounce.py +++ b/crud/pronounce.py @@ -24,7 +24,6 @@ def analysis_gugaeumhwa(text, dec): if len(r)!=3: continue if i+1>=len(dec): continue if not (r[2]=='ㄷ' or r[2]=='ㅌ'): continue - print(r) if (text[i+1]=='이' or text[i+1]=='히'): gugaeumhwa.append(text[i:i+2]) @@ -32,7 +31,7 @@ def analysis_gugaeumhwa(text, dec): def analysis_beumhwa(text, dec): beumhwa=[] - payeoleum = ['ㅂ','ㄷ','ㄱ'] + payeoleum = ['ㅂ','ㄷ','ㄱ', 'ㅍ','ㄼ','ㅄ','ㅅ','ㅆ','ㅈ','ㅊ','ㅎ','ㄲ','ㅋ','ㄺ'] beeum = ['ㄴ','ㅁ'] for i, r in enumerate(dec): r = [col for col in r if col.strip()] @@ -50,7 +49,7 @@ def analysis_yueumhwa(text, dec): for i, r in enumerate(dec): r = [col for col in r if col.strip()] if len(r)!=3: continue - if i+1>len(dec): continue + if i+1>=len(dec): continue if r[2]=='ㄹ' and dec[i+1][0]=='ㄴ': yueumhwa.append(text[i:i+2]) @@ -73,6 +72,7 @@ def analysis_yeoneumhwa(text, dec): fdec = crud.difficulty.decomposition(forward) fdec = [col for col in fdec[-1] if col.strip()] if len(fdec)!=3: continue + if fdec[2]=='ㅇ': continue yeoneumhwa.append(forward+word) # 받침 뒤에 ㅏ, ㅓ, ㅗ, ㅜ, ㅟ로 시작하는 실질 형태소가 오는 경우 @@ -103,6 +103,7 @@ def anaylsis_gyeonumhwa(text, dec): # 용언의 어간 받침 ㄴ, ㅁ 뒤 ㄱ, ㄷ, ㅅ, ㅈ # VV(동사)[2] for i, (word, tag) in enumerate(pos): + print(word, tag) if tag == 'VV': wdec = crud.difficulty.decomposition(word) if wdec[-1][2] not in ['ㄴ','ㅁ']: continue @@ -114,10 +115,9 @@ def anaylsis_gyeonumhwa(text, dec): # 관형사형 어미 -(으)ㄹ 뒤 ㄱ, ㄷ, ㅂ, ㅅ, ㅈ # ETM for i, (word, tag) in enumerate(pos): - print(tag) if 'ETM' in tag: wdec = crud.difficulty.decomposition(word) - if wdec[-1][2] not in ['ㄹ']: continue + if wdec[-1][0]!='ㅇ' or wdec[-1][2] != 'ㄹ': continue sdec = crud.difficulty.decomposition(pos[i+1][0]) if sdec[0][0] not in n1list: continue @@ -138,7 +138,7 @@ def doubleb_analysis(text, dec): # 받침 ㄱ,ㄷ,ㅂ 뒤 ㄱㄷㅂㅅㅈ if r[2] in doubleblist: - doubleb.append(text[i:i+2]) + doubleb.append(text[i]) return doubleb diff --git a/main.py b/main.py index fb4d54f..63d9974 100644 --- a/main.py +++ b/main.py @@ -1,5 +1,6 @@ from fastapi import FastAPI, HTTPException from pydantic import BaseModel, Field +from typing import Dict import os from dotenv import load_dotenv import json @@ -26,10 +27,16 @@ class ClaudeRequest(BaseModel): age: int = Field(default=11) rule: PronounceRule count: int = Field(default=5) + @app.post("/phonological_rules") -async def analysis_pronounce(text: str): - return crud.pronounce.analysis_pronounce_crud(text) +async def analysis_pronounce(text: Dict[int, str]): + analysis = {} + for n, t in text.items(): + if not t: + raise HTTPException(status_code=400, detail="text에 빈 문자열이 포함되어 있습니다.") + analysis[n]=crud.pronounce.analysis_pronounce_crud(t) + return analysis @app.post("/claude") async def generate_claude(request: ClaudeRequest): From db51b66db8f42c91cf6e5b9d7ddb81fba8ff4a0c Mon Sep 17 00:00:00 2001 From: So Hyeon Date: Sat, 16 Nov 2024 13:42:34 +0900 Subject: [PATCH 07/12] Feat/pronounce (#8) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: 겹받침 * feat: before merge * feat: score endpoint --- crud/pronounce.py | 9 ++++----- main.py | 45 +++++++++++++++++++++++++++++++++++++++------ 2 files changed, 43 insertions(+), 11 deletions(-) diff --git a/crud/pronounce.py b/crud/pronounce.py index 2df5916..d7dfd97 100644 --- a/crud/pronounce.py +++ b/crud/pronounce.py @@ -3,6 +3,8 @@ import crud.difficulty pecab = PeCab() +# 음절의 끝소리 규칙 + def analysis_pronounce_crud(text): dec = crud.difficulty.decomposition(text) return { @@ -51,7 +53,6 @@ def analysis_yueumhwa(text, dec): if len(r)!=3: continue if i+1>=len(dec): continue - if r[2]=='ㄹ' and dec[i+1][0]=='ㄴ': yueumhwa.append(text[i:i+2]) elif r[2]=='ㄴ' and dec[i+1][0]=='ㄹ': @@ -74,7 +75,7 @@ def analysis_yeoneumhwa(text, dec): fdec = [col for col in fdec[-1] if col.strip()] if len(fdec)!=3: continue if fdec[2]=='ㅇ': continue - yeoneumhwa.append(forward+word) + yeoneumhwa.append(forward[-1]+word[0]) # 받침 뒤에 ㅏ, ㅓ, ㅗ, ㅜ, ㅟ로 시작하는 실질 형태소가 오는 경우 return yeoneumhwa @@ -104,7 +105,7 @@ def anaylsis_gyeonumhwa(text, dec): # 용언의 어간 받침 ㄴ, ㅁ 뒤 ㄱ, ㄷ, ㅅ, ㅈ # VV(동사)[2] for i, (word, tag) in enumerate(pos): - + print(word, tag) if tag == 'VV': wdec = crud.difficulty.decomposition(word) if wdec[-1][2] not in ['ㄴ','ㅁ']: continue @@ -119,7 +120,6 @@ def anaylsis_gyeonumhwa(text, dec): if 'ETM' in tag: wdec = crud.difficulty.decomposition(word) if wdec[-1][0]!='ㅇ' or wdec[-1][2] != 'ㄹ': continue - sdec = crud.difficulty.decomposition(pos[i+1][0]) if sdec[0][0] not in n1list: continue @@ -142,7 +142,6 @@ def doubleb_analysis(text, dec): if r[2] in doubleblist: doubleb.append(text[i]) - return doubleb def geosensori_analysis(text, dec): diff --git a/main.py b/main.py index 63d9974..27ebb27 100644 --- a/main.py +++ b/main.py @@ -1,4 +1,4 @@ -from fastapi import FastAPI, HTTPException +from fastapi import FastAPI, HTTPException, Body from pydantic import BaseModel, Field from typing import Dict import os @@ -30,7 +30,17 @@ class ClaudeRequest(BaseModel): @app.post("/phonological_rules") -async def analysis_pronounce(text: Dict[int, str]): +async def analysis_pronounce(text: Dict[int, str] = Body( + example= + { + "1": "맏이가 동생을 돌보았다", + "2": "굳이 그렇게까지 할 필요는 없어", + "3": "해돋이를 보러 산에 올랐다", + "4": "옷이 낡아서 새로 샀다", + "5": "같이 영화 보러 갈래?" + } + +)): analysis = {} for n, t in text.items(): if not t: @@ -71,9 +81,10 @@ async def generate_claude(request: ClaudeRequest): except Exception as e: raise HTTPException(status_code=500, detail=str(e)) - +class DifficultyRequest(BaseModel): + text: str = Field("맏이가 동생을 돌보았다") @app.post("/difficulty") -async def calc_difficulty(s: str): +async def calc_difficulty(text: DifficultyRequest): b_grade={ 'ㄱ':2, 'ㄴ':2, 'ㄹ':2, 'ㅁ':2, 'ㅇ':2, 'ㄷ':3, 'ㅂ':3, 'ㅅ':3, 'ㅈ':3, 'ㅎ':3, 'ㅆ':3, @@ -92,12 +103,33 @@ async def calc_difficulty(s: str): 'ㅒ':7, 'ㅠ':7, } + s = text.text b_list, m_list = difficulty_dec(s) - print(b_list, m_list) b_grade_sum = sum(b_grade.get(b) for b in b_list) m_grade_sum = sum(m_grade.get(m) for m in m_list) return b_grade_sum + m_grade_sum +class ScoreRequest(BaseModel): + workbook: dict[int, str] = Field(description="문제집") + answer: str = Field(description="답안 S3 주소") + + +@app.post("/score") +async def score(score: ScoreRequest = Body( + example={ + "workbook": + { + "1": "맏이가 동생을 돌보았다", + "2": "굳이 그렇게까지 할 필요는 없어", + "3": "해돋이를 보러 산에 올랐다", + "4": "옷이 낡아서 새로 샀다", + "5": "같이 영화 보러 갈래?" + }, + "answer": "https://bada-static-bucket.s3.ap-northeast-2.amazonaws.com/1085767.png" + } +)): + return score + @app.get("/") async def root(): @@ -110,12 +142,13 @@ async def root(): # uvicorn main:app --reload def difficulty_dec(s: str): - res = crud.difficultydecomposition(s) + res = crud.difficulty.decomposition(s) b_list = [] m_list = [] strip_list = [[col for col in row if col.strip()] for row in res] for i in strip_list: + if len(i)==0: continue m_list.append(i[1]) if len(i) == 3: b_list.append(i[2]) From 5cc1685dedf2190902dc7b63c60ba73f710b50c7 Mon Sep 17 00:00:00 2001 From: ssoxong Date: Sun, 17 Nov 2024 18:12:43 +0900 Subject: [PATCH 08/12] feat: score format --- crud/pronounce.py | 3 +- crud/score.py | 114 ++++++++++++++++++++++++++++++++++++++++++++++ main.py | 36 ++++++++++----- 3 files changed, 140 insertions(+), 13 deletions(-) create mode 100644 crud/score.py diff --git a/crud/pronounce.py b/crud/pronounce.py index f4416e3..670b4d1 100644 --- a/crud/pronounce.py +++ b/crud/pronounce.py @@ -5,7 +5,7 @@ # 음절의 끝소리 규칙 -def analysis_pronounce_crud(text): +def pronounce_crud(text): dec = crud.difficulty.decomposition(text) return { "구개음화": analysis_gugaeumhwa(text, dec), @@ -106,7 +106,6 @@ def anaylsis_gyeonumhwa(text, dec): # 용언의 어간 받침 ㄴ, ㅁ 뒤 ㄱ, ㄷ, ㅅ, ㅈ # VV(동사)[2] for i, (word, tag) in enumerate(pos): - print(word, tag) if tag == 'VV': wdec = crud.difficulty.decomposition(word) if wdec[-1][2] not in ['ㄴ','ㅁ']: continue diff --git a/crud/score.py b/crud/score.py new file mode 100644 index 0000000..6bb0f21 --- /dev/null +++ b/crud/score.py @@ -0,0 +1,114 @@ +from crud import pronounce +from main import ScoreAnalysis, ScoreResponse +# from pydantic import List + +from main import ScoreRequest +def score_crud(score: ScoreRequest): + workbook = score.workbook + answer = score.answer + atext = ocr(answer) + ascore = simillarity(answer) + + # {1: [('맏이가', '마지가')], 2: [('굳이', '구지'), ('그렇게까지', '그러케까 지')], 4: [('새로', '세로')]} + wrong_list = extract_wa(workbook, atext) + wk = list(workbook) + print(wrong_list) + + response = {} + + for i in range(wk[0], wk[-1]+1): + sa=[] + if i not in wrong_list: + sr = ScoreResponse(score=ascore[i], analysis=[]) + response[i] = sr + continue + + for w in wrong_list[i]: + print(w) + q = w[0] + a = w[1] + saq = q + saa = a + sap = analysis_wrong(q, a) + + sa.append(ScoreAnalysis(question=saq, answer=saa, pronounce=sap)) + print(sa) + + sr = ScoreResponse(score=ascore[i], analysis=sa) + # print(sr) + + response[i] = sr + + return response + + """ + 1:{ + "score": 70 + "analysis": [ + { + "question": "맏이가", + "answer": "마지가", + "pronounce": ["구개음화", "연음화"] + }, + { + "question": "맏이가", + "answer": "마지가", + "pronounce": ["구개음화", "연음화"] + } + ] + } + 2:{ + "score": 80 + "analysis": [ + { + "question": "맏이가", + "answer": "마지가", + "pronounce": ["구개음화", "연음화"] + }, + { + "question": "맏이가", + "answer": "마지가", + "pronounce": ["구개음화", "연음화"] + } + ] + }, + 3: {"score": 100, "analysis": []} + """ + +def ocr(a): + return{ + 1: "마지가 동생을 돌보았다", + 2: "구지 그러케까지 할 필요는 없어", + 3: "해돋이를 보러 산에 올랐다", + 4: "옷이 낡아서 세로 샀다", + 5: "같이 영화 보러 갈래?", + 6: "밥머고 영화 볼 싸람?" + } + +def simillarity(a): + return {1: 90, 2:80, 3:100, 4:80, 5:100, 6:20} + +def extract_wa(workbook, atext): + wrong = {} + wk = list(workbook) + for i in range(wk[0], wk[-1]+1): + if i not in atext.keys(): continue + wlist = workbook[i].split() + alist = atext[i].split() + + for j in range(max(len(wlist), len(alist))): + if wlist[j]!=alist[j]: + if i not in wrong: wrong[i]=[] + wrong[i].append((wlist[j], alist[j])) + return wrong + +def analysis_wrong(q, a): + analysis = pronounce.pronounce_crud(q) + plist = [] + for a in analysis: + if not len(analysis[a]): continue + plist.append(a) + + if not len(plist): return ['음운규칙 없음'] + return plist + diff --git a/main.py b/main.py index 2c4d30d..85a42a5 100644 --- a/main.py +++ b/main.py @@ -1,14 +1,10 @@ from fastapi import FastAPI, HTTPException, Body from pydantic import BaseModel, Field -from typing import Dict -from typing import Dict +from typing import Dict, List import os from dotenv import load_dotenv import json -import crud -import crud.difficulty -import crud.pronounce - +from crud import difficulty, pronounce, score app = FastAPI() load_dotenv() @@ -47,7 +43,7 @@ async def analysis_pronounce(text: Dict[int, str] = Body( for n, t in text.items(): if not t: raise HTTPException(status_code=400, detail="text에 빈 문자열이 포함되어 있습니다.") - analysis[n]=crud.pronounce.analysis_pronounce_crud(t) + analysis[n]=pronounce.pronounce_crud(t) return analysis @app.post("/claude") @@ -115,9 +111,18 @@ class ScoreRequest(BaseModel): workbook: dict[int, str] = Field(description="문제집") answer: str = Field(description="답안 S3 주소") +class ScoreAnalysis(BaseModel): + question: str + answer: str + pronounce: List[str] + +class ScoreResponse(BaseModel): + score: int + analysis: List[ScoreAnalysis] + @app.post("/score") -async def score(score: ScoreRequest = Body( +async def score_endpoint(s: ScoreRequest = Body( example={ "workbook": { @@ -125,12 +130,21 @@ async def score(score: ScoreRequest = Body( "2": "굳이 그렇게까지 할 필요는 없어", "3": "해돋이를 보러 산에 올랐다", "4": "옷이 낡아서 새로 샀다", - "5": "같이 영화 보러 갈래?" + "5": "같이 영화 보러 갈래?", + "6": "밥먹고 영화 할 사람?" }, "answer": "https://bada-static-bucket.s3.ap-northeast-2.amazonaws.com/1085767.png" } )): - return score + response = score.score_crud(s) + + # return { + # "1": 80, + # "2": 90, + # "3": 47 + # } + + return response @app.get("/") @@ -144,7 +158,7 @@ async def root(): # uvicorn main:app --reload def difficulty_dec(s: str): - res = crud.difficulty.decomposition(s) + res = difficulty.decomposition(s) b_list = [] m_list = [] strip_list = [[col for col in row if col.strip()] for row in res] From b0eb4d2f556bf6d98f666b92a993befe9b56cea0 Mon Sep 17 00:00:00 2001 From: ssoxong Date: Sun, 17 Nov 2024 18:30:50 +0900 Subject: [PATCH 09/12] =?UTF-8?q?feat:=20=EC=88=9C=ED=99=98=EC=B0=B8?= =?UTF-8?q?=EC=A1=B0=EC=98=A4=EB=A5=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- crud/score.py | 12 ++++++++++-- main.py | 11 +++-------- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/crud/score.py b/crud/score.py index 6bb0f21..1f267c2 100644 --- a/crud/score.py +++ b/crud/score.py @@ -1,6 +1,14 @@ from crud import pronounce -from main import ScoreAnalysis, ScoreResponse -# from pydantic import List +from pydantic import BaseModel +from typing import List +class ScoreAnalysis(BaseModel): + question: str + answer: str + pronounce: List[str] + +class ScoreResponse(BaseModel): + score: int + analysis: List[ScoreAnalysis]# from pydantic import List from main import ScoreRequest def score_crud(score: ScoreRequest): diff --git a/main.py b/main.py index 887d603..92f1a4e 100644 --- a/main.py +++ b/main.py @@ -1,6 +1,6 @@ from fastapi import FastAPI, HTTPException, Body from pydantic import BaseModel, Field -from typing import Dict, List +from typing import Dict import os from dotenv import load_dotenv import json @@ -79,8 +79,10 @@ async def generate_claude(request: ClaudeRequest): except Exception as e: raise HTTPException(status_code=500, detail=str(e)) + class DifficultyRequest(BaseModel): text: str = Field("맏이가 동생을 돌보았다") + @app.post("/difficulty") async def calc_difficulty(text: DifficultyRequest): b_grade={ @@ -111,14 +113,7 @@ class ScoreRequest(BaseModel): workbook: dict[int, str] = Field(description="문제집") answer: str = Field(description="답안 S3 주소") -class ScoreAnalysis(BaseModel): - question: str - answer: str - pronounce: List[str] -class ScoreResponse(BaseModel): - score: int - analysis: List[ScoreAnalysis] @app.post("/score") From 4cf45eb21ac3168a7cdc4de40fff67617d682364 Mon Sep 17 00:00:00 2001 From: ssoxong Date: Sun, 17 Nov 2024 18:39:35 +0900 Subject: [PATCH 10/12] feat: circual --- crud/score.py | 3 +-- main.py | 3 --- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/crud/score.py b/crud/score.py index 1f267c2..5da8852 100644 --- a/crud/score.py +++ b/crud/score.py @@ -10,8 +10,7 @@ class ScoreResponse(BaseModel): score: int analysis: List[ScoreAnalysis]# from pydantic import List -from main import ScoreRequest -def score_crud(score: ScoreRequest): +def score_crud(score): workbook = score.workbook answer = score.answer atext = ocr(answer) diff --git a/main.py b/main.py index 92f1a4e..3cf625f 100644 --- a/main.py +++ b/main.py @@ -113,9 +113,6 @@ class ScoreRequest(BaseModel): workbook: dict[int, str] = Field(description="문제집") answer: str = Field(description="답안 S3 주소") - - - @app.post("/score") async def score_endpoint(s: ScoreRequest = Body( example={ From df9eea07c1b11f4a139f2a6264596e601abddadc Mon Sep 17 00:00:00 2001 From: ssoxong Date: Wed, 20 Nov 2024 15:38:57 +0900 Subject: [PATCH 11/12] feat: difficulty --- crud/score.py | 22 ++++++++++++++++++++-- main.py | 6 +++--- 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/crud/score.py b/crud/score.py index 5da8852..20d1731 100644 --- a/crud/score.py +++ b/crud/score.py @@ -13,13 +13,31 @@ class ScoreResponse(BaseModel): def score_crud(score): workbook = score.workbook answer = score.answer + + """ + ocr request + 답안이 저장된 s3 주소 (string) + ocr response + {문제 번호(int): 답안(string), ..., 문제 번호: 답안} + """ atext = ocr(answer) - ascore = simillarity(answer) + + """ + simillarity request + workbook + {문제 번호(int): 문제(string), ..., 문제 번호: 문제} + answer + {문제 번호(int): 문제(string), ..., 문제 번호: 문제} + + simillarity response + {문제 번호(int): 점수(int), ..., 문제 번호(int): 점수(int)} + + """ + ascore = simillarity(workbook, answer) # {1: [('맏이가', '마지가')], 2: [('굳이', '구지'), ('그렇게까지', '그러케까 지')], 4: [('새로', '세로')]} wrong_list = extract_wa(workbook, atext) wk = list(workbook) - print(wrong_list) response = {} diff --git a/main.py b/main.py index 3cf625f..84a0af3 100644 --- a/main.py +++ b/main.py @@ -21,7 +21,7 @@ class PronounceRule(str, Enum): 기식음화 = "기식음화" class ClaudeRequest(BaseModel): - age: int = Field(default=11) + difficulty: int = Field(default=11) rule: PronounceRule count: int = Field(default=5) @@ -60,14 +60,14 @@ async def generate_claude(request: ClaudeRequest): max_tokens=1000, # 다양한 결과값을 얻기 위해 temperature 값 조절 temperature=0.5, - system="너는 음운 규칙별 받아쓰기 문제를 생성하는거야. 음운 규칙에는 구개음화, 연음화, 경음화, 유음화, 비음화, 음운규칙 없음, 겹받침 쓰기, 기식음화가 있어.\n내가 'n살 난이도로 [m]유형으로 k문제 만들어줘' 라고 하면 맞춰서 받아쓰기 문제를 만들어줘.\nn: 8~13 (초등학교 1학년~6학년)\nm: 구개음화, 연음화, 경음화, 유음화, 비음화, 음운규칙 없음, 겹받침 쓰기, 기식음화\nk: 1~15\n답변 형식:\n문제번호:문제 형태로 json형식으로 반환", + system="너는 음운 규칙별 받아쓰기 문제를 생성하는거야. 음운 규칙에는 구개음화, 연음화, 경음화, 유음화, 비음화, 음운규칙 없음, 겹받침 쓰기, 기식음화가 있어.\n내가 'n 난이도로 [m]유형으로 k문제 만들어줘' 라고 하면 맞춰서 받아쓰기 문제를 만들어줘.\nn: 1~5 (초등학교 기준)\nm: 구개음화, 연음화, 경음화, 유음화, 비음화, 음운규칙 없음, 겹받침 쓰기, 기식음화\nk: 1~15\n답변 형식:\n문제번호:문제 형태로 json형식으로 반환", messages=[ { "role": "user", "content": [ { "type": "text", - "text": f"{request.age}살 난이도로 [{request.rule}] 유형으로 {request.count}문제 만들어줘. (seed: {datetime.now().isoformat()})" + "text": f"{request.difficulty} 난이도로 [{request.rule}] 유형으로 {request.count}문제 만들어줘. (seed: {datetime.now().isoformat()})" } ] } From 01cd39b055454bad5e06e68a225892dc7ad74f3c Mon Sep 17 00:00:00 2001 From: So Hyeon Date: Wed, 20 Nov 2024 16:28:54 +0900 Subject: [PATCH 12/12] feat: scoring (#13) --- crud/difficulty.py | 2 ++ crud/score.py | 2 +- main.py | 22 ++++++++++++++++------ 3 files changed, 19 insertions(+), 7 deletions(-) diff --git a/crud/difficulty.py b/crud/difficulty.py index f195172..5a72fe5 100644 --- a/crud/difficulty.py +++ b/crud/difficulty.py @@ -1,4 +1,6 @@ +import re def decomposition(korean_word: str): + korean_word = re.sub(r'[!"#$%&\'()*+,-./:;<=>?@\[\]^_\`{|}~\\\\]','', korean_word) # 초성 리스트. 00 ~ 18 CHOSUNG_LIST = ['ㄱ', 'ㄲ', 'ㄴ', 'ㄷ', 'ㄸ', 'ㄹ', 'ㅁ', 'ㅂ', 'ㅃ', 'ㅅ', 'ㅆ', 'ㅇ', 'ㅈ', 'ㅉ', 'ㅊ', 'ㅋ', 'ㅌ', 'ㅍ', 'ㅎ'] # 중성 리스트. 00 ~ 20 diff --git a/crud/score.py b/crud/score.py index 20d1731..0b030b1 100644 --- a/crud/score.py +++ b/crud/score.py @@ -110,7 +110,7 @@ def ocr(a): 6: "밥머고 영화 볼 싸람?" } -def simillarity(a): +def simillarity(workbook, a): return {1: 90, 2:80, 3:100, 4:80, 5:100, 6:20} def extract_wa(workbook, atext): diff --git a/main.py b/main.py index 84a0af3..52b8fec 100644 --- a/main.py +++ b/main.py @@ -21,11 +21,9 @@ class PronounceRule(str, Enum): 기식음화 = "기식음화" class ClaudeRequest(BaseModel): - difficulty: int = Field(default=11) + difficulty: int = Field(default=3) rule: PronounceRule count: int = Field(default=5) - - @app.post("/phonological_rules") async def analysis_pronounce(text: Dict[int, str] = Body( @@ -60,7 +58,7 @@ async def generate_claude(request: ClaudeRequest): max_tokens=1000, # 다양한 결과값을 얻기 위해 temperature 값 조절 temperature=0.5, - system="너는 음운 규칙별 받아쓰기 문제를 생성하는거야. 음운 규칙에는 구개음화, 연음화, 경음화, 유음화, 비음화, 음운규칙 없음, 겹받침 쓰기, 기식음화가 있어.\n내가 'n 난이도로 [m]유형으로 k문제 만들어줘' 라고 하면 맞춰서 받아쓰기 문제를 만들어줘.\nn: 1~5 (초등학교 기준)\nm: 구개음화, 연음화, 경음화, 유음화, 비음화, 음운규칙 없음, 겹받침 쓰기, 기식음화\nk: 1~15\n답변 형식:\n문제번호:문제 형태로 json형식으로 반환", + system="너는 음운 규칙별 받아쓰기 문제를 생성하는거야. 음운 규칙에는 구개음화, 연음화, 경음화, 유음화, 비음화, 음운규칙 없음, 겹받침 쓰기, 기식음화가 있어.\n내가 'n 난이도로 [m]유형으로 k문제 만들어줘' 라고 하면 맞춰서 받아쓰기 문제를 만들어줘.\nn: 1~5 (초등학교 기준, 1: 단어, 2: 쉬운 단어가 있는 간단한 문장, 3: 쉬운 단어가 있는 짧은 문장, 4: 짧은 문장, 5: 문장)\nm: 구개음화, 연음화, 경음화, 유음화, 비음화, 음운규칙 없음, 겹받침 쓰기, 기식음화\n답변 형식:\n문제번호:문제 형태로 json형식으로 반환", messages=[ { "role": "user", @@ -103,11 +101,23 @@ async def calc_difficulty(text: DifficultyRequest): 'ㅒ':7, 'ㅠ':7, } + #pronounce 추출해서 해당하는 부분만 스코어링 s = text.text - b_list, m_list = difficulty_dec(s) + analysis = pronounce.pronounce_crud(s) + + spro = '' + + for k, v in analysis.items(): + if not v: continue + spro+=''.join(v) + + b_list, m_list = difficulty_dec(spro) b_grade_sum = sum(b_grade.get(b) for b in b_list) m_grade_sum = sum(m_grade.get(m) for m in m_list) - return b_grade_sum + m_grade_sum + total = (b_grade_sum+m_grade_sum)//5 + if total>5: total=5 + if total<1: total=1 + return total class ScoreRequest(BaseModel): workbook: dict[int, str] = Field(description="문제집")