hangyeol 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- hangyeol-0.1.0/LICENSE +21 -0
- hangyeol-0.1.0/PKG-INFO +217 -0
- hangyeol-0.1.0/README.md +183 -0
- hangyeol-0.1.0/hangyeol.egg-info/PKG-INFO +217 -0
- hangyeol-0.1.0/hangyeol.egg-info/SOURCES.txt +73 -0
- hangyeol-0.1.0/hangyeol.egg-info/dependency_links.txt +1 -0
- hangyeol-0.1.0/hangyeol.egg-info/entry_points.txt +2 -0
- hangyeol-0.1.0/hangyeol.egg-info/requires.txt +22 -0
- hangyeol-0.1.0/hangyeol.egg-info/top_level.txt +3 -0
- hangyeol-0.1.0/pyproject.toml +49 -0
- hangyeol-0.1.0/setup.cfg +4 -0
- hangyeol-0.1.0/tests/test_http/354/227/260/352/262/260.py +124 -0
- hangyeol-0.1.0/tests/test_llm/353/263/265/354/233/220.py +214 -0
- hangyeol-0.1.0/tests/test_mcp/354/227/260/352/262/260.py +76 -0
- hangyeol-0.1.0/tests/test_/352/262/200/354/246/235.py +80 -0
- hangyeol-0.1.0/tests/test_/352/262/251/353/260/260/354/240/225.py +96 -0
- hangyeol-0.1.0/tests/test_/352/262/251/355/213/200/354/212/244/355/202/244/353/247/210.py +330 -0
- hangyeol-0.1.0/tests/test_/352/262/251/355/213/200/354/227/255/355/225/240_/352/267/200/354/206/215.py +78 -0
- hangyeol-0.1.0/tests/test_/352/267/270/353/236/230/355/224/204/352/265/254/354/204/261.py +90 -0
- hangyeol-0.1.0/tests/test_/353/205/274/355/225/255/352/267/200/354/206/215.py +414 -0
- hangyeol-0.1.0/tests/test_/353/214/200/355/231/224.py +91 -0
- hangyeol-0.1.0/tests/test_/353/217/204/352/265/254/353/240/210/354/247/200/354/212/244/355/212/270/353/246/254.py +56 -0
- hangyeol-0.1.0/tests/test_/353/263/265/354/233/220/355/217/264/353/260/261.py +97 -0
- hangyeol-0.1.0/tests/test_/353/266/210/355/231/225/354/213/244/354/204/261_/354/236/254/354/241/260/354/240/225.py +101 -0
- hangyeol-0.1.0/tests/test_/354/205/270/354/227/260/352/262/260.py +103 -0
- hangyeol-0.1.0/tests/test_/354/210/240/354/226/264/352/270/260/353/263/270/355/230/225.py +96 -0
- hangyeol-0.1.0/tests/test_/354/213/235/353/263/204/354/236/220_/355/225/234/352/270/200.py +162 -0
- hangyeol-0.1.0/tests/test_/354/213/244/355/226/211/354/227/224/354/247/204.py +46 -0
- hangyeol-0.1.0/tests/test_/354/213/244/355/226/211/355/206/265/355/225/251.py +66 -0
- hangyeol-0.1.0/tests/test_/354/227/255/355/225/240/353/260/260/354/240/225.py +84 -0
- hangyeol-0.1.0/tests/test_/354/227/260/352/262/260cli.py +40 -0
- hangyeol-0.1.0/tests/test_/354/227/260/352/262/260/353/247/210/353/262/225/354/202/254.py +37 -0
- hangyeol-0.1.0/tests/test_/354/227/260/352/262/260/353/260/234/352/262/254.py +113 -0
- hangyeol-0.1.0/tests/test_/354/231/270/353/266/200/352/260/222_/355/225/234/352/270/200.py +211 -0
- hangyeol-0.1.0/tests/test_/354/235/230/353/257/270/353/266/200/353/245/230.py +210 -0
- hangyeol-0.1.0/tests/test_/354/235/230/354/241/264/355/214/214/354/204/234.py +133 -0
- hangyeol-0.1.0/tests/test_/354/235/230/354/241/264/355/214/214/354/204/234/353/262/244/354/271/230.py +190 -0
- hangyeol-0.1.0/tests/test_/354/266/234/353/240/245/355/225/234/352/270/200.py +109 -0
- hangyeol-0.1.0/tests/test_/354/266/234/353/240/245/355/230/225/354/213/235.py +134 -0
- hangyeol-0.1.0/tests/test_/355/214/214/354/235/274/353/217/204/352/265/254.py +40 -0
- hangyeol-0.1.0/tests/test_/355/221/234/353/251/264/355/230/225_/353/263/265/354/233/220.py +68 -0
- hangyeol-0.1.0/tests/test_/355/230/225/355/203/234/354/206/214.py +72 -0
- hangyeol-0.1.0//354/226/264/355/234/230/354/247/221/__init__.py +1 -0
- hangyeol-0.1.0//354/226/264/355/234/230/354/247/221//352/262/251/355/213/200.yaml +297 -0
- hangyeol-0.1.0//354/226/264/355/234/230/354/247/221//354/210/240/354/226/264.yaml +86 -0
- hangyeol-0.1.0//354/226/264/355/234/230/354/247/221//354/235/230/353/257/270/353/266/200/353/245/230.yaml +102 -0
- hangyeol-0.1.0//354/226/264/355/234/230/354/247/221//354/235/230/353/257/270/354/227/255.yaml +115 -0
- hangyeol-0.1.0//354/226/264/355/234/230/354/247/221//354/241/260/354/202/254.yaml +148 -0
- hangyeol-0.1.0//355/225/234/352/262/260/353/237/260/355/203/200/354/236/204/__init__.py +47 -0
- hangyeol-0.1.0//355/225/234/352/262/260/353/237/260/355/203/200/354/236/204/cli.py +205 -0
- hangyeol-0.1.0//355/225/234/352/262/260/353/237/260/355/203/200/354/236/204/http/354/227/260/352/262/260.py +72 -0
- hangyeol-0.1.0//355/225/234/352/262/260/353/237/260/355/203/200/354/236/204/mcp/354/227/260/352/262/260.py +116 -0
- hangyeol-0.1.0//355/225/234/352/262/260/353/237/260/355/203/200/354/236/204//352/262/200/354/203/211/353/217/204/352/265/254.py +58 -0
- hangyeol-0.1.0//355/225/234/352/262/260/353/237/260/355/203/200/354/236/204//353/214/200/355/231/224.py +112 -0
- hangyeol-0.1.0//355/225/234/352/262/260/353/237/260/355/203/200/354/236/204//353/217/204/352/265/254/353/240/210/354/247/200/354/212/244/355/212/270/353/246/254.py +91 -0
- hangyeol-0.1.0//355/225/234/352/262/260/353/237/260/355/203/200/354/236/204//353/237/260/355/203/200/354/236/204/355/221/234/355/230/204.py +34 -0
- hangyeol-0.1.0//355/225/234/352/262/260/353/237/260/355/203/200/354/236/204//353/266/204/354/204/235/353/217/204/352/265/254.py +87 -0
- hangyeol-0.1.0//355/225/234/352/262/260/353/237/260/355/203/200/354/236/204//354/205/270/354/227/260/352/262/260.py +72 -0
- hangyeol-0.1.0//355/225/234/352/262/260/353/237/260/355/203/200/354/236/204//354/213/244/355/226/211/354/227/224/354/247/204.py +110 -0
- hangyeol-0.1.0//355/225/234/352/262/260/353/237/260/355/203/200/354/236/204//354/227/260/352/262/260/354/204/244/354/240/225.py +174 -0
- hangyeol-0.1.0//355/225/234/352/262/260/353/237/260/355/203/200/354/236/204//355/214/214/354/235/274/353/217/204/352/265/254.py +59 -0
- hangyeol-0.1.0//355/225/234/352/262/260/355/214/214/354/204/234/__init__.py +80 -0
- hangyeol-0.1.0//355/225/234/352/262/260/355/214/214/354/204/234/llm/353/263/265/354/233/220.py +298 -0
- hangyeol-0.1.0//355/225/234/352/262/260/355/214/214/354/204/234//352/262/200/354/246/235.py +142 -0
- hangyeol-0.1.0//355/225/234/352/262/260/355/214/214/354/204/234//352/262/251/355/213/200/354/241/260/355/232/214.py +288 -0
- hangyeol-0.1.0//355/225/234/352/262/260/355/214/214/354/204/234//353/202/264/353/266/200/355/221/234/355/230/204.py +117 -0
- hangyeol-0.1.0//355/225/234/352/262/260/355/214/214/354/204/234//353/263/265/354/233/220/355/217/264/353/260/261.py +71 -0
- hangyeol-0.1.0//355/225/234/352/262/260/355/214/214/354/204/234//354/226/264/354/240/210/353/254/266/352/270/260.py +171 -0
- hangyeol-0.1.0//355/225/234/352/262/260/355/214/214/354/204/234//354/226/264/355/234/230/354/247/221/353/241/234/353/223/234.py +19 -0
- hangyeol-0.1.0//355/225/234/352/262/260/355/214/214/354/204/234//354/227/255/355/225/240/353/260/260/354/240/225.py +85 -0
- hangyeol-0.1.0//355/225/234/352/262/260/355/214/214/354/204/234//354/234/240/354/202/254/353/217/204.py +28 -0
- hangyeol-0.1.0//355/225/234/352/262/260/355/214/214/354/204/234//354/235/230/353/217/204/352/267/270/353/236/230/355/224/204/352/265/254/354/204/261.py +210 -0
- hangyeol-0.1.0//355/225/234/352/262/260/355/214/214/354/204/234//354/235/230/353/257/270/354/227/255/355/213/200.py +285 -0
- hangyeol-0.1.0//355/225/234/352/262/260/355/214/214/354/204/234//354/235/230/354/241/264/355/214/214/354/204/234.py +174 -0
- hangyeol-0.1.0//355/225/234/352/262/260/355/214/214/354/204/234//355/230/225/355/203/234/354/206/214/353/266/204/354/204/235.py +251 -0
hangyeol-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 sunghoon.kim
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
hangyeol-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: hangyeol
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: K-Parser: 한국어 문법 구조 기반 에이전트 실행 그래프 컴파일러
|
|
5
|
+
Author-email: "sunghoon.kim" <sunghoon.kim@aigensciences.com>
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Keywords: korean,parser,nlp,intent-graph,dependency-parsing,한국어
|
|
8
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
9
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
10
|
+
Classifier: Natural Language :: Korean
|
|
11
|
+
Classifier: Topic :: Text Processing :: Linguistic
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Requires-Python: >=3.11
|
|
14
|
+
Description-Content-Type: text/markdown
|
|
15
|
+
License-File: LICENSE
|
|
16
|
+
Requires-Dist: kiwipiepy>=0.23.1
|
|
17
|
+
Requires-Dist: pyyaml>=6.0
|
|
18
|
+
Requires-Dist: jsonschema>=4.23
|
|
19
|
+
Requires-Dist: numpy>=1.26
|
|
20
|
+
Provides-Extra: parser
|
|
21
|
+
Requires-Dist: stanza>=1.9; extra == "parser"
|
|
22
|
+
Provides-Extra: llm
|
|
23
|
+
Requires-Dist: anthropic>=0.40; extra == "llm"
|
|
24
|
+
Provides-Extra: dev
|
|
25
|
+
Requires-Dist: pytest>=8.0; extra == "dev"
|
|
26
|
+
Requires-Dist: pytest-cov; extra == "dev"
|
|
27
|
+
Requires-Dist: build>=1.0; extra == "dev"
|
|
28
|
+
Requires-Dist: twine>=5.0; extra == "dev"
|
|
29
|
+
Provides-Extra: mcp
|
|
30
|
+
Requires-Dist: mcp>=1.0; extra == "mcp"
|
|
31
|
+
Provides-Extra: repl
|
|
32
|
+
Requires-Dist: prompt_toolkit>=3.0; extra == "repl"
|
|
33
|
+
Dynamic: license-file
|
|
34
|
+
|
|
35
|
+
# 한결 K-Parser
|
|
36
|
+
|
|
37
|
+
> 한국어 발화를 **에이전트 실행 그래프(의도그래프)**로 컴파일하는 한국어 문법 기반 파서.
|
|
38
|
+
|
|
39
|
+
`"CSV로 논문을 찾아서 정리해줘"` 같은 한 문장을, LLM 없이 한국어 문법 구조만으로
|
|
40
|
+
실행 가능한 도구 호출 DAG로 변환한다.
|
|
41
|
+
|
|
42
|
+
```json
|
|
43
|
+
{
|
|
44
|
+
"발화": "CSV로 논문을 찾아서 정리해줘",
|
|
45
|
+
"노드": [
|
|
46
|
+
{"번호": "n1", "도구": "검색", "술어": "찾아서", "인자": {"대상": "논문"}},
|
|
47
|
+
{"번호": "n2", "도구": "요약", "술어": "정리해줘",
|
|
48
|
+
"인자": {"출력형식": "CSV", "대상": "$n1.출력"}}
|
|
49
|
+
],
|
|
50
|
+
"간선": [{"출발": "n1", "도착": "n2", "유형": "선행조건"}],
|
|
51
|
+
"불확실성": []
|
|
52
|
+
}
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
`찾아서`(검색) → `정리해줘`(요약) 두 술어를 노드로, "논문"을 검색 대상으로, "CSV"를
|
|
56
|
+
요약의 출력형식으로 배정하고, `$n1.출력`으로 노드 간 데이터 흐름을 잇는다.
|
|
57
|
+
|
|
58
|
+
## 설계 원칙
|
|
59
|
+
|
|
60
|
+
- **결정론 우선** — 형태소·조사·격틀(세종 동사 사전 계열)만으로 파싱한다. LLM은
|
|
61
|
+
실패한 경우의 *복원* 경로(opt-in)일 뿐, 정상 경로에 개입하지 않는다.
|
|
62
|
+
- **드롭/예외 없음·정직성** — 확신이 없는 배정도 버리지 않고 `불확실성` 배열에
|
|
63
|
+
근거와 함께 남긴다. 선택제약 위반·의미부류 미분류도 침묵하지 않고 신호로 표시한다.
|
|
64
|
+
- **DAG 불변** — 노드ID(`n1`), 노드 간 참조(`$nN.출력`) 형식은 안정 계약.
|
|
65
|
+
- **완전 한글화** — 모듈·함수·필드·테스트까지 한글 식별자(고유명사·3rd-party
|
|
66
|
+
API 표면 제외). `tests/test_식별자_한글.py`가 AST로 강제한다.
|
|
67
|
+
|
|
68
|
+
## 설치
|
|
69
|
+
|
|
70
|
+
요구사항: Python ≥ 3.11
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
python -m venv .venv && source .venv/bin/activate
|
|
74
|
+
pip install -e . # 코어 (kiwipiepy, pyyaml, jsonschema, numpy)
|
|
75
|
+
pip install -e '.[parser]' # + Stanza 의존구문분석 (선택)
|
|
76
|
+
pip install -e '.[llm]' # + anthropic (LLM 복원, 선택)
|
|
77
|
+
pip install -e '.[mcp]' # + mcp (외부 에이전트 연결, 선택)
|
|
78
|
+
pip install -e '.[repl]' # + prompt_toolkit (대화 REPL 편의, 선택)
|
|
79
|
+
pip install -e '.[dev]' # + pytest
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## 빠른 시작
|
|
83
|
+
|
|
84
|
+
### 파이썬 API
|
|
85
|
+
|
|
86
|
+
```python
|
|
87
|
+
from 한결파서 import 파싱, 파싱_json
|
|
88
|
+
|
|
89
|
+
그래프 = 파싱("논문을 요약해줘")
|
|
90
|
+
print(그래프.노드들[0].도구) # → '요약'
|
|
91
|
+
|
|
92
|
+
# JSON 문자열로 바로:
|
|
93
|
+
print(파싱_json("CSV로 논문을 찾아서 정리해줘", 들여쓰기=2))
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
`파싱()` 시그니처:
|
|
97
|
+
|
|
98
|
+
```python
|
|
99
|
+
파싱(발화: str,
|
|
100
|
+
엄격: bool = False, # True면 불확실성 발생 시 예외
|
|
101
|
+
의존파서사용: bool = True, # Stanza UD 보강 (미설치 시 자동 우회)
|
|
102
|
+
llm복원사용: bool = False, # 실패 노드 LLM 복원 (ANTHROPIC_API_KEY 필요)
|
|
103
|
+
예시수: int = 3) -> 의도그래프
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### 명령줄 (CLI)
|
|
107
|
+
|
|
108
|
+
설치 시 `한결` 명령이 등록된다 (또는 `python -m 한결런타임.cli`):
|
|
109
|
+
|
|
110
|
+
```bash
|
|
111
|
+
한결 파싱 "논문을 요약해줘" # 파싱만 (실행 안 함)
|
|
112
|
+
한결 실행 "논문을 요약해줘" # 파싱 후 실제 도구 실행 (샌드박스 ./한결_출력)
|
|
113
|
+
한결 대화 # 발화를 한 줄씩 받아 실행하는 대화형 REPL
|
|
114
|
+
한결 # 인자 없이 실행해도 대화 루프
|
|
115
|
+
한결 연결 --목록 # 등록된 도구를 MCP 커넥터로
|
|
116
|
+
한결 연결 --마법사 # 대화형 마법사로 도구↔서버 연결 등록
|
|
117
|
+
한결 연결 --발견 <서버> # MCP 서버가 노출하는 도구를 자동 발견해 목록 출력
|
|
118
|
+
|
|
119
|
+
# 스킬 브리지 스크립트도 동일 동작:
|
|
120
|
+
python skills/한결/scripts/한결파싱.py "논문을 요약해줘" --들여쓰기
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
`실행`·`대화`의 파일 출력은 기본적으로 샌드박스 디렉터리 `./한결_출력`로
|
|
124
|
+
제한된다(`--샌드박스`로 변경). 요약·번역 등 생성형 도구는 연결이 없으면 실행 시
|
|
125
|
+
"연결된 에이전트 없음" 에러가 나며, `한결 연결 --마법사` 또는 루트의
|
|
126
|
+
[`도구연결.예시.yaml`](도구연결.예시.yaml)을 `도구연결.yaml`로 복사해 등록한다.
|
|
127
|
+
생성형 도구는 `mcp` SDK 없이 로컬 셸 명령으로도 연결할 수 있다(`셸명령들` 섹션) —
|
|
128
|
+
도구 인자는 stdin-JSON으로 들어가고 stdout이 결과로 돌아온다.
|
|
129
|
+
생성형 도구는 원격 HTTP 끝점으로도 연결할 수 있다(`http끝점들` 섹션) —
|
|
130
|
+
`POST {url}/{도구명}` 으로 인자를 JSON 본문에 실어 보내고 응답 본문이 결과로 돌아온다.
|
|
131
|
+
`한결 연결 --마법사`는 서버가 이미 등록돼 있으면 발견된 도구 목록에서 번호로
|
|
132
|
+
고를 수 있어 서버측 도구명을 손으로 외울 필요가 없다.
|
|
133
|
+
|
|
134
|
+
## 출력 구조 (의도그래프)
|
|
135
|
+
|
|
136
|
+
| 필드 | 의미 |
|
|
137
|
+
|---|---|
|
|
138
|
+
| `발화` | 원본 입력 문장 |
|
|
139
|
+
| `실행방식` | `즉시` 등 — 그래프 실행 전략 |
|
|
140
|
+
| `노드` | 도구 호출 단위. `번호`(nN)·`도구`·`술어`(표면형)·`인자`(역할→값 dict) |
|
|
141
|
+
| `간선` | 노드 간 의존. `출발`·`도착`·`유형`(`선행조건` 등) |
|
|
142
|
+
| `불확실성` | 확신 못 한 배정의 근거 목록 — 위반·미분류·미등록 신호 포함 |
|
|
143
|
+
|
|
144
|
+
`인자` 값이 `$n1.출력`이면 앞선 노드의 출력을 참조한다(논항 생략 보충).
|
|
145
|
+
|
|
146
|
+
## 처리 파이프라인 (`한결파서/`)
|
|
147
|
+
|
|
148
|
+
| 단계 | 모듈 | 역할 |
|
|
149
|
+
|---|---|---|
|
|
150
|
+
| 1 형태소분석 | `형태소분석.py` | kiwipiepy 형태소 분해 |
|
|
151
|
+
| 2 어절묶기 | `어절묶기.py` | SOV 어절 묶음 구성 |
|
|
152
|
+
| 3 역할배정 | `역할배정.py` | 조사 → 격(대상·도구·출발점…) |
|
|
153
|
+
| 4 의존파서 | `의존파서.py` | Stanza UD 보강 (선택) |
|
|
154
|
+
| 5 격틀조회 | `격틀조회.py` | 술어 격틀 조회·인자정렬·선택제약 검사 |
|
|
155
|
+
| 6 의도그래프구성 | `의도그래프구성.py` | 술어→노드, 논항 귀속, 간선 연결 (DAG) |
|
|
156
|
+
| 7 검증 | `검증.py` | 순환·미등록 도구·필수 인자 점검 |
|
|
157
|
+
| 8 LLM복원 | `llm복원.py` | 실패 노드 복원 (opt-in, anthropic) |
|
|
158
|
+
|
|
159
|
+
핵심 휴리스틱: **핵어후행 원리**(한국어 논항은 자기 술어에 선행) + **격틀 인가**
|
|
160
|
+
(논항을 "가장 가까운 후행 술어 중 그 역할을 인가하는 첫 술어"에 귀속). 인가 술어가
|
|
161
|
+
없으면 현행 위치를 유지하고 불확실성에 기록한다(silent drop 금지).
|
|
162
|
+
|
|
163
|
+
## 어휘집 (`어휘집/`)
|
|
164
|
+
|
|
165
|
+
| 파일 | 내용 |
|
|
166
|
+
|---|---|
|
|
167
|
+
| `술어.yaml` | 한국어 술어 기본형 → 도구 별칭 |
|
|
168
|
+
| `격틀.yaml` | 도구별 의미역 슬롯(필수/선택) + 허용 조사 + 선택제약 |
|
|
169
|
+
| `조사.yaml` | 조사 → 격 매핑 |
|
|
170
|
+
| `의미역.yaml` | 의미역 ↔ 한글 역할, 국립국어원 표준 약호 |
|
|
171
|
+
| `의미부류.yaml` | 세종 명사 의미부류 타크소노미 + 선택제약 온톨로지 |
|
|
172
|
+
|
|
173
|
+
선택제약은 세종 명사 의미부류 위계로 소프트하게 강제한다 — 위반 시 모호도↑+경고,
|
|
174
|
+
미분류 시 저강도 "검사 불가" 신호, 통과는 그대로(어느 경우에도 역할을 드롭하지 않음).
|
|
175
|
+
|
|
176
|
+
## 런타임 (`한결런타임/`)
|
|
177
|
+
|
|
178
|
+
의도그래프를 실제로 실행하는 계층:
|
|
179
|
+
|
|
180
|
+
- `실행엔진.py` — DAG 위상 정렬 후 노드별 도구 호출, `$nN.출력` 데이터 전달
|
|
181
|
+
- `도구레지스트리.py` / `검색도구.py` / `분석도구.py` / `파일도구.py` — 도구 구현
|
|
182
|
+
- `mcp연결.py` / `연결설정.py` — 한결 도구를 MCP 커넥터로 노출/연결
|
|
183
|
+
- `cli.py` — `한결 파싱|실행|연결` 진입점
|
|
184
|
+
|
|
185
|
+
## 테스트
|
|
186
|
+
|
|
187
|
+
```bash
|
|
188
|
+
.venv/bin/python -m pytest tests/ -q # 전체 (265 passed, 2 skipped)
|
|
189
|
+
.venv/bin/python -m pytest -m 'not slow' -q # 벤치마크 제외
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
`2 skipped`는 LLM 복원의 실제 API 검증 — `ANTHROPIC_API_KEY` 설정 후
|
|
193
|
+
`pytest tests/test_llm복원.py -v`로 해소된다.
|
|
194
|
+
|
|
195
|
+
주요 테스트: `test_논항귀속`(노드·역할 배정) · `test_의미부류`(선택제약) ·
|
|
196
|
+
`test_격틀스키마` · `test_검증` · `test_식별자_한글`(한글 식별자 강제) ·
|
|
197
|
+
`test_실행통합`(런타임).
|
|
198
|
+
|
|
199
|
+
## 프로젝트 구조
|
|
200
|
+
|
|
201
|
+
```
|
|
202
|
+
한결파서/ 파싱 코어 (형태소 → 의도그래프)
|
|
203
|
+
한결런타임/ 실행엔진 + 도구 + MCP + CLI
|
|
204
|
+
어휘집/ 술어·격틀·조사·의미역·의미부류 YAML
|
|
205
|
+
tests/ pytest 스위트 (23개 파일)
|
|
206
|
+
examples/ 기본예시.py
|
|
207
|
+
skills/한결/ 에이전트 스킬 브리지 (한결파싱.py 등)
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
## 개발 워크플로 / 협업 하네스
|
|
211
|
+
|
|
212
|
+
기여 규칙·승인 게이트·세션 협업 규약은 별도 문서에 있다:
|
|
213
|
+
|
|
214
|
+
- **`AGENTS.md`** — 작업 규칙, 승인 게이트, 검증 명령 (공유 규칙의 단일 출처)
|
|
215
|
+
- **`CLAUDE.md`** — Claude Code 진입점, 세션 리추얼, 네이티브 프리미티브
|
|
216
|
+
- **`WORKFLOW.md`** — 계약→플랜→실행 파이프라인, 슬라이스 라우팅
|
|
217
|
+
- **`.agent/`** — 슬라이스별 상태(`status/`)·계약(`contracts/`)·플랜(`plans/`)
|
hangyeol-0.1.0/README.md
ADDED
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
# 한결 K-Parser
|
|
2
|
+
|
|
3
|
+
> 한국어 발화를 **에이전트 실행 그래프(의도그래프)**로 컴파일하는 한국어 문법 기반 파서.
|
|
4
|
+
|
|
5
|
+
`"CSV로 논문을 찾아서 정리해줘"` 같은 한 문장을, LLM 없이 한국어 문법 구조만으로
|
|
6
|
+
실행 가능한 도구 호출 DAG로 변환한다.
|
|
7
|
+
|
|
8
|
+
```json
|
|
9
|
+
{
|
|
10
|
+
"발화": "CSV로 논문을 찾아서 정리해줘",
|
|
11
|
+
"노드": [
|
|
12
|
+
{"번호": "n1", "도구": "검색", "술어": "찾아서", "인자": {"대상": "논문"}},
|
|
13
|
+
{"번호": "n2", "도구": "요약", "술어": "정리해줘",
|
|
14
|
+
"인자": {"출력형식": "CSV", "대상": "$n1.출력"}}
|
|
15
|
+
],
|
|
16
|
+
"간선": [{"출발": "n1", "도착": "n2", "유형": "선행조건"}],
|
|
17
|
+
"불확실성": []
|
|
18
|
+
}
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
`찾아서`(검색) → `정리해줘`(요약) 두 술어를 노드로, "논문"을 검색 대상으로, "CSV"를
|
|
22
|
+
요약의 출력형식으로 배정하고, `$n1.출력`으로 노드 간 데이터 흐름을 잇는다.
|
|
23
|
+
|
|
24
|
+
## 설계 원칙
|
|
25
|
+
|
|
26
|
+
- **결정론 우선** — 형태소·조사·격틀(세종 동사 사전 계열)만으로 파싱한다. LLM은
|
|
27
|
+
실패한 경우의 *복원* 경로(opt-in)일 뿐, 정상 경로에 개입하지 않는다.
|
|
28
|
+
- **드롭/예외 없음·정직성** — 확신이 없는 배정도 버리지 않고 `불확실성` 배열에
|
|
29
|
+
근거와 함께 남긴다. 선택제약 위반·의미부류 미분류도 침묵하지 않고 신호로 표시한다.
|
|
30
|
+
- **DAG 불변** — 노드ID(`n1`), 노드 간 참조(`$nN.출력`) 형식은 안정 계약.
|
|
31
|
+
- **완전 한글화** — 모듈·함수·필드·테스트까지 한글 식별자(고유명사·3rd-party
|
|
32
|
+
API 표면 제외). `tests/test_식별자_한글.py`가 AST로 강제한다.
|
|
33
|
+
|
|
34
|
+
## 설치
|
|
35
|
+
|
|
36
|
+
요구사항: Python ≥ 3.11
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
python -m venv .venv && source .venv/bin/activate
|
|
40
|
+
pip install -e . # 코어 (kiwipiepy, pyyaml, jsonschema, numpy)
|
|
41
|
+
pip install -e '.[parser]' # + Stanza 의존구문분석 (선택)
|
|
42
|
+
pip install -e '.[llm]' # + anthropic (LLM 복원, 선택)
|
|
43
|
+
pip install -e '.[mcp]' # + mcp (외부 에이전트 연결, 선택)
|
|
44
|
+
pip install -e '.[repl]' # + prompt_toolkit (대화 REPL 편의, 선택)
|
|
45
|
+
pip install -e '.[dev]' # + pytest
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## 빠른 시작
|
|
49
|
+
|
|
50
|
+
### 파이썬 API
|
|
51
|
+
|
|
52
|
+
```python
|
|
53
|
+
from 한결파서 import 파싱, 파싱_json
|
|
54
|
+
|
|
55
|
+
그래프 = 파싱("논문을 요약해줘")
|
|
56
|
+
print(그래프.노드들[0].도구) # → '요약'
|
|
57
|
+
|
|
58
|
+
# JSON 문자열로 바로:
|
|
59
|
+
print(파싱_json("CSV로 논문을 찾아서 정리해줘", 들여쓰기=2))
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
`파싱()` 시그니처:
|
|
63
|
+
|
|
64
|
+
```python
|
|
65
|
+
파싱(발화: str,
|
|
66
|
+
엄격: bool = False, # True면 불확실성 발생 시 예외
|
|
67
|
+
의존파서사용: bool = True, # Stanza UD 보강 (미설치 시 자동 우회)
|
|
68
|
+
llm복원사용: bool = False, # 실패 노드 LLM 복원 (ANTHROPIC_API_KEY 필요)
|
|
69
|
+
예시수: int = 3) -> 의도그래프
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### 명령줄 (CLI)
|
|
73
|
+
|
|
74
|
+
설치 시 `한결` 명령이 등록된다 (또는 `python -m 한결런타임.cli`):
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
한결 파싱 "논문을 요약해줘" # 파싱만 (실행 안 함)
|
|
78
|
+
한결 실행 "논문을 요약해줘" # 파싱 후 실제 도구 실행 (샌드박스 ./한결_출력)
|
|
79
|
+
한결 대화 # 발화를 한 줄씩 받아 실행하는 대화형 REPL
|
|
80
|
+
한결 # 인자 없이 실행해도 대화 루프
|
|
81
|
+
한결 연결 --목록 # 등록된 도구를 MCP 커넥터로
|
|
82
|
+
한결 연결 --마법사 # 대화형 마법사로 도구↔서버 연결 등록
|
|
83
|
+
한결 연결 --발견 <서버> # MCP 서버가 노출하는 도구를 자동 발견해 목록 출력
|
|
84
|
+
|
|
85
|
+
# 스킬 브리지 스크립트도 동일 동작:
|
|
86
|
+
python skills/한결/scripts/한결파싱.py "논문을 요약해줘" --들여쓰기
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
`실행`·`대화`의 파일 출력은 기본적으로 샌드박스 디렉터리 `./한결_출력`로
|
|
90
|
+
제한된다(`--샌드박스`로 변경). 요약·번역 등 생성형 도구는 연결이 없으면 실행 시
|
|
91
|
+
"연결된 에이전트 없음" 에러가 나며, `한결 연결 --마법사` 또는 루트의
|
|
92
|
+
[`도구연결.예시.yaml`](도구연결.예시.yaml)을 `도구연결.yaml`로 복사해 등록한다.
|
|
93
|
+
생성형 도구는 `mcp` SDK 없이 로컬 셸 명령으로도 연결할 수 있다(`셸명령들` 섹션) —
|
|
94
|
+
도구 인자는 stdin-JSON으로 들어가고 stdout이 결과로 돌아온다.
|
|
95
|
+
생성형 도구는 원격 HTTP 끝점으로도 연결할 수 있다(`http끝점들` 섹션) —
|
|
96
|
+
`POST {url}/{도구명}` 으로 인자를 JSON 본문에 실어 보내고 응답 본문이 결과로 돌아온다.
|
|
97
|
+
`한결 연결 --마법사`는 서버가 이미 등록돼 있으면 발견된 도구 목록에서 번호로
|
|
98
|
+
고를 수 있어 서버측 도구명을 손으로 외울 필요가 없다.
|
|
99
|
+
|
|
100
|
+
## 출력 구조 (의도그래프)
|
|
101
|
+
|
|
102
|
+
| 필드 | 의미 |
|
|
103
|
+
|---|---|
|
|
104
|
+
| `발화` | 원본 입력 문장 |
|
|
105
|
+
| `실행방식` | `즉시` 등 — 그래프 실행 전략 |
|
|
106
|
+
| `노드` | 도구 호출 단위. `번호`(nN)·`도구`·`술어`(표면형)·`인자`(역할→값 dict) |
|
|
107
|
+
| `간선` | 노드 간 의존. `출발`·`도착`·`유형`(`선행조건` 등) |
|
|
108
|
+
| `불확실성` | 확신 못 한 배정의 근거 목록 — 위반·미분류·미등록 신호 포함 |
|
|
109
|
+
|
|
110
|
+
`인자` 값이 `$n1.출력`이면 앞선 노드의 출력을 참조한다(논항 생략 보충).
|
|
111
|
+
|
|
112
|
+
## 처리 파이프라인 (`한결파서/`)
|
|
113
|
+
|
|
114
|
+
| 단계 | 모듈 | 역할 |
|
|
115
|
+
|---|---|---|
|
|
116
|
+
| 1 형태소분석 | `형태소분석.py` | kiwipiepy 형태소 분해 |
|
|
117
|
+
| 2 어절묶기 | `어절묶기.py` | SOV 어절 묶음 구성 |
|
|
118
|
+
| 3 역할배정 | `역할배정.py` | 조사 → 격(대상·도구·출발점…) |
|
|
119
|
+
| 4 의존파서 | `의존파서.py` | Stanza UD 보강 (선택) |
|
|
120
|
+
| 5 격틀조회 | `격틀조회.py` | 술어 격틀 조회·인자정렬·선택제약 검사 |
|
|
121
|
+
| 6 의도그래프구성 | `의도그래프구성.py` | 술어→노드, 논항 귀속, 간선 연결 (DAG) |
|
|
122
|
+
| 7 검증 | `검증.py` | 순환·미등록 도구·필수 인자 점검 |
|
|
123
|
+
| 8 LLM복원 | `llm복원.py` | 실패 노드 복원 (opt-in, anthropic) |
|
|
124
|
+
|
|
125
|
+
핵심 휴리스틱: **핵어후행 원리**(한국어 논항은 자기 술어에 선행) + **격틀 인가**
|
|
126
|
+
(논항을 "가장 가까운 후행 술어 중 그 역할을 인가하는 첫 술어"에 귀속). 인가 술어가
|
|
127
|
+
없으면 현행 위치를 유지하고 불확실성에 기록한다(silent drop 금지).
|
|
128
|
+
|
|
129
|
+
## 어휘집 (`어휘집/`)
|
|
130
|
+
|
|
131
|
+
| 파일 | 내용 |
|
|
132
|
+
|---|---|
|
|
133
|
+
| `술어.yaml` | 한국어 술어 기본형 → 도구 별칭 |
|
|
134
|
+
| `격틀.yaml` | 도구별 의미역 슬롯(필수/선택) + 허용 조사 + 선택제약 |
|
|
135
|
+
| `조사.yaml` | 조사 → 격 매핑 |
|
|
136
|
+
| `의미역.yaml` | 의미역 ↔ 한글 역할, 국립국어원 표준 약호 |
|
|
137
|
+
| `의미부류.yaml` | 세종 명사 의미부류 타크소노미 + 선택제약 온톨로지 |
|
|
138
|
+
|
|
139
|
+
선택제약은 세종 명사 의미부류 위계로 소프트하게 강제한다 — 위반 시 모호도↑+경고,
|
|
140
|
+
미분류 시 저강도 "검사 불가" 신호, 통과는 그대로(어느 경우에도 역할을 드롭하지 않음).
|
|
141
|
+
|
|
142
|
+
## 런타임 (`한결런타임/`)
|
|
143
|
+
|
|
144
|
+
의도그래프를 실제로 실행하는 계층:
|
|
145
|
+
|
|
146
|
+
- `실행엔진.py` — DAG 위상 정렬 후 노드별 도구 호출, `$nN.출력` 데이터 전달
|
|
147
|
+
- `도구레지스트리.py` / `검색도구.py` / `분석도구.py` / `파일도구.py` — 도구 구현
|
|
148
|
+
- `mcp연결.py` / `연결설정.py` — 한결 도구를 MCP 커넥터로 노출/연결
|
|
149
|
+
- `cli.py` — `한결 파싱|실행|연결` 진입점
|
|
150
|
+
|
|
151
|
+
## 테스트
|
|
152
|
+
|
|
153
|
+
```bash
|
|
154
|
+
.venv/bin/python -m pytest tests/ -q # 전체 (265 passed, 2 skipped)
|
|
155
|
+
.venv/bin/python -m pytest -m 'not slow' -q # 벤치마크 제외
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
`2 skipped`는 LLM 복원의 실제 API 검증 — `ANTHROPIC_API_KEY` 설정 후
|
|
159
|
+
`pytest tests/test_llm복원.py -v`로 해소된다.
|
|
160
|
+
|
|
161
|
+
주요 테스트: `test_논항귀속`(노드·역할 배정) · `test_의미부류`(선택제약) ·
|
|
162
|
+
`test_격틀스키마` · `test_검증` · `test_식별자_한글`(한글 식별자 강제) ·
|
|
163
|
+
`test_실행통합`(런타임).
|
|
164
|
+
|
|
165
|
+
## 프로젝트 구조
|
|
166
|
+
|
|
167
|
+
```
|
|
168
|
+
한결파서/ 파싱 코어 (형태소 → 의도그래프)
|
|
169
|
+
한결런타임/ 실행엔진 + 도구 + MCP + CLI
|
|
170
|
+
어휘집/ 술어·격틀·조사·의미역·의미부류 YAML
|
|
171
|
+
tests/ pytest 스위트 (23개 파일)
|
|
172
|
+
examples/ 기본예시.py
|
|
173
|
+
skills/한결/ 에이전트 스킬 브리지 (한결파싱.py 등)
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
## 개발 워크플로 / 협업 하네스
|
|
177
|
+
|
|
178
|
+
기여 규칙·승인 게이트·세션 협업 규약은 별도 문서에 있다:
|
|
179
|
+
|
|
180
|
+
- **`AGENTS.md`** — 작업 규칙, 승인 게이트, 검증 명령 (공유 규칙의 단일 출처)
|
|
181
|
+
- **`CLAUDE.md`** — Claude Code 진입점, 세션 리추얼, 네이티브 프리미티브
|
|
182
|
+
- **`WORKFLOW.md`** — 계약→플랜→실행 파이프라인, 슬라이스 라우팅
|
|
183
|
+
- **`.agent/`** — 슬라이스별 상태(`status/`)·계약(`contracts/`)·플랜(`plans/`)
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: hangyeol
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: K-Parser: 한국어 문법 구조 기반 에이전트 실행 그래프 컴파일러
|
|
5
|
+
Author-email: "sunghoon.kim" <sunghoon.kim@aigensciences.com>
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Keywords: korean,parser,nlp,intent-graph,dependency-parsing,한국어
|
|
8
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
9
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
10
|
+
Classifier: Natural Language :: Korean
|
|
11
|
+
Classifier: Topic :: Text Processing :: Linguistic
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Requires-Python: >=3.11
|
|
14
|
+
Description-Content-Type: text/markdown
|
|
15
|
+
License-File: LICENSE
|
|
16
|
+
Requires-Dist: kiwipiepy>=0.23.1
|
|
17
|
+
Requires-Dist: pyyaml>=6.0
|
|
18
|
+
Requires-Dist: jsonschema>=4.23
|
|
19
|
+
Requires-Dist: numpy>=1.26
|
|
20
|
+
Provides-Extra: parser
|
|
21
|
+
Requires-Dist: stanza>=1.9; extra == "parser"
|
|
22
|
+
Provides-Extra: llm
|
|
23
|
+
Requires-Dist: anthropic>=0.40; extra == "llm"
|
|
24
|
+
Provides-Extra: dev
|
|
25
|
+
Requires-Dist: pytest>=8.0; extra == "dev"
|
|
26
|
+
Requires-Dist: pytest-cov; extra == "dev"
|
|
27
|
+
Requires-Dist: build>=1.0; extra == "dev"
|
|
28
|
+
Requires-Dist: twine>=5.0; extra == "dev"
|
|
29
|
+
Provides-Extra: mcp
|
|
30
|
+
Requires-Dist: mcp>=1.0; extra == "mcp"
|
|
31
|
+
Provides-Extra: repl
|
|
32
|
+
Requires-Dist: prompt_toolkit>=3.0; extra == "repl"
|
|
33
|
+
Dynamic: license-file
|
|
34
|
+
|
|
35
|
+
# 한결 K-Parser
|
|
36
|
+
|
|
37
|
+
> 한국어 발화를 **에이전트 실행 그래프(의도그래프)**로 컴파일하는 한국어 문법 기반 파서.
|
|
38
|
+
|
|
39
|
+
`"CSV로 논문을 찾아서 정리해줘"` 같은 한 문장을, LLM 없이 한국어 문법 구조만으로
|
|
40
|
+
실행 가능한 도구 호출 DAG로 변환한다.
|
|
41
|
+
|
|
42
|
+
```json
|
|
43
|
+
{
|
|
44
|
+
"발화": "CSV로 논문을 찾아서 정리해줘",
|
|
45
|
+
"노드": [
|
|
46
|
+
{"번호": "n1", "도구": "검색", "술어": "찾아서", "인자": {"대상": "논문"}},
|
|
47
|
+
{"번호": "n2", "도구": "요약", "술어": "정리해줘",
|
|
48
|
+
"인자": {"출력형식": "CSV", "대상": "$n1.출력"}}
|
|
49
|
+
],
|
|
50
|
+
"간선": [{"출발": "n1", "도착": "n2", "유형": "선행조건"}],
|
|
51
|
+
"불확실성": []
|
|
52
|
+
}
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
`찾아서`(검색) → `정리해줘`(요약) 두 술어를 노드로, "논문"을 검색 대상으로, "CSV"를
|
|
56
|
+
요약의 출력형식으로 배정하고, `$n1.출력`으로 노드 간 데이터 흐름을 잇는다.
|
|
57
|
+
|
|
58
|
+
## 설계 원칙
|
|
59
|
+
|
|
60
|
+
- **결정론 우선** — 형태소·조사·격틀(세종 동사 사전 계열)만으로 파싱한다. LLM은
|
|
61
|
+
실패한 경우의 *복원* 경로(opt-in)일 뿐, 정상 경로에 개입하지 않는다.
|
|
62
|
+
- **드롭/예외 없음·정직성** — 확신이 없는 배정도 버리지 않고 `불확실성` 배열에
|
|
63
|
+
근거와 함께 남긴다. 선택제약 위반·의미부류 미분류도 침묵하지 않고 신호로 표시한다.
|
|
64
|
+
- **DAG 불변** — 노드ID(`n1`), 노드 간 참조(`$nN.출력`) 형식은 안정 계약.
|
|
65
|
+
- **완전 한글화** — 모듈·함수·필드·테스트까지 한글 식별자(고유명사·3rd-party
|
|
66
|
+
API 표면 제외). `tests/test_식별자_한글.py`가 AST로 강제한다.
|
|
67
|
+
|
|
68
|
+
## 설치
|
|
69
|
+
|
|
70
|
+
요구사항: Python ≥ 3.11
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
python -m venv .venv && source .venv/bin/activate
|
|
74
|
+
pip install -e . # 코어 (kiwipiepy, pyyaml, jsonschema, numpy)
|
|
75
|
+
pip install -e '.[parser]' # + Stanza 의존구문분석 (선택)
|
|
76
|
+
pip install -e '.[llm]' # + anthropic (LLM 복원, 선택)
|
|
77
|
+
pip install -e '.[mcp]' # + mcp (외부 에이전트 연결, 선택)
|
|
78
|
+
pip install -e '.[repl]' # + prompt_toolkit (대화 REPL 편의, 선택)
|
|
79
|
+
pip install -e '.[dev]' # + pytest
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## 빠른 시작
|
|
83
|
+
|
|
84
|
+
### 파이썬 API
|
|
85
|
+
|
|
86
|
+
```python
|
|
87
|
+
from 한결파서 import 파싱, 파싱_json
|
|
88
|
+
|
|
89
|
+
그래프 = 파싱("논문을 요약해줘")
|
|
90
|
+
print(그래프.노드들[0].도구) # → '요약'
|
|
91
|
+
|
|
92
|
+
# JSON 문자열로 바로:
|
|
93
|
+
print(파싱_json("CSV로 논문을 찾아서 정리해줘", 들여쓰기=2))
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
`파싱()` 시그니처:
|
|
97
|
+
|
|
98
|
+
```python
|
|
99
|
+
파싱(발화: str,
|
|
100
|
+
엄격: bool = False, # True면 불확실성 발생 시 예외
|
|
101
|
+
의존파서사용: bool = True, # Stanza UD 보강 (미설치 시 자동 우회)
|
|
102
|
+
llm복원사용: bool = False, # 실패 노드 LLM 복원 (ANTHROPIC_API_KEY 필요)
|
|
103
|
+
예시수: int = 3) -> 의도그래프
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### 명령줄 (CLI)
|
|
107
|
+
|
|
108
|
+
설치 시 `한결` 명령이 등록된다 (또는 `python -m 한결런타임.cli`):
|
|
109
|
+
|
|
110
|
+
```bash
|
|
111
|
+
한결 파싱 "논문을 요약해줘" # 파싱만 (실행 안 함)
|
|
112
|
+
한결 실행 "논문을 요약해줘" # 파싱 후 실제 도구 실행 (샌드박스 ./한결_출력)
|
|
113
|
+
한결 대화 # 발화를 한 줄씩 받아 실행하는 대화형 REPL
|
|
114
|
+
한결 # 인자 없이 실행해도 대화 루프
|
|
115
|
+
한결 연결 --목록 # 등록된 도구를 MCP 커넥터로
|
|
116
|
+
한결 연결 --마법사 # 대화형 마법사로 도구↔서버 연결 등록
|
|
117
|
+
한결 연결 --발견 <서버> # MCP 서버가 노출하는 도구를 자동 발견해 목록 출력
|
|
118
|
+
|
|
119
|
+
# 스킬 브리지 스크립트도 동일 동작:
|
|
120
|
+
python skills/한결/scripts/한결파싱.py "논문을 요약해줘" --들여쓰기
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
`실행`·`대화`의 파일 출력은 기본적으로 샌드박스 디렉터리 `./한결_출력`로
|
|
124
|
+
제한된다(`--샌드박스`로 변경). 요약·번역 등 생성형 도구는 연결이 없으면 실행 시
|
|
125
|
+
"연결된 에이전트 없음" 에러가 나며, `한결 연결 --마법사` 또는 루트의
|
|
126
|
+
[`도구연결.예시.yaml`](도구연결.예시.yaml)을 `도구연결.yaml`로 복사해 등록한다.
|
|
127
|
+
생성형 도구는 `mcp` SDK 없이 로컬 셸 명령으로도 연결할 수 있다(`셸명령들` 섹션) —
|
|
128
|
+
도구 인자는 stdin-JSON으로 들어가고 stdout이 결과로 돌아온다.
|
|
129
|
+
생성형 도구는 원격 HTTP 끝점으로도 연결할 수 있다(`http끝점들` 섹션) —
|
|
130
|
+
`POST {url}/{도구명}` 으로 인자를 JSON 본문에 실어 보내고 응답 본문이 결과로 돌아온다.
|
|
131
|
+
`한결 연결 --마법사`는 서버가 이미 등록돼 있으면 발견된 도구 목록에서 번호로
|
|
132
|
+
고를 수 있어 서버측 도구명을 손으로 외울 필요가 없다.
|
|
133
|
+
|
|
134
|
+
## 출력 구조 (의도그래프)
|
|
135
|
+
|
|
136
|
+
| 필드 | 의미 |
|
|
137
|
+
|---|---|
|
|
138
|
+
| `발화` | 원본 입력 문장 |
|
|
139
|
+
| `실행방식` | `즉시` 등 — 그래프 실행 전략 |
|
|
140
|
+
| `노드` | 도구 호출 단위. `번호`(nN)·`도구`·`술어`(표면형)·`인자`(역할→값 dict) |
|
|
141
|
+
| `간선` | 노드 간 의존. `출발`·`도착`·`유형`(`선행조건` 등) |
|
|
142
|
+
| `불확실성` | 확신 못 한 배정의 근거 목록 — 위반·미분류·미등록 신호 포함 |
|
|
143
|
+
|
|
144
|
+
`인자` 값이 `$n1.출력`이면 앞선 노드의 출력을 참조한다(논항 생략 보충).
|
|
145
|
+
|
|
146
|
+
## 처리 파이프라인 (`한결파서/`)
|
|
147
|
+
|
|
148
|
+
| 단계 | 모듈 | 역할 |
|
|
149
|
+
|---|---|---|
|
|
150
|
+
| 1 형태소분석 | `형태소분석.py` | kiwipiepy 형태소 분해 |
|
|
151
|
+
| 2 어절묶기 | `어절묶기.py` | SOV 어절 묶음 구성 |
|
|
152
|
+
| 3 역할배정 | `역할배정.py` | 조사 → 격(대상·도구·출발점…) |
|
|
153
|
+
| 4 의존파서 | `의존파서.py` | Stanza UD 보강 (선택) |
|
|
154
|
+
| 5 격틀조회 | `격틀조회.py` | 술어 격틀 조회·인자정렬·선택제약 검사 |
|
|
155
|
+
| 6 의도그래프구성 | `의도그래프구성.py` | 술어→노드, 논항 귀속, 간선 연결 (DAG) |
|
|
156
|
+
| 7 검증 | `검증.py` | 순환·미등록 도구·필수 인자 점검 |
|
|
157
|
+
| 8 LLM복원 | `llm복원.py` | 실패 노드 복원 (opt-in, anthropic) |
|
|
158
|
+
|
|
159
|
+
핵심 휴리스틱: **핵어후행 원리**(한국어 논항은 자기 술어에 선행) + **격틀 인가**
|
|
160
|
+
(논항을 "가장 가까운 후행 술어 중 그 역할을 인가하는 첫 술어"에 귀속). 인가 술어가
|
|
161
|
+
없으면 현행 위치를 유지하고 불확실성에 기록한다(silent drop 금지).
|
|
162
|
+
|
|
163
|
+
## 어휘집 (`어휘집/`)
|
|
164
|
+
|
|
165
|
+
| 파일 | 내용 |
|
|
166
|
+
|---|---|
|
|
167
|
+
| `술어.yaml` | 한국어 술어 기본형 → 도구 별칭 |
|
|
168
|
+
| `격틀.yaml` | 도구별 의미역 슬롯(필수/선택) + 허용 조사 + 선택제약 |
|
|
169
|
+
| `조사.yaml` | 조사 → 격 매핑 |
|
|
170
|
+
| `의미역.yaml` | 의미역 ↔ 한글 역할, 국립국어원 표준 약호 |
|
|
171
|
+
| `의미부류.yaml` | 세종 명사 의미부류 타크소노미 + 선택제약 온톨로지 |
|
|
172
|
+
|
|
173
|
+
선택제약은 세종 명사 의미부류 위계로 소프트하게 강제한다 — 위반 시 모호도↑+경고,
|
|
174
|
+
미분류 시 저강도 "검사 불가" 신호, 통과는 그대로(어느 경우에도 역할을 드롭하지 않음).
|
|
175
|
+
|
|
176
|
+
## 런타임 (`한결런타임/`)
|
|
177
|
+
|
|
178
|
+
의도그래프를 실제로 실행하는 계층:
|
|
179
|
+
|
|
180
|
+
- `실행엔진.py` — DAG 위상 정렬 후 노드별 도구 호출, `$nN.출력` 데이터 전달
|
|
181
|
+
- `도구레지스트리.py` / `검색도구.py` / `분석도구.py` / `파일도구.py` — 도구 구현
|
|
182
|
+
- `mcp연결.py` / `연결설정.py` — 한결 도구를 MCP 커넥터로 노출/연결
|
|
183
|
+
- `cli.py` — `한결 파싱|실행|연결` 진입점
|
|
184
|
+
|
|
185
|
+
## 테스트
|
|
186
|
+
|
|
187
|
+
```bash
|
|
188
|
+
.venv/bin/python -m pytest tests/ -q # 전체 (265 passed, 2 skipped)
|
|
189
|
+
.venv/bin/python -m pytest -m 'not slow' -q # 벤치마크 제외
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
`2 skipped`는 LLM 복원의 실제 API 검증 — `ANTHROPIC_API_KEY` 설정 후
|
|
193
|
+
`pytest tests/test_llm복원.py -v`로 해소된다.
|
|
194
|
+
|
|
195
|
+
주요 테스트: `test_논항귀속`(노드·역할 배정) · `test_의미부류`(선택제약) ·
|
|
196
|
+
`test_격틀스키마` · `test_검증` · `test_식별자_한글`(한글 식별자 강제) ·
|
|
197
|
+
`test_실행통합`(런타임).
|
|
198
|
+
|
|
199
|
+
## 프로젝트 구조
|
|
200
|
+
|
|
201
|
+
```
|
|
202
|
+
한결파서/ 파싱 코어 (형태소 → 의도그래프)
|
|
203
|
+
한결런타임/ 실행엔진 + 도구 + MCP + CLI
|
|
204
|
+
어휘집/ 술어·격틀·조사·의미역·의미부류 YAML
|
|
205
|
+
tests/ pytest 스위트 (23개 파일)
|
|
206
|
+
examples/ 기본예시.py
|
|
207
|
+
skills/한결/ 에이전트 스킬 브리지 (한결파싱.py 등)
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
## 개발 워크플로 / 협업 하네스
|
|
211
|
+
|
|
212
|
+
기여 규칙·승인 게이트·세션 협업 규약은 별도 문서에 있다:
|
|
213
|
+
|
|
214
|
+
- **`AGENTS.md`** — 작업 규칙, 승인 게이트, 검증 명령 (공유 규칙의 단일 출처)
|
|
215
|
+
- **`CLAUDE.md`** — Claude Code 진입점, 세션 리추얼, 네이티브 프리미티브
|
|
216
|
+
- **`WORKFLOW.md`** — 계약→플랜→실행 파이프라인, 슬라이스 라우팅
|
|
217
|
+
- **`.agent/`** — 슬라이스별 상태(`status/`)·계약(`contracts/`)·플랜(`plans/`)
|