Code refactoring
app.data.rdbms.location.py
generate_location_response
| ํญ๋ชฉ | ๊ฐ์ ๋ด์ฉ | ์ด์ |
|---|
| ๋ชจ๋ํ | db_model, schema_model ์ถ์ถ์ .get()์ผ๋ก | ํค ๋ฏธ์ค ๋ฐ์ ์ ์๋ฌ ๋ฐฉ์ง ๋ฐ ๋ก๊น
|
| ๋ก๊น
์์ค ์กฐ์ | logger.exception ์ฌ์ฉ | stack trace ํฌํจํ์ฌ ๊ธฐ๋ก, ๋๋ฒ๊น
์ฉ์ด |
| ๋ฌธ์์ด ํฌ๋งท | f-string ํต์ผ, ์ค๋ณต ์ ๊ฑฐ | ์ง๊ด์ ์ด๋ฉฐ ์ ์ง๋ณด์์ ์ ๋ฆฌ |
| ์์ธ ๋ฉ์์ง | ๊ณ ์ ๋ str โ ๋์ ๋ฉ์์ง | ์ด๋ค location์์ ์คํจํ๋์ง ๋ช
ํํ |
| ์ถ๋ ฅ ๊ตฌ์กฐ | actionValue dict ๋ณํฉ ๋ฐฉ์ ๊ฐ์ | ์๋ฏธ ๋ช
ํํ ๋ฐ ๊ตฌ์กฐ ์ผ๊ด์ฑ ์ ์ง |
get_closet_place
| ํญ๋ชฉ | ๊ฐ์ ๋ด์ฉ | ์ด์ |
|---|
| ๋ก๊น
ํฌ๋งท | [get_closest_place] prefix ์ฌ์ฉ | ๋ก๊ทธ ์ถ์ ์ฑ๊ณผ ํํฐ๋ง ํฅ์ |
| ์ฟผ๋ฆฌ ๊ฒฐ๊ณผ ์ฒ๋ฆฌ | .first() ์ฌ์ฉ | .all()[0]๋ณด๋ค ์์ ํ๊ณ ๋ช
ํ |
| ์์ธ ๋ฉ์์ง | .exception() ์ฌ์ฉ | stack trace ํฌํจํ์ฌ ๋๋ฒ๊น
์ฉ์ด |
| ๋ชจ๋ธ ๊ณตํต ํ๋ ์ถ์ถ | getattr() ์ฌ์ฉ | ํ๋ ์ ๋ฌด ์ฒดํฌ + ๊ฐ๋
์ฑ ํ๋ณด |
| ์๋ฌ ๊ฐ๋
์ฑ | DB ์กฐํ ์คํจ ์ ValueError | ์คํจ ์์ธ ๋ช
ํํ ๊ตฌ๋ถ |
app.data.vectorDB.py
vector_store_initialize
| ํญ๋ชฉ | ๊ฐ์ ๋ด์ฉ | ์ด์ |
|---|
ํ๊ฒฝ ๋ณ์ ๊ฒ์ฆ ํจ์ validate_env() ์ถ๊ฐ | None ์ฒดํฌ๋ฅผ ๋ช
์์ ์ผ๋ก ์ํ | ๋ฐํ์ ์ ๋ถ๋ช
ํํ KeyError ์๋ฐฉ |
| ๋ถ๊ธฐ๋ฌธ if-elif ๊ตฌ์กฐ๋ก ๋ณ๊ฒฝ | ๋์
๋๋ฆฌ config ์ ๊ฑฐ | ์ค๋ณต ์ ๊ฑฐ๋ณด๋ค ๋ก์ง ํ๋ฆ๊ณผ ์์ธ ์ฒ๋ฆฌ ์ค์ |
ํ๊ฒฝ ๋ณ์ ๋ช
์ ๋ก๋ฉ (load_dotenv) | .env ์ฌ์ฉ ์ ๋ช
ํํ ๋ก๋ | ํ
์คํธ ํ๊ฒฝ์์ ์๋๋ ๋ก๋ฉ ๋ณด์ฅ |
| ์๋ฌ ๋ฉ์์ง ๊ฐ์ | ์ด๋ค ๊ฐ์ด ๋๋ฝ๋์๋์ง ๋ช
์ | ๋ฌธ์ ์ถ์ ์ฉ์ด |
vector_search
| ํญ๋ชฉ | ๊ฐ์ ๋ด์ฉ | ์ด์ |
|---|
| ์ธ์ด ๊ฐ์ง ํจ์ ๋ถ๋ฆฌ | process_query โ _translate_to_korean_if_needed | ๋จ์ผ ์ฑ
์ ์์น ์ ์ฉ, ํ
์คํธ ๊ฐ๋ฅ |
| ๋ฌธ์์ด ์ฒ๋ฆฌ ์์ธ ๋ช
ํํ | strip() ๊ฒ์ฌ โ ValueError | ์กฐ๊ธฐ ์คํจ(Fail Fast) ์์น |
| ํ์
ํํธ ๋ช
ํํ | List[Document] ๋ฑ ์ ์ฉ | ์๋์์ฑ + ๋๋ฒ๊น
ํฅ์ |
| try-catch ๋ฒ์ ์ถ์ | ๋ฒ์ญ ๋ก์ง, ์ ์ฒด ๋ก์ง์ ๊ฐ๋ณ ์์ธ ์ฒ๋ฆฌ | ๋ฌธ์ ์์ธ ํ์
์ฉ์ด |
| ์ถ๋ ฅ ํฌ๋งท ๊ฐ์ | ๋ฆฌ์คํธ ์ปดํ๋ฆฌํจ์
๊ธฐ๋ฐ join() | ๊ฐ๋
์ฑ + ์ฑ๋ฅ ๋ชจ๋ ๊ฐ์ |
| ๋ถํ์ ์ฃผ์/print ์ ๊ฑฐ | ์ค์ ์๋น์ค ์ฝ๋์์๋ ์ถ๋ ฅ ์ ๊ฑฐ | ์ฝ์ ๋
ธ์ด์ฆ ๋ฐฉ์ง |
vector_insert
| ํญ๋ชฉ | ๊ฐ์ ๋ด์ฉ | ์ด์ |
|---|
| ๊ฒฝ๋ก ์ฒ๋ฆฌ | os.path.join() ์ฌ์ฉ | OS ๊ฐ ํธํ์ฑ ํ๋ณด (Windows/Linux/Mac) |
| ๋น ํ์ผ ์ฒ๋ฆฌ | strip() ์ฒดํฌ๋ก ๊ฑด๋๋ | ๋ถํ์ํ ์ฝ์
๋ฐฉ์ง |
| ํ์ผ ์กด์ฌ ํ์ธ | if not txt_files ์ฒดํฌ | ๋ถํ์ํ ์ด๊ธฐํ ๋ฐฉ์ง |
| ๊ณตํต Splitter ์ฌ์ฌ์ฉ | for ๋ฃจํ ๋ฐ์ ์ ์ธ | ์ฑ๋ฅ ์ต์ ํ, ๋ฉ๋ชจ๋ฆฌ ๋ญ๋น ๋ฐฉ์ง |
| ํ์ผ ๋ฉํ๋ฐ์ดํฐ ์๋ ์ถ๊ฐ | "source": filename | ์ถ์ ์ฑ๊ณผ ๊ด๋ฆฌ ํธ์์ฑ |
| ์๋ฌ ํธ๋ค๋ง | ๊ฐ๋ณ ํ์ผ try-catch | ์ ์ฒด ์ค๋จ ์์ด ์คํจ ํ์ผ๋ง skip |
app.langgraph_chatbot.graph.chatbot_graph.py
| ํญ๋ชฉ | ๊ฐ์ ์ | ๊ฐ์ ํ | ์ด์ |
|---|
| ๋
ธ๋ ์ ์ | .add_node() ์ฐ์ ํธ์ถ | NODE_DEFINITIONS ๋์
๋๋ฆฌ | ๋
ธ๋ ์ถ๊ฐ๊ฐ ๋ง์์ ธ๋ ์ ์ง๋ณด์ ์ฌ์ |
| ์ฃ์ง ์ ์ | .add_edge() ์ฐ์ ํธ์ถ | EDGE_DEFINITIONS ๋ฆฌ์คํธ | ์ถํ ๊ตฌ์กฐ์ ์๊ฐํ๋ ์ถ์ ์ ์ ๋ฆฌ |
| ์กฐ๊ฑด๋ถ ์ฃ์ง | ์ง์ .add_conditional_edges() ํธ์ถ | CONDITIONAL_EDGES ๋งคํ | ๋ถ๊ธฐ ์กฐ๊ฑด์ด ๋ง์ ๋ ์ผ๊ด์ฑ ์ ์ง |
| ๋ก๊น
๊ตฌ์กฐ | app.logger ์ฌ์ฉ | ํ์ค Python logger๋ก ๊ต์ฒด | ํ
์คํธ ๋ฐ ๋
๋ฆฝ ์คํ ์ ์ ์ฐ์ฑ ํ๋ณด |
| ์ฝ๋ ์ผ๊ด์ฑ | ํจ์/๊ฐ์ฒด ์ง์ ์ฐ๊ฒฐ | ๋ชจ๋ ๊ตฌ์ฑ ์์๋ฅผ ์ ์ธ์ ์ผ๋ก ์ ์ | ๊ธฐ๋ฅ/๋ก์ง๊ณผ ๊ตฌ์ฑ์ ๋ถ๋ฆฌํ์ฌ ๋ชจ๋ํ ๊ฐ๋ฅ |
app.langgraph_chatbot.chat_engine.py
| ํญ๋ชฉ | ๊ฐ์ ๋ด์ฉ | ์ด์ |
|---|
| ์ค๋ณต ์ ๊ฑฐ | _build_initial_state(), _execute_graph() | ์ด๊ธฐ ์ํ ๋ก์ง ๊ณตํตํ, ์ฝ๋ ๊ฐ๊ฒฐํ |
| ์์ธ ๋ฉ์์ง ๋ช
ํํ | ๋ฉ์๋๋ณ prefix ([respond_all], [message_stream] ๋ฑ) | ์๋ฌ ๋ก๊น
ํํฐ๋ง/๋๋ฒ๊น
ํฅ์ |
| ์ต์
๋ ๋ฐํ ํ์
| Optional[List[ResponseButtonModel]] | ํ์
์์ ์ฑ๊ณผ ๋ช
ํํ ์๋ฏธ ์ ๋ฌ |
| try-except ๋ถ๋ฆฌ | ์ธ๋ถ ํธ์ถ๊ณผ ๋ด๋ถ ์ํ ๊ตฌ๋ถ | ์คํจ ์์ธ ์ถ์ ์ฉ์ด |
| Kakao ๋์ ๋ถ๋ฆฌ | UserInfoModel ์์ ์์ฑ ์์น ๋ณ๊ฒฝ | ์ฝ๋ ์ผ๊ด์ฑ๊ณผ ์ฌ์ฌ์ฉ์ฑ ํฅ์ |
app.langgraph_chatbot.utils.chatbot_classify.py
| ํญ๋ชฉ | ๊ฐ์ ๋ด์ฉ | ์ด์ |
|---|
| ํ์
๋ช
์ | input_text: str, target_lang: str | ํ์
์์ ์ฑ๊ณผ IDE ์ง์ ํฅ์ |
| ๋น ๋ฌธ์์ด ์ฒ๋ฆฌ | if not input_text.strip() | ์ค๋ฅ ๋ฐฉ์ง ๋ฐ ์กฐ๊ธฐ ๋ฆฌํด |
| target_lang ํ๋ผ๋ฏธํฐํ | "en" ๊ณ ์ ์ ๊ฑฐ | ๋ฒ์ฉ์ฑ๊ณผ ํ
์คํธ ๊ฐ๋ฅ์ฑ ์ฆ๊ฐ |
| ์ธ์ด ๋ก๊ทธ ์ถ๊ฐ | logger.info(f"Detected...") | ์ด์ ์ค ๋ค๊ตญ์ด ์
๋ ฅ ๋ถํฌ ํ์ธ ๊ฐ๋ฅ |
| ์๋ฌ ๋ ๋ฒจ ๊ตฌ๋ถ | ๊ฐ์ง ์คํจ = warning, ๋ฒ์ญ ์คํจ = error | ๋ชจ๋ํฐ๋ง ์ ์ํฅ๋ ๊ธฐ์ค ๋ถ๋ฅ ๊ฐ๋ฅ |
load_spacy_model
| ํญ๋ชฉ | ๊ฐ์ ๋ด์ฉ | ์ด์ |
|---|
Lock ์ฌ์ฉ | threading.Lock ๋์
| ๋ฉํฐ์ค๋ ๋ ํ๊ฒฝ์์ race condition ๋ฐฉ์ง |
double-checked locking | if _NLP is None 2๋ฒ ํ์ธ | ๋ถํ์ํ Lock ํ๋ ๋ฐฉ์ง (์ฑ๋ฅ ์ต์ ํ) |
| ์์ธ ์ฒ๋ฆฌ ์ถ๊ฐ | try-except ๋ฌธ | ๋ชจ๋ธ ๋ก๋ฉ ์คํจ ์ ์๋ฌ ๋ก๊ทธ ๋ฐ ๋ช
ํํ ์ถ์ ๊ฐ๋ฅ |
| ๋ช
ํํ ํ์
ํํธ | -> Language, _NLP: Optional[Language] | ์ฝ๋ ์๋์์ฑ๊ณผ ํ์
๊ฒ์ฌ ์ง์ |
QueryClassifier
| ํญ๋ชฉ | ๋ณ๊ฒฝ ๋ด์ฉ | ์ด์ |
|---|
| spaCy ๋ชจ๋ธ ๋ก๋ฉ ์ต์ํ | load_spacy_model() 1ํ๋ง ํธ์ถ | ๋ถํ์ํ IO ๋ฐ ์ฑ๋ฅ ๋ญ๋น ๋ฐฉ์ง |
| ์ค๋ณต ์ ๊ท์ ์ต์ ํ | re.compile() ํจํด ์ ์ | ์ปดํ์ผ ์ ๊ฐ์, ์ฑ๋ฅ ์ต์ ํ |
| ํจ์ ์ฑ
์ ๋ถ๋ฆฌ | detect_location_question, extract_main_noun | ํ
์คํธ ๋ฐ ์ ์ง๋ณด์ ์ฌ์ |
| ํ๋์ฝ๋ฉ ๊ฐ ์์ํ | _location_patterns, _location_verbs, _threshold ๋ฑ | ๊ฐ๋
์ฑ๊ณผ ์์ ์ฉ์ด์ฑ ํฅ์ |
| ๋ฉ์๋ ์ค์ฌ ์ค๊ณ | ํด๋์ค ์ธ๋ถ ์์กด ์ต์ํ | ์ ๋ํ
์คํธ ๋ฐ ์บก์ํ ์ ํฉ |
LocationHandler
| ํญ๋ชฉ | ๊ฐ์ ๋ด์ฉ | ์ด์ |
|---|
| ํ์
ํํธ ๋ช
ํํ | UserInfoModel, ResponseButtonModel, Optional[...] | ์ ์ ๋ถ์, ์๋์์ฑ, ํ
์คํธ์ ์ ๋ฆฌ |
| ์ฌ์ฉ์ ์์น ์ ํจ์ฑ ๊ฒ์ฌ | latitude, longitude None ์ฒดํฌ | ์๋ชป๋ ์์น ์ ๋ณด ์ฒ๋ฆฌ ๋ฐฉ์ง |
| ์์ธ ์ฒ๋ฆฌ ์ถ๊ฐ | try-except ๋์
| ์๋น์ค ์ค๋จ ๋ฐฉ์ง, graceful degradation |
| ๋ก๊ทธ ์ถ๊ฐ | warning / error ๊ตฌ๋ถ | ์ด์ ์ค ๋๋ฒ๊น
๋ฐ ์ฌ์ฉ์ ์ด์ ์ถ์ ์ ์ ์ฉ |
app.langgraph_chatbot.node.retrieve.py
| ํญ๋ชฉ | ๊ฐ์ ๋ด์ฉ | ์ด์ |
|---|
state.get("query", "").strip() | query ์ ํจ์ฑ ํ ์ค๋ก ๊ฒ์ฌ | ๋ช
ํํ๊ณ ์์ ํ๊ฒ ์ฒ๋ฆฌ ๊ฐ๋ฅ |
logger.exception() ์ฌ์ฉ | ์ ์ฒด traceback ํฌํจ ๋ก๊น
| ๋๋ฒ๊น
์ ๋ ๋ง์ ์ ๋ณด ์ ๊ณต |
| Lazy import ์์น ๋ช
ํํ | from app.main import vector_store | ์ํ ์ฐธ์กฐ ๋ฌธ์ ๋ฐฉ์ง |
| ๋ก๊น
์ผ๊ด์ฑ ํฅ์ | prefix ํฌํจ โ [retrieve_context] | ๋ก๊ทธ ํํฐ๋ง/๊ฒ์์ ์ ๋ฆฌ |
| ๋ถํ์ํ ์ฝ๋ฉํธ ์ ๊ฑฐ | ์ฝ๋๊ฐ ์๋๋ฅผ ์ ์ค๋ช
ํจ | ๊ฐ๋
์ฑ ํฅ์ |
app.langgraph_chatbot.node.generate.py
| ํญ๋ชฉ | ๊ฐ์ ๋ด์ฉ | ์ด์ |
|---|
| ๋น ์ฟผ๋ฆฌ early return | query.strip() ์ฒดํฌ | ๋ถํ์ํ ์ฒ๋ฆฌ ๋ฐฉ์ง ๋ฐ UX ๊ฐ์ |
| ์ธ์ด ๊ฐ์ง fallback | ์คํจ ์ ๋ก๊ทธ + default ์ธ์ด | ๋ค๊ตญ์ด ์
๋ ฅ ๋์ ์ ๋ขฐ์ฑ ํฅ์ |
| prompt ํ์ผ ์์ธ ์ฒ๋ฆฌ | FileNotFoundError ๋ถ๋ฆฌ | ์ด์ ์ config ๋๋ฝ ํ์ง ๊ฐ๋ฅ |
| ๋ชจ๋ธ๋ช
์์ํ ์ ๊ฑฐ | "gpt-4o-mini" ์ง์ ๋ช
์ | ํ
์คํธ ๋ฐ ๋ฆฌํฉํ ๋ง ์ ์ฐ |
| ๋ก๊น
prefix ํต์ผ | [generate_response] ์ฌ์ฉ | ์ถ์ ์ฑ๊ณผ ํํฐ๋ง ํฅ์ |
| ๋ฉ์์ง ์
๋ ฅ ๋ถ๋ฆฌ | prompt_inputs ๋ณ์ํ | ๊ฐ๋
์ฑ + ๋๋ฒ๊น
์ฉ์ด |
| LCEL ์ ์ฉ | LCEL ๋ฌธ๋ฒ ์ ์ฉ | ๊ฐ๋
์ฑ + ์ ์ฐํจ |
app.main.py
| ํญ๋ชฉ | ๊ฐ์ | ์ด์ |
|---|
create_app() ํจ์ ๋ถ๋ฆฌ | ํ
์คํธ ์ TestClient(create_app()) ๊ตฌ์กฐ ํ์ฉ | DI ๋ฐ ์ ๋ ํ
์คํธ ํธ์์ฑ ํฅ์ |
ํ๊ฒฝ ๋ณ์ setdefault() | ์ด๋ฏธ ์ค์ ๋ ๊ฐ ๋ฎ์ด์ฐ์ง ์์ | ์ ์ฐํ ํ๊ฒฝ ๊ตฌ์ฑ ๋์ |
lifespan() ๋ด ์์ธ์ฒ๋ฆฌ ์ถ๊ฐ | ์ด๊ธฐํ ์คํจ ์ ๋ก๊ทธ ๋ฐ ๋ช
ํํ ์ค๋ฅ ํ์ | ์ด์ ์ค ๋ฌธ์ ํ์ง ์ฉ์ด |
| ๋ผ์ฐํฐ ๋ฐ ๋ฏธ๋ค์จ์ด ์ ๋ฆฌ | ๋ช
์์ ์ด๊ณ ๋ชจ๋ํ๋ ๋ฑ๋ก | ๊ธฐ๋ฅ๋ณ ๋ถ๋ฆฌ, ๊ด๋ฆฌ ํธ์์ฑ ์ฆ๊ฐ |
| ํฌ์ค ์ฒดํฌ ์๋ํฌ์ธํธ ๋ช
ํํ | / โ read_root() ํจ์ | ๋ฐฐํฌ ํ๊ฒฝ์์ ๊ธฐ๋ณธ ์๋ต ์ฉ์ด |
Refactor ์ ์ฉ ์ : 353.59s (42passed)
Refactor ์ ์ฉ ํ: 310.05s (42passed)
ํ์ฌ ๋ฌธ์ ๋ ๋ฌด์์ธ๊ฐ?
LangSmith๋ฅผ ํตํด ์ถ์ ํ๋ฉฐ ์ด๋์ ์๊ฐ์ด ๋ง์ด ์์๋๋์ง ํ์ธํด๋ณธ ๊ฒฐ๊ณผ:
LLM์ ์ต์ข
๋ต๋ณ ์์ฑ ์๊ฐ์ด ์ค๋ ๊ฑธ๋ฆผ.
์ ์ค๋ ๊ฑธ๋ฆฌ๋๊ฐ?
Retrieve ๋ก ๊ฐ์ ธ์จ ๋ฌธ์์ ์์ด ์๋นํด์.
๊ทธ๋ ๋ค๊ณ ํด๋น ๋ฌธ์๋ค์ด ๋ฐ๋์ ๊ด๋ จ์ด ์๋๊ฐ?
๋ ๊ทธ๋ฐ ๊ฒ์ ์๋.
ํค์ค์คํฌ ์ด๋ป๊ฒ ์ฌ์ฉํ๋๋ ์ง๋ฌธ์ ๊ฒฐํผ ๋น์ ๋ฌธ์๋ถํฐ ๊ฐ์ ธ์ค๋ ๊ฒ์ ๋ณด๋ฉด ์๋ ๊ฒ์ผ๋ก ๋ณด์.
์ด์ ๊ฐ์ ์ฌํญ์ผ๋ก 2๊ฐ์ง ์ ๋๋ฅผ ์๊ฐํด๋ณผ ์ ์๋ค.
- Retrieve ๊ฐ์
- classify node์์ Fallback์ผ๋ก ์ผ๋ฐ ์ง๋ฌธ์ผ ๊ฒฝ์ฐ retrieveํ์ง ์๊ณ ๋ฐ๋ก generate๋ก ๊ฐ๋ ๋ฐฉ๋ฒ.