Skip to content

Commit 0b4e3f6

Browse files
authored
Merge branch 'master' into feature/46-retrieve성능-향상
2 parents a6d7a76 + 382d831 commit 0b4e3f6

File tree

4 files changed

+194
-23
lines changed

4 files changed

+194
-23
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,4 @@ dist/
88
.venv/
99
test_lhm/
1010
.cursorignore
11+
.vscode

cli/__init__.py

Lines changed: 115 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,135 @@
1-
import click
1+
"""
2+
Datahub GMS 서버 URL을 설정하고, 필요 시 Streamlit 인터페이스를 실행하는 CLI 프로그램입니다.
3+
"""
4+
25
import subprocess
6+
7+
import click
8+
39
from llm_utils.tools import set_gms_server
410

511

612
@click.group()
713
@click.version_option(version="0.1.4")
814
@click.pass_context
915
@click.option(
10-
"--datahub_server", default="http://localhost:8080", help="Datahub GMS 서버 URL"
16+
"--datahub_server",
17+
default="http://localhost:8080",
18+
help=(
19+
"Datahub GMS 서버의 URL을 설정합니다. "
20+
"기본값은 'http://localhost:8080'이며, "
21+
"운영 환경 또는 테스트 환경에 맞게 변경할 수 있습니다."
22+
),
23+
)
24+
@click.option(
25+
"--run-streamlit",
26+
is_flag=True,
27+
help=(
28+
"이 옵션을 지정하면 CLI 실행 시 Streamlit 애플리케이션을 바로 실행합니다. "
29+
"별도의 명령어 입력 없이 웹 인터페이스를 띄우고 싶을 때 사용합니다."
30+
),
31+
)
32+
@click.option(
33+
"-p",
34+
"--port",
35+
type=int,
36+
default=8501,
37+
help=(
38+
"Streamlit 서버가 바인딩될 포트 번호를 지정합니다. "
39+
"기본 포트는 8501이며, 포트 충돌을 피하거나 여러 인스턴스를 실행할 때 변경할 수 있습니다."
40+
),
1141
)
12-
@click.option("--run-streamlit", is_flag=True, help="Run the Streamlit app.")
13-
@click.option("-p", "--port", type=int, default=8501, help="Streamlit port")
14-
def cli(ctx, datahub_server, run_streamlit, port):
42+
# pylint: disable=redefined-outer-name
43+
def cli(
44+
ctx: click.Context,
45+
datahub_server: str,
46+
run_streamlit: bool,
47+
port: int,
48+
) -> None:
49+
"""
50+
Datahub GMS 서버 URL을 설정하고, Streamlit 애플리케이션을 실행할 수 있는 CLI 명령 그룹입니다.
51+
52+
이 함수는 다음 역할을 수행합니다:
53+
- 전달받은 'datahub_server' URL을 바탕으로 GMS 서버 연결을 설정합니다.
54+
- 설정 과정 중 오류가 발생하면 오류 메시지를 출력하고 프로그램을 종료합니다.
55+
- '--run-streamlit' 옵션이 활성화된 경우, 지정된 포트에서 Streamlit 웹 앱을 즉시 실행합니다.
56+
57+
매개변수:
58+
ctx (click.Context): 명령어 실행 컨텍스트 객체입니다.
59+
datahub_server (str): 설정할 Datahub GMS 서버의 URL입니다.
60+
run_streamlit (bool): Streamlit 앱을 실행할지 여부를 나타내는 플래그입니다.
61+
port (int): Streamlit 서버가 바인딩될 포트 번호입니다.
62+
63+
주의:
64+
'set_gms_server' 함수에서 ValueError가 발생할 경우, 프로그램은 비정상 종료(exit code 1)합니다.
65+
"""
66+
1567
try:
1668
set_gms_server(datahub_server)
1769
except ValueError as e:
18-
click.echo(str(e))
70+
click.secho(f"GMS 서버 URL 설정 실패: {str(e)}", fg="red")
1971
ctx.exit(1)
2072
if run_streamlit:
2173
run_streamlit_command(port)
2274

2375

