Metadata-Version: 2.4
Name: hangyeol
Version: 0.1.0
Summary: K-Parser: 한국어 문법 구조 기반 에이전트 실행 그래프 컴파일러
Author-email: "sunghoon.kim" <sunghoon.kim@aigensciences.com>
License-Expression: MIT
Keywords: korean,parser,nlp,intent-graph,dependency-parsing,한국어
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Natural Language :: Korean
Classifier: Topic :: Text Processing :: Linguistic
Classifier: Intended Audience :: Developers
Requires-Python: >=3.11
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: kiwipiepy>=0.23.1
Requires-Dist: pyyaml>=6.0
Requires-Dist: jsonschema>=4.23
Requires-Dist: numpy>=1.26
Provides-Extra: parser
Requires-Dist: stanza>=1.9; extra == "parser"
Provides-Extra: llm
Requires-Dist: anthropic>=0.40; extra == "llm"
Provides-Extra: dev
Requires-Dist: pytest>=8.0; extra == "dev"
Requires-Dist: pytest-cov; extra == "dev"
Requires-Dist: build>=1.0; extra == "dev"
Requires-Dist: twine>=5.0; extra == "dev"
Provides-Extra: mcp
Requires-Dist: mcp>=1.0; extra == "mcp"
Provides-Extra: repl
Requires-Dist: prompt_toolkit>=3.0; extra == "repl"
Dynamic: license-file

# 한결 K-Parser

> 한국어 발화를 **에이전트 실행 그래프(의도그래프)**로 컴파일하는 한국어 문법 기반 파서.

`"CSV로 논문을 찾아서 정리해줘"` 같은 한 문장을, LLM 없이 한국어 문법 구조만으로
실행 가능한 도구 호출 DAG로 변환한다.

```json
{
  "발화": "CSV로 논문을 찾아서 정리해줘",
  "노드": [
    {"번호": "n1", "도구": "검색", "술어": "찾아서", "인자": {"대상": "논문"}},
    {"번호": "n2", "도구": "요약", "술어": "정리해줘",
     "인자": {"출력형식": "CSV", "대상": "$n1.출력"}}
  ],
  "간선": [{"출발": "n1", "도착": "n2", "유형": "선행조건"}],
  "불확실성": []
}
```

`찾아서`(검색) → `정리해줘`(요약) 두 술어를 노드로, "논문"을 검색 대상으로, "CSV"를
요약의 출력형식으로 배정하고, `$n1.출력`으로 노드 간 데이터 흐름을 잇는다.

## 설계 원칙

- **결정론 우선** — 형태소·조사·격틀(세종 동사 사전 계열)만으로 파싱한다. LLM은
  실패한 경우의 *복원* 경로(opt-in)일 뿐, 정상 경로에 개입하지 않는다.
- **드롭/예외 없음·정직성** — 확신이 없는 배정도 버리지 않고 `불확실성` 배열에
  근거와 함께 남긴다. 선택제약 위반·의미부류 미분류도 침묵하지 않고 신호로 표시한다.
- **DAG 불변** — 노드ID(`n1`), 노드 간 참조(`$nN.출력`) 형식은 안정 계약.
- **완전 한글화** — 모듈·함수·필드·테스트까지 한글 식별자(고유명사·3rd-party
  API 표면 제외). `tests/test_식별자_한글.py`가 AST로 강제한다.

## 설치

요구사항: Python ≥ 3.11

```bash
python -m venv .venv && source .venv/bin/activate
pip install -e .            # 코어 (kiwipiepy, pyyaml, jsonschema, numpy)
pip install -e '.[parser]'  # + Stanza 의존구문분석 (선택)
pip install -e '.[llm]'     # + anthropic (LLM 복원, 선택)
pip install -e '.[mcp]'     # + mcp (외부 에이전트 연결, 선택)
pip install -e '.[repl]'    # + prompt_toolkit (대화 REPL 편의, 선택)
pip install -e '.[dev]'     # + pytest
```

