From 04dc41341464eb9a266f440c8d9dc9b2e15c12cc Mon Sep 17 00:00:00 2001 From: dMario24 Date: Sun, 2 Feb 2025 16:50:56 +0900 Subject: [PATCH 1/6] Built-in-Morph --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 7156ca9..14a0981 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "fff", - "version": "252.2.2", + "version": "253.1.1", "private": true, "scripts": { "dev": "next dev", From 377a9d518c138d9ec499f6e35a691c0d4d67d05f Mon Sep 17 00:00:00 2001 From: dMario24 Date: Sun, 2 Feb 2025 17:15:11 +0900 Subject: [PATCH 2/6] basic python api --- .gitignore | 1 + README.md | 12 +++- api/py/__pycache__/index.cpython-310.pyc | Bin 0 -> 589 bytes api/py/index.py | 13 ++++ next.config.mjs | 26 ++++++++ package-lock.json | 78 +++++++++++++++++++++-- package.json | 8 ++- requirements.txt | 4 ++ 8 files changed, 132 insertions(+), 10 deletions(-) create mode 100644 api/py/__pycache__/index.cpython-310.pyc create mode 100644 api/py/index.py create mode 100644 requirements.txt diff --git a/.gitignore b/.gitignore index 8049b2a..a85b854 100644 --- a/.gitignore +++ b/.gitignore @@ -40,3 +40,4 @@ next-env.d.ts public/img/uploads postgres_data/ postgres_ssl/certs/certstrap +venv/ diff --git a/README.md b/README.md index 5a124e9..c09dfe5 100644 --- a/README.md +++ b/README.md @@ -84,8 +84,6 @@ - Alternatively, you can use the local DBMS using the Dockerizing part below. The setting file DATABASE_CLIENT needs to be changed. - - ### 🌱 Env - Rename env.dummy to .env.local. Make sure the file is not pushed to the public GitHub repository. - To avoid using analytics and statistics by connecting to Google Firebase, delete analytics.ts. @@ -99,6 +97,16 @@ $ npm install $ npm run dev ``` +### Dev Python API +```bash +$ pyenv global +3.10.12 +# $ python -m venv venv +$ source venv/bin/activate +$ pip install -r requirements.txt +$ uvicorn api.index:app --reload +``` + ### Test ```bash $ npx jest -t "should correctly join URL parts into a complete URL" diff --git a/api/py/__pycache__/index.cpython-310.pyc b/api/py/__pycache__/index.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c83f44ed5acf84dedbb499e1afb4dd5efbe4393e GIT binary patch literal 589 zcmYjP!H&}~5Vf5&aocpYTJZsUB$r0O6(JC41(y{PHy?;h?506>Y}u)_?Q!ACH!K|a zrCd3|CvajWbk!YcM(_DeJkNIAYPBE`e;(hpx0H}yNFGKCEikKN@ znP4^%$;1 z8)lG_j`@|0!>jl2N;YyO2R(FFk0~M$(>Gl+Tmx9?n<2<%sC&2T { + return [ + { + source: "/api/py/:path*", + destination: + process.env.NODE_ENV === "development" + ? "http://127.0.0.1:8000/api/py/:path*" + : "/api/", + }, + { + source: "/docs", + destination: + process.env.NODE_ENV === "development" + ? "http://127.0.0.1:8000/api/py/docs" + : "/api/py/docs", + }, + { + source: "/openapi.json", + destination: + process.env.NODE_ENV === "development" + ? "http://127.0.0.1:8000/api/py/openapi.json" + : "/api/py/openapi.json", + }, + ]; + }, }; export default nextConfig; diff --git a/package-lock.json b/package-lock.json index 5a2efda..b8649e0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "fff", - "version": "252.2.2", + "version": "253.1.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "fff", - "version": "252.2.2", + "version": "253.1.1", "dependencies": { "@fingerprintjs/fingerprintjs": "^4.5.1", "@heroicons/react": "^2.2.0", @@ -31,6 +31,7 @@ "bcrypt": "^5.1.1", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", + "concurrently": "^9.0.1", "file-saver": "^2.0.5", "firebase": "^11.0.2", "jszip": "^3.10.1", @@ -5281,7 +5282,6 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, "license": "MIT", "dependencies": { "ansi-styles": "^4.1.0", @@ -5561,6 +5561,46 @@ "typedarray": "^0.0.6" } }, + "node_modules/concurrently": { + "version": "9.1.2", + "resolved": "https://registry.npmjs.org/concurrently/-/concurrently-9.1.2.tgz", + "integrity": "sha512-H9MWcoPsYddwbOGM6difjVwVZHl63nwMEwDJG/L7VGtuaJhb12h2caPG2tVPWs7emuYix252iGfqOyrz1GczTQ==", + "license": "MIT", + "dependencies": { + "chalk": "^4.1.2", + "lodash": "^4.17.21", + "rxjs": "^7.8.1", + "shell-quote": "^1.8.1", + "supports-color": "^8.1.1", + "tree-kill": "^1.2.2", + "yargs": "^17.7.2" + }, + "bin": { + "conc": "dist/bin/concurrently.js", + "concurrently": "dist/bin/concurrently.js" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/open-cli-tools/concurrently?sponsor=1" + } + }, + "node_modules/concurrently/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, "node_modules/console-control-strings": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", @@ -7625,7 +7665,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -11834,6 +11873,15 @@ "queue-microtask": "^1.2.2" } }, + "node_modules/rxjs": { + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", + "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.1.0" + } + }, "node_modules/safe-array-concat": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.3.tgz", @@ -12077,6 +12125,18 @@ "node": ">=8" } }, + "node_modules/shell-quote": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.2.tgz", + "integrity": "sha512-AzqKpGKjrj7EM6rKVQEPpB288oCfnrEIuyoT9cyF4nmGa7V8Zk6f7RRqYisX8X9m+Q7bd632aZW4ky7EhbQztA==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/side-channel": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", @@ -12602,7 +12662,6 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, "license": "MIT", "dependencies": { "has-flag": "^4.0.0" @@ -12865,6 +12924,15 @@ "node": ">=12" } }, + "node_modules/tree-kill": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", + "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", + "license": "MIT", + "bin": { + "tree-kill": "cli.js" + } + }, "node_modules/ts-api-utils": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.0.1.tgz", diff --git a/package.json b/package.json index 14a0981..017bc76 100644 --- a/package.json +++ b/package.json @@ -3,12 +3,13 @@ "version": "253.1.1", "private": true, "scripts": { - "dev": "next dev", + "dev": "concurrently \"next dev\" \"npm run fastapi-dev\"", "lh": "next dev -H 0.0.0.0 -p 3000", "build": "next build", "start": "next start", "lint": "next lint", - "test": "jest" + "test": "jest", + "fastapi-dev": "pip install -r requirements.txt && python -m uvicorn api.py.index:app --reload" }, "dependencies": { "@fingerprintjs/fingerprintjs": "^4.5.1", @@ -56,7 +57,8 @@ "tailwindcss-animate": "^1.0.7", "use-debounce": "^10.0.4", "vaul": "^1.1.2", - "zod": "^3.24.1" + "zod": "^3.24.1", + "concurrently": "^9.0.1" }, "devDependencies": { "@testing-library/jest-dom": "^6.6.3", diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..92dee15 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,4 @@ +fastapi==0.115.0 +uvicorn[standard]==0.30.6 +korean-age-calculator==1.0.0 +flag-morph==1.0.1 From 65fcdc0e8ff6d51b2f9676497785c33244b76d61 Mon Sep 17 00:00:00 2001 From: dMario24 Date: Sun, 2 Feb 2025 17:28:41 +0900 Subject: [PATCH 3/6] ignore pyc --- .gitignore | 3 +++ api/py/__pycache__/index.cpython-310.pyc | Bin 589 -> 0 bytes 2 files changed, 3 insertions(+) delete mode 100644 api/py/__pycache__/index.cpython-310.pyc diff --git a/.gitignore b/.gitignore index a85b854..6aefd35 100644 --- a/.gitignore +++ b/.gitignore @@ -41,3 +41,6 @@ public/img/uploads postgres_data/ postgres_ssl/certs/certstrap venv/ +__pycache__/ +*.pyc +*.pyo diff --git a/api/py/__pycache__/index.cpython-310.pyc b/api/py/__pycache__/index.cpython-310.pyc deleted file mode 100644 index c83f44ed5acf84dedbb499e1afb4dd5efbe4393e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 589 zcmYjP!H&}~5Vf5&aocpYTJZsUB$r0O6(JC41(y{PHy?;h?506>Y}u)_?Q!ACH!K|a zrCd3|CvajWbk!YcM(_DeJkNIAYPBE`e;(hpx0H}yNFGKCEikKN@ znP4^%$;1 z8)lG_j`@|0!>jl2N;YyO2R(FFk0~M$(>Gl+Tmx9?n<2<%sC&2T Date: Sun, 2 Feb 2025 17:36:41 +0900 Subject: [PATCH 4/6] movie python api --- api/{py => }/index.py | 0 package.json | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename api/{py => }/index.py (100%) diff --git a/api/py/index.py b/api/index.py similarity index 100% rename from api/py/index.py rename to api/index.py diff --git a/package.json b/package.json index 017bc76..d1fb667 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,7 @@ "start": "next start", "lint": "next lint", "test": "jest", - "fastapi-dev": "pip install -r requirements.txt && python -m uvicorn api.py.index:app --reload" + "fastapi-dev": "pip install -r requirements.txt && python -m uvicorn api.index:app --reload" }, "dependencies": { "@fingerprintjs/fingerprintjs": "^4.5.1", From 29c87538f22ea67a1d693251eec1602c4181e39e Mon Sep 17 00:00:00 2001 From: dMario24 Date: Sun, 2 Feb 2025 17:43:57 +0900 Subject: [PATCH 5/6] =?UTF-8?q?=ED=98=95=ED=83=9C=EC=86=8C=20=EB=B6=84?= =?UTF-8?q?=EC=84=9D=20API=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ``` curl -X 'GET' \ 'http://localhost:3000/api/py/n/%EC%95%84%EB%B2%84%EC%A7%80%EA%B0%80%EB%B0%A9%EC%97%90%EB%93%A4%EC%96%B4%EA%B0%80%EC%8B%A0%EB%8B%A4' \ -H 'accept: application/json' ``` --- api/index.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/api/index.py b/api/index.py index ebbf215..5296817 100644 --- a/api/index.py +++ b/api/index.py @@ -1,7 +1,5 @@ from fastapi import FastAPI -from datetime import datetime, date from typing import Dict -import random from flag_morph.extract import extract_nouns ### Create FastAPI instance with custom docs and openapi url @@ -11,3 +9,8 @@ def hello_fast_api(): return {"message": "HI PYTHON FastAPI"} +@app.get("/api/py/n/{sentence}") +def get_nouns(sentence: str) -> Dict[str, list[str]]: + r = extract_nouns(sentence) + return {"nouns": r} + From 2de21135c322956b79e7c4b5fa130f63927ba295 Mon Sep 17 00:00:00 2001 From: dMario24 Date: Sun, 2 Feb 2025 18:37:38 +0900 Subject: [PATCH 6/6] kiwi pre model load --- README.md | 10 +++++++--- api/index.py | 24 ++++++++++++++++++++++++ 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index c09dfe5..731725e 100644 --- a/README.md +++ b/README.md @@ -99,10 +99,14 @@ $ npm run dev ### Dev Python API ```bash -$ pyenv global -3.10.12 -# $ python -m venv venv +$ pyenv versions + system + 3.10.12 +* 3.12.8 (set by /home/ppabam/.pyenv/version) +$ python -m venv venv $ source venv/bin/activate +$ python -V +Python 3.10.12 $ pip install -r requirements.txt $ uvicorn api.index:app --reload ``` diff --git a/api/index.py b/api/index.py index 5296817..acab6ff 100644 --- a/api/index.py +++ b/api/index.py @@ -1,6 +1,7 @@ from fastapi import FastAPI from typing import Dict from flag_morph.extract import extract_nouns +from kiwipiepy import Kiwi ### Create FastAPI instance with custom docs and openapi url app = FastAPI(docs_url="/api/py/docs", openapi_url="/api/py/openapi.json") @@ -14,3 +15,26 @@ def get_nouns(sentence: str) -> Dict[str, list[str]]: r = extract_nouns(sentence) return {"nouns": r} +kiwi = Kiwi() +kiwi.analyze("테스트") # 강제로 모델 로드 + +def extract_nouns(sentence: str, is_print: bool = False) -> list: + """ + 주어진 문장에서 명사(NNG, NNP, NP)만 추출하여 리스트로 반환합니다. + """ + result = kiwi.analyze(sentence) + tokens = result[0][0] + + target_pos = {"NNG", "NNP", "NP"} + extracted = [word for word, pos, _, _ in tokens if pos in target_pos] + + if is_print: + print(f"Extracted nouns: {extracted}") + + return extracted + +@app.get("/api/py/kiwi/{sentence}") +def run_kiwi(sentence: str) -> Dict[str, list[str]]: + r = extract_nouns(sentence) + return {"nouns": r} +