24-
def run_streamlit_command(port):
25-
"""Run the Streamlit app."""
26-
subprocess.run(
27-
["streamlit", "run", "interface/streamlit_app.py", "--server.port", str(port)]
28-
)
76+
def run_streamlit_command(port: int) -> None:
77+
"""
78+
지정된 포트에서 Streamlit 애플리케이션을 실행하는 함수입니다.
79+
80+
이 함수는 subprocess를 통해 'streamlit run' 명령어를 실행하여
81+
'interface/streamlit_app.py' 파일을 웹 서버 형태로 구동합니다.
82+
사용자가 지정한 포트 번호를 Streamlit 서버의 포트로 설정합니다.
83+
84+
매개변수:
85+
port (int): Streamlit 서버가 바인딩될 포트 번호입니다.
86+
87+
주의:
88+
- Streamlit이 시스템에 설치되어 있어야 정상 동작합니다.
89+
- subprocess 호출 실패 시 예외가 발생할 수 있습니다.
90+
"""
91+
92+
try:
93+
subprocess.run(
94+
[
95+
"streamlit",
96+
"run",
97+
"interface/streamlit_app.py",
98+
"--server.port",
99+
str(port),
100+
],
101+
check=True,
102+
)
103+
except subprocess.CalledProcessError as e:
104+
click.echo(f"Streamlit 실행 실패: {e}")
105+
raise
106+
107+
108+
@cli.command(name="run-streamlit")
109+
@click.option(
110+
"-p",
111+
"--port",
112+
type=int,
113+
default=8501,
114+
help=(
115+
"Streamlit 애플리케이션이 바인딩될 포트 번호를 지정합니다. "
116+
"기본 포트는 8501이며, 필요 시 포트 충돌을 피하거나 "
117+
"여러 인스턴스를 동시에 실행할 때 다른 포트 번호를 설정할 수 있습니다."
118+
),
119+
)
120+
def run_streamlit_cli_command(port: int) -> None:
121+
"""
122+
CLI 명령어를 통해 Streamlit 애플리케이션을 실행하는 함수입니다.
123+
124+
이 명령은 'interface/streamlit_app.py' 파일을 Streamlit 서버로 구동하며,
125+
사용자가 지정한 포트 번호를 바인딩하여 웹 인터페이스를 제공합니다.
126+
127+
매개변수:
128+
port (int): Streamlit 서버가 사용할 포트 번호입니다. 기본값은 8501입니다.
29129
130+
주의:
131+
- Streamlit이 시스템에 설치되어 있어야 정상적으로 실행됩니다.
132+
- Streamlit 실행에 실패할 경우 subprocess 호출에서 예외가 발생할 수 있습니다.
133+
"""
30134

31-
@cli.command()
32-
@click.option("-p", "--port", type=int, default=8501, help="Streamlit port")
33-
def run_streamlit(port):
34-
"""Run the Streamlit app."""
35135
run_streamlit_command(port)

interface/streamlit_app.py

Lines changed: 72 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,75 @@
1+
"""
2+
Streamlit 멀티 페이지 애플리케이션 설정 파일.
3+
4+
- PAGES 딕셔너리로 페이지 정보(page 경로 및 제목)를 관리합니다.
5+
- PAGES를 기반으로 Streamlit 네비게이션 메뉴를 생성하고 실행합니다.
6+
"""
7+
18
import streamlit as st
29

3-
pg = st.navigation(
4-
[
5-
st.Page("lang2sql.py", title="Lang2SQL"),
6-
st.Page("viz_eval.py", title="Lang2SQL Evaluation 시각화"),
7-
]
8-
)
10+
PAGES = {
11+
"lang2sql": {
12+
"page": "lang2sql.py",
13+
"title": "Lang2SQL",
14+
},
15+
"lang2sql_eval_viz": {
16+
"page": "viz_eval.py",
17+
"title": "Lang2SQL Evaluation 시각화",
18+
},
19+
}
20+
21+
22+
def validate_pages(
23+
*,
24+
pages_dict: dict,
25+
) -> None:
26+
"""
27+
PAGES 딕셔너리의 구조와 값을 검증합니다.
28+
29+
검증 항목:
30+
- 최상위 객체는 딕셔너리(dict)여야 합니다.
31+
- 각 항목은 'page'와 'title' 키를 가진 딕셔너리여야 합니다.
32+
- 'page'와 'title' 값은 비어 있지 않은 문자열이어야 합니다.
33+
34+
오류 발생:
35+
- 조건을 만족하지 않으면 ValueError를 발생시킵니다.
36+
37+
Args:
38+
pages_dict (dict): 페이지 정보가 담긴 딕셔너리
39+
40+
Raises:
41+
ValueError: 유효하지 않은 구조나 값을 가진 경우
42+
"""
43+
44+
if not isinstance(pages_dict, dict):
45+
raise ValueError("PAGES must be a dictionary.")
46+
47+
for key, page_info in pages_dict.items():
48+
if not isinstance(page_info, dict):
49+
raise ValueError(
50+
f"Each page info must be a dictionary. Error at key: {key}"
51+
)
52+
53+
if "page" not in page_info or "title" not in page_info:
54+
raise ValueError(
55+
f"Each page must have 'page' and 'title' fields. Error at key: {key}"
56+
)
57+
58+
if not isinstance(page_info["page"], str) or not page_info["page"]:
59+
raise ValueError(f"'page' must be a non-empty string. Error at key: {key}")
60+
61+
if not isinstance(page_info["title"], str) or not page_info["title"]:
62+
raise ValueError(f"'title' must be a non-empty string. Error at key: {key}")
63+
64+
65+
validate_pages(pages_dict=PAGES)
66+
67+
pages = [
68+
st.Page(
69+
page=page_info["page"],
70+
title=page_info["title"],
71+
)
72+
for page_info in PAGES.values()
73+
]
974

10-
pg.run()
75+
st.navigation(pages).run()

requirements.txt

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,9 @@ pre_commit==4.1.0
1111
setuptools
1212
wheel
1313
twine
14-
transformers==4.51.2
14+
transformers==4.51.2
15+
langchain-aws>=0.2.21,<0.3.0
16+
langchain-google-genai>=2.1.3,<3.0.0
17+
langchain-ollama>=0.3.2,<0.4.0
18+
langchain-huggingface>=0.1.2,<0.2.0
19+
clickhouse_driver

0 commit comments

Comments
 (0)