## 빠른 시작

### 파이썬 API

```python
from 한결파서 import 파싱, 파싱_json

그래프 = 파싱("논문을 요약해줘")
print(그래프.노드들[0].도구)          # → '요약'

# JSON 문자열로 바로:
print(파싱_json("CSV로 논문을 찾아서 정리해줘", 들여쓰기=2))
```

`파싱()` 시그니처:

```python
파싱(발화: str,
     엄격: bool = False,          # True면 불확실성 발생 시 예외
     의존파서사용: bool = True,    # Stanza UD 보강 (미설치 시 자동 우회)
     llm복원사용: bool = False,   # 실패 노드 LLM 복원 (ANTHROPIC_API_KEY 필요)
     예시수: int = 3) -> 의도그래프
```

### 명령줄 (CLI)

설치 시 `한결` 명령이 등록된다 (또는 `python -m 한결런타임.cli`):

```bash
한결 파싱 "논문을 요약해줘"            # 파싱만 (실행 안 함)
한결 실행 "논문을 요약해줘"            # 파싱 후 실제 도구 실행 (샌드박스 ./한결_출력)
한결 대화                              # 발화를 한 줄씩 받아 실행하는 대화형 REPL
한결                                   # 인자 없이 실행해도 대화 루프
한결 연결 --목록                       # 등록된 도구를 MCP 커넥터로
한결 연결 --마법사                     # 대화형 마법사로 도구↔서버 연결 등록
한결 연결 --발견 <서버>                 # MCP 서버가 노출하는 도구를 자동 발견해 목록 출력

# 스킬 브리지 스크립트도 동일 동작:
python skills/한결/scripts/한결파싱.py "논문을 요약해줘" --들여쓰기
```

`실행`·`대화`의 파일 출력은 기본적으로 샌드박스 디렉터리 `./한결_출력`로
제한된다(`--샌드박스`로 변경). 요약·번역 등 생성형 도구는 연결이 없으면 실행 시
"연결된 에이전트 없음" 에러가 나며, `한결 연결 --마법사` 또는 루트의
[`도구연결.예시.yaml`](도구연결.예시.yaml)을 `도구연결.yaml`로 복사해 등록한다.
생성형 도구는 `mcp` SDK 없이 로컬 셸 명령으로도 연결할 수 있다(`셸명령들` 섹션) —
도구 인자는 stdin-JSON으로 들어가고 stdout이 결과로 돌아온다.
생성형 도구는 원격 HTTP 끝점으로도 연결할 수 있다(`http끝점들` 섹션) —
`POST {url}/{도구명}` 으로 인자를 JSON 본문에 실어 보내고 응답 본문이 결과로 돌아온다.
`한결 연결 --마법사`는 서버가 이미 등록돼 있으면 발견된 도구 목록에서 번호로
고를 수 있어 서버측 도구명을 손으로 외울 필요가 없다.

## 출력 구조 (의도그래프)

| 필드 | 의미 |
|---|---|
| `발화` | 원본 입력 문장 |
| `실행방식` | `즉시` 등 — 그래프 실행 전략 |
| `노드` | 도구 호출 단위. `번호`(nN)·`도구`·`술어`(표면형)·`인자`(역할→값 dict) |
| `간선` | 노드 간 의존. `출발`·`도착`·`유형`(`선행조건` 등) |
| `불확실성` | 확신 못 한 배정의 근거 목록 — 위반·미분류·미등록 신호 포함 |

`인자` 값이 `$n1.출력`이면 앞선 노드의 출력을 참조한다(논항 생략 보충).

## 처리 파이프라인 (`한결파서/`)

| 단계 | 모듈 | 역할 |
|---|---|---|
| 1 형태소분석 | `형태소분석.py` | kiwipiepy 형태소 분해 |
| 2 어절묶기 | `어절묶기.py` | SOV 어절 묶음 구성 |
| 3 역할배정 | `역할배정.py` | 조사 → 격(대상·도구·출발점…) |
| 4 의존파서 | `의존파서.py` | Stanza UD 보강 (선택) |
| 5 격틀조회 | `격틀조회.py` | 술어 격틀 조회·인자정렬·선택제약 검사 |
| 6 의도그래프구성 | `의도그래프구성.py` | 술어→노드, 논항 귀속, 간선 연결 (DAG) |
| 7 검증 | `검증.py` | 순환·미등록 도구·필수 인자 점검 |
| 8 LLM복원 | `llm복원.py` | 실패 노드 복원 (opt-in, anthropic) |

핵심 휴리스틱: **핵어후행 원리**(한국어 논항은 자기 술어에 선행) + **격틀 인가**
(논항을 "가장 가까운 후행 술어 중 그 역할을 인가하는 첫 술어"에 귀속). 인가 술어가
없으면 현행 위치를 유지하고 불확실성에 기록한다(silent drop 금지).

## 어휘집 (`어휘집/`)

| 파일 | 내용 |
|---|---|
| `술어.yaml` | 한국어 술어 기본형 → 도구 별칭 |
| `격틀.yaml` | 도구별 의미역 슬롯(필수/선택) + 허용 조사 + 선택제약 |
| `조사.yaml` | 조사 → 격 매핑 |
| `의미역.yaml` | 의미역 ↔ 한글 역할, 국립국어원 표준 약호 |
| `의미부류.yaml` | 세종 명사 의미부류 타크소노미 + 선택제약 온톨로지 |

선택제약은 세종 명사 의미부류 위계로 소프트하게 강제한다 — 위반 시 모호도↑+경고,
미분류 시 저강도 "검사 불가" 신호, 통과는 그대로(어느 경우에도 역할을 드롭하지 않음).

## 런타임 (`한결런타임/`)

의도그래프를 실제로 실행하는 계층:

- `실행엔진.py` — DAG 위상 정렬 후 노드별 도구 호출, `$nN.출력` 데이터 전달
- `도구레지스트리.py` / `검색도구.py` / `분석도구.py` / `파일도구.py` — 도구 구현
- `mcp연결.py` / `연결설정.py` — 한결 도구를 MCP 커넥터로 노출/연결
- `cli.py` — `한결 파싱|실행|연결` 진입점

## 테스트

```bash
.venv/bin/python -m pytest tests/ -q          # 전체 (265 passed, 2 skipped)
.venv/bin/python -m pytest -m 'not slow' -q   # 벤치마크 제외
```

`2 skipped`는 LLM 복원의 실제 API 검증 — `ANTHROPIC_API_KEY` 설정 후
`pytest tests/test_llm복원.py -v`로 해소된다.

주요 테스트: `test_논항귀속`(노드·역할 배정) · `test_의미부류`(선택제약) ·
`test_격틀스키마` · `test_검증` · `test_식별자_한글`(한글 식별자 강제) ·
`test_실행통합`(런타임).

## 프로젝트 구조

```
한결파서/      파싱 코어 (형태소 → 의도그래프)
한결런타임/    실행엔진 + 도구 + MCP + CLI
어휘집/        술어·격틀·조사·의미역·의미부류 YAML
tests/         pytest 스위트 (23개 파일)
examples/      기본예시.py
skills/한결/   에이전트 스킬 브리지 (한결파싱.py 등)
```

## 개발 워크플로 / 협업 하네스

기여 규칙·승인 게이트·세션 협업 규약은 별도 문서에 있다:

- **`AGENTS.md`** — 작업 규칙, 승인 게이트, 검증 명령 (공유 규칙의 단일 출처)
- **`CLAUDE.md`** — Claude Code 진입점, 세션 리추얼, 네이티브 프리미티브
- **`WORKFLOW.md`** — 계약→플랜→실행 파이프라인, 슬라이스 라우팅
- **`.agent/`** — 슬라이스별 상태(`status/`)·계약(`contracts/`)·플랜(`plans/`)
