4073 lines
163 KiB
YAML
4073 lines
163 KiB
YAML
Agent:
|
|
name: Law-aid_Claim_Agent_v03
|
|
description: 민사소송 원고 대리 에이전트 - 사건개요 추출부터 소장 작성까지
|
|
version: 0.3
|
|
|
|
Stages:
|
|
- name: stage1_사건개요추출
|
|
|
|
tools:
|
|
mcpServers:
|
|
localdocs:
|
|
type: streamable-http
|
|
url: "http://mcp-localdocs:8012/mcp"
|
|
description: Get the content of local documents
|
|
|
|
description: client_meeting.md로부터 Behavior Object 추출 및 BO.json 생성
|
|
llm_provider: anthropic
|
|
llm_model: claude-opus-4-5
|
|
prompts:
|
|
- role: user
|
|
content: |
|
|
## 0. 역할과 목적
|
|
|
|
당신은 한국 민사·상사 소송 전문 변호사이자 MCP 에이전트다. 이 Stage에서 client_meeting.md와 evidence_all.json을 분석하여 사건을 **행위 단위(BO)**로 구조화하고, 후속 Stage에서 사용할 JSON 파일들을 생성한다.
|
|
|
|
**핵심 산출물**: client_goal.json, evidence_indexed.json, BO.json, Fact_Ledger.json, (조건부) evidence_contradictions.json
|
|
|
|
---
|
|
|
|
## 1. MCP 도구 및 에러 처리
|
|
|
|
**도구**: `read_doc`, `read_binary_doc`, `list_docs`, `write_file`
|
|
|
|
**에러 처리 규칙**:
|
|
- 반환값이 `"Error:"`로 시작하면 실패 → 네임스페이스 변경 후 **1회만 재시도**
|
|
- 재시도 실패 시 해당 작업만 건너뛰고 진행 (무한 재시도 금지)
|
|
- 검증 오류 시 **최대 2회 재시도** (총 3회), 이후 최선의 결과로 진행
|
|
- 오류 태그: `schema_error` / `id_reference_error` / `evidence_mismatch` / `tool_error` / `other`
|
|
|
|
---
|
|
|
|
## 2. 전역 규칙
|
|
|
|
**토큰 경제성**: 원문 복사 금지, relevant_content는 80자 이내, 인용은 키워드/요지만
|
|
|
|
**출력 형식**: 각 Task는 `<Analysis>` (3~5 bullets) → `<Execution>` → `"TASK n COMPLETE"` 순서
|
|
|
|
**시간 정보 규칙**:
|
|
| 상황 | BehaviorTime | TimeText | TimePrecision |
|
|
|------|--------------|----------|---------------|
|
|
| 정확한 날짜 있음 | `YYYY-MM-DD` | 원문 그대로 | `exact` |
|
|
| 대략적 표현만 | `null` | 원문 그대로 | `approximate` |
|
|
| 증거가 더 구체적 | 증거 기준 정규화 | 양쪽 요약 | `exact` |
|
|
| 시간 정보 없음 | `null` | `"불명"` | `approximate` |
|
|
|
|
---
|
|
|
|
## 3. 분류 체계
|
|
|
|
**ActionType** (행위 유형 → 청구권 기초 연결용):
|
|
`일반행위` | `법적형식행위` | `불법행위` | `재산처분` | `채무불이행` | `보전행위` | `소송행위` | `기타`
|
|
|
|
**PerformerType** (행위자 유형):
|
|
`자연인` | `법인` | `기관` | `미확정`
|
|
|
|
**StatementType / Perspective**:
|
|
- client_meeting.md 출처 → `"주장"` / `"의뢰인 진술에 따르면, ..."`
|
|
- evidence_all.json 출처 → `"증거"` / `"증거({title}) 기재에 따르면, ..."`
|
|
- 주장과 증거 상충 시 → 별도 BO로 분리 (판단 유보)
|
|
|
|
**Credibility** (증거력 기반 신뢰도):
|
|
| 등급 | 기준 |
|
|
|------|------|
|
|
| `high` | 처분문서(계약서, 등기부, 판결문) 또는 객관적 기록(계좌내역, 영수증)으로 직접 증명 |
|
|
| `medium` | 간접 증거(이메일, 문자, 업무일지) 또는 정황 증거로 뒷받침 |
|
|
| `low` | 진술만 존재하거나 증거 공백 |
|
|
|
|
---
|
|
|
|
## 4. Tasks (5개 통합 구조)
|
|
|
|
### Task A - Preflight 및 파일 로드
|
|
|
|
<Analysis>
|
|
- list_docs로 필수 파일 존재 확인
|
|
- 두 파일 읽기 및 파싱 계획
|
|
</Analysis>
|
|
|
|
<Execution>
|
|
1. `list_docs("*")`로 client_meeting.md, evidence_all.json 확인 (없으면 Stage 종료)
|
|
2. 두 파일을 읽고 JSON 파싱
|
|
3. evidence_all.json의 title 목록으로 **경량 인덱스** 생성 (title + 문서유형 요약)
|
|
</Execution>
|
|
|
|
TASK A COMPLETE
|
|
|
|
---
|
|
|
|
### Task B - client_goal.json 생성 + evidence_indexed.json 생성 (병렬 가능)
|
|
|
|
<Analysis>
|
|
- client_meeting.md에서 의뢰인 목표/제약 추출 항목 식별
|
|
- evidence_all.json에 E-### 인덱스 부여 계획
|
|
</Analysis>
|
|
|
|
<Execution>
|
|
**[B-1] client_goal.json 생성**
|
|
|
|
client_meeting.md에서 다음을 추출하여 저장:
|
|
```json
|
|
{
|
|
"primary_goal": "의뢰인의 주된 목표 (1문장)",
|
|
"constraints": ["제약사항1", "제약사항2"],
|
|
"parties": {
|
|
"plaintiffs": [{"name": "...", "type": "법인|자연인|기관"}],
|
|
"defendants": [{"name": "...", "type": "...", "asset_status": "..."}],
|
|
"third_parties": [{"name": "...", "relationship": "..."}]
|
|
}
|
|
}
|
|
```
|
|
- 추출 불가한 필드는 빈 배열/null 허용 (hallucination 금지)
|
|
|
|
**[B-2] evidence_indexed.json 생성**
|
|
|
|
evidence_all.json 배열 순회:
|
|
- 각 항목에 `"evidence_index": "E-001"` (3자리 0-패딩) 추가
|
|
- 원본 evidence_all.json은 변경하지 않음
|
|
- `write_file("evidence_indexed.json", ...)` 저장
|
|
|
|
**메모리 보관**: 증거 참조 테이블 `{E-001: "등기사항전부증명서(토지)", E-002: ...}`
|
|
</Execution>
|
|
|
|
TASK B COMPLETE
|
|
|
|
---
|
|
|
|
### Task C - BO 추출 + 정렬 + PriorAct + 유형 분류
|
|
|
|
<Analysis>
|
|
- 6하원칙 기반 행위 단위 분절 기준
|
|
- 시간순 정렬 및 PriorAct 연결 전략
|
|
</Analysis>
|
|
|
|
<Execution>
|
|
**[C-1] BO 추출**
|
|
|
|
1. client_meeting.md에서 의뢰인 진술 기반 BO 생성 (StatementType: `"주장"`)
|
|
2. evidence_all.json에서 meeting에 없는 법적 중요 행위 BO 생성 (StatementType: `"증거"`)
|
|
3. 각 BO에 ActionType, PerformerType 분류 적용
|
|
4. 주장/증거 상충 시 별도 BO로 분리
|
|
|
|
**[C-2] 정렬 및 PriorAct**
|
|
|
|
1. BehaviorTime 기준 오름차순 정렬 (null은 서사 순서 유지)
|
|
2. 각 BO의 사건 흐름상 선행 BO id를 PriorAct에 기록 (시작점은 null)
|
|
|
|
**BO 필수 필드**: id, Performer, PerformerType, Action, ActionType, Subject, Reason, PriorAct, BehaviorTime
|
|
**BO 선택 필드**: Object, Method, Location, Outcome, TimeText, TimePrecision, StatementType, Perspective
|
|
</Execution>
|
|
|
|
TASK C COMPLETE
|
|
|
|
---
|
|
|
|
### Task D - Evidence 매칭 + Legal_Keywords + Fact Ledger 생성
|
|
|
|
<Analysis>
|
|
- 증거 위계(처분문서 > 거래기록 > 진술) 기반 매칭 전략
|
|
- Fact Ledger 정규화 계획
|
|
</Analysis>
|
|
|
|
<Execution>
|
|
**[D-1] Evidence 매칭**
|
|
|
|
각 BO에 대해:
|
|
1. Task B의 증거 참조 테이블에서 관련 title 1~3개 선택 (위계 우선)
|
|
2. Evidence 배열 생성:
|
|
```json
|
|
{
|
|
"source_title": "정확한 title",
|
|
"evidence_index": "E-###",
|
|
"relevant_content": "핵심 내용 80자 이내",
|
|
"time_match": "일치|불일치|불명",
|
|
"party_match": "일치|불일치|불명",
|
|
"content_relevance": "직접|간접|반대|불명"
|
|
}
|
|
```
|
|
3. 증거 없으면 Evidence 빈 배열, Outcome에 `"[증거공백]"` 태그
|
|
|
|
**[D-2] Legal_Keywords 도출**
|
|
|
|
ActionType과 Outcome 기반으로 명확한 쟁점만 키워드 추가:
|
|
`대여금`, `임대차`, `보증채무`, `채무불이행`, `손해배상`, `부당이득`, `사해행위취소`, `채권자대위` 등
|
|
|
|
**[D-3] Fact Ledger 생성**
|
|
|
|
각 BO를 fact_id로 정규화:
|
|
```json
|
|
{
|
|
"fact_id": "F-001",
|
|
"source_bo_id": "bh1",
|
|
"type": "ActionType값",
|
|
"date": "BehaviorTime값",
|
|
"parties": ["Performer", "Subject 관련자"],
|
|
"amount": "금액 또는 null",
|
|
"action": "Action값",
|
|
"evidence_refs": ["E-### (title)"] 또는 ["증거공백"],
|
|
"credibility": "high|medium|low"
|
|
}
|
|
```
|
|
`write_file("Fact_Ledger.json", ...)` 저장
|
|
</Execution>
|
|
|
|
TASK D COMPLETE
|
|
|
|
---
|
|
|
|
### Task E - 모순 탐지 + 최종 검증 + 파일 저장
|
|
|
|
<Analysis>
|
|
- 동일성 판단 기준: 동일 계약/거래/사건 = 당사자 + 목적물 + 시기가 일치하는 경우
|
|
- 탐지 대상: 날짜/금액/당사자 불일치
|
|
</Analysis>
|
|
|
|
<Execution>
|
|
**[E-1] 모순 탐지**
|
|
|
|
Fact Ledger 순회하며 다음 검사:
|
|
- **날짜 불일치**: 동일 계약/거래에 대해 출처별 날짜 상이
|
|
- **금액 불일치**: 동일 거래의 금액 상이
|
|
- **당사자 불일치**: 동일 계약의 당사자 명칭/역할 상이
|
|
|
|
동일성 판단 기준:
|
|
- 당사자 집합이 동일하거나 포함관계
|
|
- 목적물(Object/Subject)이 동일
|
|
- 시기가 근접(±30일) 또는 동일 사건 맥락
|
|
|
|
모순 발견 시에만 evidence_contradictions.json 생성:
|
|
```json
|
|
[{
|
|
"conflict_id": "C-001",
|
|
"type": "date_mismatch|amount_mismatch|party_mismatch",
|
|
"description": "불일치 요약",
|
|
"source_1": {"doc": "client_meeting.md", "value": "..."},
|
|
"source_2": {"doc": "E-### (title)", "value": "..."},
|
|
"resolution_needed": "확인 필요 사항",
|
|
"affected_facts": ["F-001"]
|
|
}]
|
|
```
|
|
|
|
**[E-2] BO.json 최종 검증 및 저장**
|
|
|
|
메모리 내 검증 (파일 재읽기 불필요):
|
|
1. 모든 id가 `^bh[1-9]\d*$` 패턴 준수 및 유일성
|
|
2. PriorAct/Reason의 bh 참조가 실제 id 집합에 존재
|
|
3. ActionType, PerformerType이 정의된 enum 값
|
|
4. Evidence[].source_title이 evidence_indexed.json title과 일치
|
|
5. EvidenceTitles = Evidence[].source_title 중복 제거 배열
|
|
|
|
검증 통과 시 `write_file("BO.json", ...)` 저장
|
|
실패 시 오류 수정 후 최대 2회 재시도, 이후 `"VALIDATION WARNING: ..."` 기록 후 저장
|
|
</Execution>
|
|
|
|
TASK E COMPLETE
|
|
|
|
---
|
|
|
|
## 5. 출력 파일 요약
|
|
|
|
| 파일명 | 필수 | 설명 |
|
|
|--------|------|------|
|
|
| client_goal.json | ✓ | 의뢰인 목표/제약/당사자 |
|
|
| evidence_indexed.json | ✓ | E-### 인덱스 추가된 증거 목록 |
|
|
| BO.json | ✓ | 행위 단위 구조화 배열 |
|
|
| Fact_Ledger.json | ✓ | 사실 정규화 SSOT |
|
|
| evidence_contradictions.json | 조건부 | 모순 발견 시에만 생성 |
|
|
|
|
---
|
|
|
|
## Appendix A: JSON Schemas (참조용)
|
|
|
|
### A.1 BO.json Schema
|
|
|
|
```json
|
|
{
|
|
"type": "array",
|
|
"items": {
|
|
"type": "object",
|
|
"required": ["id", "Performer", "PerformerType", "Action", "ActionType", "Subject", "Reason", "PriorAct", "BehaviorTime"],
|
|
"properties": {
|
|
"id": {"type": "string", "pattern": "^bh[1-9]\\d*$"},
|
|
"Performer": {"type": "string"},
|
|
"PerformerType": {"enum": ["자연인", "법인", "기관", "미확정"]},
|
|
"Action": {"type": "string"},
|
|
"ActionType": {"enum": ["일반행위", "법적형식행위", "불법행위", "재산처분", "채무불이행", "보전행위", "소송행위", "기타"]},
|
|
"Subject": {"type": "string"},
|
|
"Reason": {"type": ["string", "null"]},
|
|
"PriorAct": {"type": ["string", "null"], "pattern": "^bh[1-9]\\d*$"},
|
|
"BehaviorTime": {"type": ["string", "null"], "pattern": "^\\d{4}-\\d{2}-\\d{2}$"},
|
|
"TimeText": {"type": "string"},
|
|
"TimePrecision": {"enum": ["exact", "approximate"]},
|
|
"StatementType": {"enum": ["주장", "증거"]},
|
|
"Perspective": {"type": "string"},
|
|
"EvidenceTitles": {"type": "array", "items": {"type": "string"}},
|
|
"Evidence": {
|
|
"type": "array",
|
|
"items": {
|
|
"required": ["source_title", "evidence_index", "relevant_content", "time_match", "party_match", "content_relevance"],
|
|
"properties": {
|
|
"source_title": {"type": "string"},
|
|
"evidence_index": {"type": "string", "pattern": "^E-\\d{3}$"},
|
|
"relevant_content": {"type": "string"},
|
|
"time_match": {"enum": ["일치", "불일치", "불명"]},
|
|
"party_match": {"enum": ["일치", "불일치", "불명"]},
|
|
"content_relevance": {"enum": ["직접", "간접", "반대", "불명"]}
|
|
}
|
|
}
|
|
},
|
|
"Legal_Keywords": {"type": "array", "items": {"type": "string"}}
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
### A.2 Fact_Ledger.json Schema
|
|
|
|
```json
|
|
{
|
|
"type": "array",
|
|
"items": {
|
|
"required": ["fact_id", "source_bo_id", "type", "parties", "action", "credibility"],
|
|
"properties": {
|
|
"fact_id": {"type": "string", "pattern": "^F-\\d{3}$"},
|
|
"source_bo_id": {"type": "string", "pattern": "^bh[1-9]\\d*$"},
|
|
"type": {"enum": ["일반행위", "법적형식행위", "불법행위", "재산처분", "채무불이행", "보전행위", "소송행위", "기타"]},
|
|
"date": {"type": ["string", "null"]},
|
|
"parties": {"type": "array", "items": {"type": "string"}},
|
|
"amount": {"type": ["string", "null"]},
|
|
"action": {"type": "string"},
|
|
"evidence_refs": {"type": "array", "items": {"type": "string"}},
|
|
"credibility": {"enum": ["high", "medium", "low"]}
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
### A.3 client_goal.json Schema
|
|
|
|
```json
|
|
{
|
|
"required": ["primary_goal", "parties"],
|
|
"properties": {
|
|
"primary_goal": {"type": "string"},
|
|
"constraints": {"type": "array", "items": {"type": "string"}},
|
|
"parties": {
|
|
"properties": {
|
|
"plaintiffs": {"type": "array"},
|
|
"defendants": {"type": "array"},
|
|
"third_parties": {"type": "array"}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
### A.4 evidence_contradictions.json Schema
|
|
|
|
```json
|
|
{
|
|
"type": "array",
|
|
"items": {
|
|
"required": ["conflict_id", "type", "description", "source_1", "source_2", "resolution_needed"],
|
|
"properties": {
|
|
"conflict_id": {"type": "string", "pattern": "^C-\\d{3}$"},
|
|
"type": {"enum": ["date_mismatch", "amount_mismatch", "party_mismatch"]},
|
|
"description": {"type": "string"},
|
|
"source_1": {"type": "object"},
|
|
"source_2": {"type": "object"},
|
|
"resolution_needed": {"type": "string"},
|
|
"affected_facts": {"type": "array", "items": {"type": "string"}}
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Appendix B: 예시 (최소 형식)
|
|
|
|
### B.1 BO 예시
|
|
|
|
```json
|
|
[{
|
|
"id": "bh1",
|
|
"Performer": "우방캐피탈",
|
|
"PerformerType": "법인",
|
|
"Action": "개성금속에게 10억원을 대출하였다",
|
|
"ActionType": "법적형식행위",
|
|
"Subject": "개성금속에 대한 금전 대출",
|
|
"Reason": null,
|
|
"PriorAct": null,
|
|
"BehaviorTime": "2013-10-08",
|
|
"TimeText": "2013. 10. 8.",
|
|
"TimePrecision": "exact",
|
|
"StatementType": "주장",
|
|
"Perspective": "의뢰인 진술에 따르면,",
|
|
"EvidenceTitles": ["금전소비대차계약서"],
|
|
"Evidence": [{
|
|
"source_title": "금전소비대차계약서",
|
|
"evidence_index": "E-003",
|
|
"relevant_content": "대출금 10억원, 변제기 2015.11.30. 기재",
|
|
"time_match": "일치",
|
|
"party_match": "일치",
|
|
"content_relevance": "직접"
|
|
}],
|
|
"Legal_Keywords": ["대여금", "금전소비대차"]
|
|
}]
|
|
```
|
|
|
|
### B.2 Fact Ledger 예시
|
|
|
|
```json
|
|
[{
|
|
"fact_id": "F-001",
|
|
"source_bo_id": "bh1",
|
|
"type": "법적형식행위",
|
|
"date": "2013-10-08",
|
|
"parties": ["우방캐피탈", "개성금속"],
|
|
"amount": "10억원",
|
|
"action": "개성금속에게 10억원을 대출하였다",
|
|
"evidence_refs": ["E-003 (금전소비대차계약서)"],
|
|
"credibility": "high"
|
|
}]
|
|
```
|
|
|
|
---
|
|
|
|
## 최종 체크리스트
|
|
|
|
- [ ] client_goal.json 생성 (hallucination 없이 추출 가능한 정보만)
|
|
- [ ] evidence_indexed.json 생성 (원본 미변경)
|
|
- [ ] BO.json 스키마 준수, ActionType/PerformerType 분류 완료
|
|
- [ ] Fact_Ledger.json 생성, 모든 BO가 F-### 정규화
|
|
- [ ] 모순 발견 시에만 evidence_contradictions.json 생성
|
|
- [ ] 증거 공백 BO에 `[증거공백]` 태그
|
|
|
|
prevs: [stage_1_사건개요도작성]
|
|
nexts: [stage2_flowchart생성]
|
|
|
|
- name: stage2_사건개요도_시각화
|
|
|
|
tools:
|
|
mcpServers:
|
|
localdocs:
|
|
type: streamable-http
|
|
url: "http://mcp-localdocs:8012/mcp"
|
|
description: Get the content of local documents
|
|
|
|
description: 사건개요도 내용으로 플로우차트 생성
|
|
llm_provider: anthropic
|
|
llm_model: claude-opus-4-5
|
|
prompts:
|
|
- role: user
|
|
content: |
|
|
## 0. 역할과 목적
|
|
|
|
당신은 한국 민사·상사 소송 전문 변호사이자 MCP 에이전트다. Stage 1에서 생성된 구조화 데이터를 입력받아 **단일 HTML 파일**을 생성한다. HTML은 Mermaid.js 다이어그램을 활용하여 사건 구조를 시각화한다.
|
|
|
|
**핵심 산출물**: `Case_Dashboard.html`
|
|
|
|
**설계 원칙**: 단순하고 명료한 단일 페이지. 탭 없이 순차적으로 콘텐츠를 표시한다. Mermaid.js만 사용하여 다이어그램을 렌더링한다.
|
|
|
|
---
|
|
|
|
## 1. MCP 도구와 에러 처리
|
|
|
|
### 사용 도구
|
|
- `read_doc(doc_name: str)` - 텍스트 파일 읽기
|
|
- `list_docs(pattern: str = "*")` - 파일 목록 조회
|
|
- `write_file(path: str, content: str, overwrite: bool = True)` - 파일 쓰기
|
|
|
|
### 에러 처리 규칙
|
|
- 반환값이 `"Error:"`로 시작하면 실패 → 네임스페이스 변경 후 **1회만 재시도**
|
|
- 재시도 실패 시 해당 작업만 건너뛰고 진행
|
|
- 무한 재시도 금지
|
|
|
|
---
|
|
|
|
## 2. 전역 규칙
|
|
|
|
### 토큰 경제성
|
|
- 긴 원문 복사 금지
|
|
- 인용은 키워드/요지 수준으로 압축
|
|
|
|
### Output Discipline
|
|
각 Task는 다음 순서:
|
|
1. `<Analysis>`: 3~5 bullets
|
|
2. `<Execution>`: 핵심 실행
|
|
3. `"TASK n COMPLETE"` 출력
|
|
|
|
---
|
|
|
|
## 3. 입력 파일
|
|
|
|
| 파일명 | 용도 |
|
|
|--------|------|
|
|
| `BO.json` | 타임라인, 인과관계도 |
|
|
| `client_goal.json` | 목표/제약 서술 |
|
|
| `evidence_indexed.json` | 증거 매핑 |
|
|
| `Fact_Ledger.json` | 사실원장 타임라인 |
|
|
|
|
---
|
|
|
|
## 4. HTML 출력 구조
|
|
|
|
HTML은 탭 없이 단일 페이지에 다음 섹션을 **순차적으로** 표시한다:
|
|
|
|
```
|
|
[Section 1] 사건 개요 (Primary Goal & Constraints)
|
|
[Section 2] 행위 타임라인 (BO Timeline - Mermaid Timeline)
|
|
[Section 3] 인과관계도 (Causality DAG - Mermaid Flowchart)
|
|
[Section 4] 사실원장 타임라인 (Fact Ledger Timeline)
|
|
[Section 5] 증거 매핑표 (Evidence Index Table)
|
|
```
|
|
|
|
---
|
|
|
|
## 5. Tasks (2개 구조)
|
|
|
|
### Task A - 데이터 로드
|
|
|
|
<Analysis>
|
|
- list_docs로 4개 파일 존재 확인
|
|
- 각 JSON 파싱
|
|
</Analysis>
|
|
|
|
<Execution>
|
|
1. `list_docs("*")`로 파일 확인
|
|
2. `read_doc`로 4개 파일 읽기
|
|
3. JSON 파싱하여 메모리에 저장:
|
|
- `goal_data`: client_goal.json
|
|
- `bo_list`: BO.json
|
|
- `fact_list`: Fact_Ledger.json
|
|
- `evidence_list`: evidence_indexed.json
|
|
</Execution>
|
|
|
|
TASK A COMPLETE
|
|
|
|
---
|
|
|
|
### Task B - HTML 생성 및 저장
|
|
|
|
<Analysis>
|
|
- Section 1: goal_data에서 primary_goal, constraints 추출하여 산문체 서술
|
|
- Section 2: bo_list에서 Mermaid Timeline 생성
|
|
- Section 3: bo_list의 PriorAct 기반 Mermaid Flowchart 생성
|
|
- Section 4: fact_list에서 Mermaid Timeline 생성
|
|
- Section 5: evidence_list를 HTML 테이블로 생성
|
|
</Analysis>
|
|
|
|
<Execution>
|
|
|
|
아래 형식의 HTML을 생성하여 `write_file("Case_Dashboard.html", html_content)`로 저장한다.
|
|
|
|
---
|
|
|
|
#### HTML 템플릿 구조
|
|
|
|
```html
|
|
<!DOCTYPE html>
|
|
<html lang="ko">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>사건 시각화 대시보드</title>
|
|
<script src="https://cdn.jsdelivr.net/npm/mermaid/dist/mermaid.min.js"></script>
|
|
<style>
|
|
body {
|
|
font-family: 'Malgun Gothic', sans-serif;
|
|
max-width: 1200px;
|
|
margin: 0 auto;
|
|
padding: 40px 20px;
|
|
background: #f5f5f5;
|
|
color: #333;
|
|
}
|
|
h1 {
|
|
text-align: center;
|
|
color: #1a365d;
|
|
border-bottom: 3px solid #2563eb;
|
|
padding-bottom: 15px;
|
|
}
|
|
h2 {
|
|
color: #1e40af;
|
|
margin-top: 50px;
|
|
padding: 10px 15px;
|
|
background: #dbeafe;
|
|
border-left: 5px solid #2563eb;
|
|
}
|
|
.section {
|
|
background: white;
|
|
padding: 25px;
|
|
margin: 20px 0;
|
|
border-radius: 8px;
|
|
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
|
}
|
|
.mermaid {
|
|
display: flex;
|
|
justify-content: center;
|
|
margin: 20px 0;
|
|
}
|
|
table {
|
|
width: 100%;
|
|
border-collapse: collapse;
|
|
margin: 20px 0;
|
|
}
|
|
th, td {
|
|
border: 1px solid #e2e8f0;
|
|
padding: 12px;
|
|
text-align: left;
|
|
}
|
|
th {
|
|
background: #1e40af;
|
|
color: white;
|
|
}
|
|
tr:nth-child(even) {
|
|
background: #f8fafc;
|
|
}
|
|
.highlight {
|
|
background: #fef3c7;
|
|
padding: 2px 6px;
|
|
border-radius: 4px;
|
|
}
|
|
.warning {
|
|
color: #dc2626;
|
|
font-weight: bold;
|
|
}
|
|
.constraint-box {
|
|
background: #fef2f2;
|
|
border: 1px solid #fecaca;
|
|
border-radius: 8px;
|
|
padding: 15px;
|
|
margin: 15px 0;
|
|
}
|
|
.goal-box {
|
|
background: #ecfdf5;
|
|
border: 1px solid #a7f3d0;
|
|
border-radius: 8px;
|
|
padding: 15px;
|
|
margin: 15px 0;
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<h1>⚖️ 사건 시각화 대시보드</h1>
|
|
|
|
<!-- Section 1: 사건 개요 -->
|
|
<h2>1. 사건 개요</h2>
|
|
<div class="section">
|
|
<div class="goal-box">
|
|
<strong>의뢰 목표 (Primary Goal):</strong>
|
|
<p>{{PRIMARY_GOAL_TEXT}}</p>
|
|
</div>
|
|
<div class="constraint-box">
|
|
<strong>⚠️ 제약 사항 (Constraints):</strong>
|
|
<p>{{CONSTRAINTS_TEXT}}</p>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Section 2: 행위 타임라인 -->
|
|
<h2>2. 행위 타임라인 (Behavioral Objects)</h2>
|
|
<div class="section">
|
|
<div class="mermaid">
|
|
{{BO_TIMELINE_MERMAID}}
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Section 3: 인과관계도 -->
|
|
<h2>3. 인과관계도 (Causality Flow)</h2>
|
|
<div class="section">
|
|
<div class="mermaid">
|
|
{{CAUSALITY_FLOWCHART_MERMAID}}
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Section 4: 사실원장 타임라인 -->
|
|
<h2>4. 사실원장 타임라인 (Fact Ledger)</h2>
|
|
<div class="section">
|
|
<div class="mermaid">
|
|
{{FACT_TIMELINE_MERMAID}}
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Section 5: 증거 매핑표 -->
|
|
<h2>5. 증거 매핑표 (Evidence Index)</h2>
|
|
<div class="section">
|
|
<table>
|
|
<thead>
|
|
<tr>
|
|
<th>증거번호</th>
|
|
<th>문서유형</th>
|
|
<th>제목</th>
|
|
<th>핵심사실</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{{EVIDENCE_TABLE_ROWS}}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
|
|
<script>
|
|
mermaid.initialize({
|
|
startOnLoad: true,
|
|
theme: 'default',
|
|
securityLevel: 'loose'
|
|
});
|
|
</script>
|
|
</body>
|
|
</html>
|
|
```
|
|
|
|
---
|
|
|
|
#### 플레이스홀더 생성 규칙
|
|
|
|
**{{PRIMARY_GOAL_TEXT}}**: `goal_data.primary_goal` 값을 산문체 문장으로 서술
|
|
|
|
**{{CONSTRAINTS_TEXT}}**: `goal_data.constraints` 배열을 순서대로 나열하여 산문체로 서술. 예: "첫째, [constraint1]. 둘째, [constraint2]. 셋째, [constraint3]."
|
|
|
|
**{{BO_TIMELINE_MERMAID}}**: Mermaid Timeline 문법으로 생성
|
|
|
|
```
|
|
timeline
|
|
title 행위 타임라인
|
|
section 2013
|
|
2013-10-07 : bh1 - 김수경, 근저당권 설정
|
|
2013-10-08 : bh2 - 우방캐피탈, 대출 실행
|
|
section 2015
|
|
2015-12-01 : bh8 - 개성금속, 부도
|
|
section 2017
|
|
...
|
|
```
|
|
|
|
생성 로직:
|
|
1. `bo_list`를 `BehaviorTime` 기준 정렬
|
|
2. 연도별로 section 그룹화
|
|
3. 각 BO: `{BehaviorTime} : {id} - {Performer}, {Action 앞 20자}`
|
|
4. 증거공백 BO는 끝에 `[증거공백]` 표시
|
|
|
|
**{{CAUSALITY_FLOWCHART_MERMAID}}**: Mermaid Flowchart 문법으로 생성
|
|
|
|
```
|
|
flowchart TD
|
|
classDef gap fill:#fee2e2,stroke:#ef4444,stroke-width:2px
|
|
|
|
bh1["김수경: 근저당권 설정"]
|
|
bh2["우방캐피탈: 대출 실행"]
|
|
bh7["개성금속: 기한연장 거부"]:::gap
|
|
|
|
bh1 --> bh2
|
|
bh2 --> bh3
|
|
bh6 --> bh7
|
|
```
|
|
|
|
생성 로직:
|
|
1. 각 BO에 대해 노드 생성: `{id}["{Performer}: {Action 앞 15자}"]`
|
|
2. 증거공백 BO는 `:::gap` 클래스 적용
|
|
3. `PriorAct`가 있으면 `{PriorAct} --> {id}` 연결선 추가
|
|
|
|
**{{FACT_TIMELINE_MERMAID}}**: Mermaid Timeline 문법으로 생성
|
|
|
|
```
|
|
timeline
|
|
title 사실원장 타임라인
|
|
section 2013
|
|
2013-10-07 : F-001 - 근저당권 설정 (high)
|
|
2013-10-08 : F-002 - 대출 실행 (high)
|
|
section 2015
|
|
2015-11-30 : F-007 - 기한연장 거부 (low)
|
|
```
|
|
|
|
생성 로직:
|
|
1. `fact_list`를 `date` 기준 정렬
|
|
2. 연도별로 section 그룹화
|
|
3. 각 Fact: `{date} : {fact_id} - {action 앞 20자} ({credibility})`
|
|
4. credibility가 low인 경우 표시 강조
|
|
|
|
**{{EVIDENCE_TABLE_ROWS}}**: HTML 테이블 행으로 생성
|
|
|
|
```html
|
|
<tr>
|
|
<td>E-001</td>
|
|
<td>등기부등본</td>
|
|
<td>근저당권설정등기</td>
|
|
<td>채권최고액 15억원...</td>
|
|
</tr>
|
|
```
|
|
|
|
생성 로직:
|
|
1. `evidence_list` 순회
|
|
2. 각 항목: `evidence_index`, `doc_type`, `title`, `key_facts`
|
|
|
|
---
|
|
|
|
</Execution>
|
|
|
|
TASK B COMPLETE
|
|
|
|
---
|
|
|
|
## 6. 출력 파일
|
|
|
|
| 파일명 | 설명 |
|
|
|--------|------|
|
|
| `Case_Dashboard.html` | 단일 페이지 시각화 대시보드 |
|
|
|
|
---
|
|
|
|
## 7. Mermaid 문법 참조
|
|
|
|
### Timeline 문법
|
|
```
|
|
timeline
|
|
title 제목
|
|
section 그룹명
|
|
날짜1 : 이벤트1
|
|
날짜2 : 이벤트2
|
|
```
|
|
|
|
### Flowchart 문법
|
|
```
|
|
flowchart TD
|
|
classDef 클래스명 fill:#색상,stroke:#색상
|
|
|
|
노드id["라벨텍스트"]
|
|
노드id2["라벨텍스트"]:::클래스명
|
|
|
|
노드id --> 노드id2
|
|
```
|
|
|
|
---
|
|
|
|
## 8. 최종 체크리스트
|
|
|
|
- [ ] 4개 입력 파일 로드 완료
|
|
- [ ] Section 1: Primary Goal, Constraints 산문체 서술
|
|
- [ ] Section 2: BO Timeline (Mermaid Timeline)
|
|
- [ ] Section 3: Causality Flowchart (Mermaid Flowchart)
|
|
- [ ] Section 4: Fact Ledger Timeline (Mermaid Timeline)
|
|
- [ ] Section 5: Evidence Table (HTML Table)
|
|
- [ ] Case_Dashboard.html 저장 완료
|
|
|
|
prevs: []
|
|
nexts: [stage3_청구전작업]
|
|
|
|
- name: stage3_청구전작업
|
|
description: 청구구조도 작성을 위한 전작업
|
|
llm_provider: anthropic
|
|
llm_model: claude-opus-4-5
|
|
prompts:
|
|
- role: user
|
|
content: |
|
|
## 0. 역할과 목적
|
|
|
|
당신은 한국 민사·상사 소송 전문 변호사이자 MCP 에이전트다. 이 Stage에서는 Stage 1 산출물과 추가 입력 파일, 외부 DB 기준을 분석하여 **청구 전략을 수립**하고 구조화된 문서를 생성한다.
|
|
|
|
**핵심 산출물**: `청구전작업.md` (전체 2,000단어 이내)
|
|
|
|
**설계 철학**: LLM은 법률적 판단을 "대체"하는 것이 아니라, 변호사가 전략적 결단을 내릴 수 있는 사고 환경을 구축한다. 환각을 방지하기 위해 taxonomy exact-match 원칙과 외부 DB 기준 최우선 원칙을 엄격히 적용한다.
|
|
|
|
**최종 문서에 포함될 내용**:
|
|
1. 청구권 리스트 (우선순위별, 상위 5개 상세 + 나머지 요약)
|
|
2. 청구권별 원고/피고 결정
|
|
3. 청구권별 사건 종류 결정
|
|
4. 다수 청구권 존재 시 청구방식(병합/단독) 설계
|
|
|
|
---
|
|
|
|
## 1. MCP 도구와 에러 처리
|
|
|
|
### 1.1 사용 도구
|
|
|
|
**파일 도구:**
|
|
- `read_doc(doc_name: str)` - 텍스트/JSON 파일 읽기
|
|
- `list_docs(pattern: str = "*")` - 파일 목록 조회
|
|
- `write_file(path: str, content: str, overwrite: bool = True)` - 파일 쓰기
|
|
|
|
**Weaviate 도구:**
|
|
- `search_hybrid(collection_name, tenant, query, limit, alpha, ...)` - 하이브리드 검색
|
|
- `list_collections()` - 컬렉션 목록 조회
|
|
- `list_tenants(collection_name)` - 테넌트 목록 조회
|
|
|
|
### 1.2 에러 처리 규칙
|
|
|
|
**파일 도구 에러:**
|
|
- 반환값이 `"Error:"`로 시작하면 실패 → 네임스페이스 변경 후 **1회만 재시도**
|
|
- 재시도 실패 시 해당 작업만 건너뛰고 진행
|
|
- 무한 재시도 금지
|
|
|
|
**Weaviate 도구 에러:**
|
|
- 반환값이 `{"error": "..."}` 형태면 실패
|
|
- tenant 지정 누락 에러 시: tenant 파라미터 확인 후 재시도
|
|
- 그 외 에러 시: `DB_CRITERIA = "조회실패"` 설정 후 **Fallback 결정 트리** 적용
|
|
|
|
**검증/재시도 상한:**
|
|
- 동일 작업 최대 2회 재시도 (총 3회 시도)
|
|
- 3회 시도 후에도 실패 시: 최선의 결과로 진행 + `VALIDATION WARNING` 기록
|
|
|
|
---
|
|
|
|
## 2. 전역 규칙
|
|
|
|
### 2.1 토큰 경제성
|
|
- 긴 원문 복사 금지
|
|
- 입력 파일은 ID 중심 참조만 (bo_id, fact_id, evidence_index)
|
|
- 원문 재진술 금지, 인용은 키워드/요지 수준으로 압축
|
|
|
|
### 2.2 환각 방지 원칙
|
|
|
|
**taxonomy exact-match 원칙:**
|
|
- `case_kinds.json`에 존재하는 문자열만 그대로 복사(copy-paste)
|
|
- 띄어쓰기/조사/용어 임의 변경 금지
|
|
- 불확실하면 한 단계 상위로 back-off
|
|
|
|
**외부 DB 기준 최우선 원칙:**
|
|
- Weaviate DB에서 조회한 병합/단독 기준을 최우선 적용
|
|
- 문서 밖 기준 추가 금지
|
|
|
|
### 2.3 불명확성 통일 처리 규칙
|
|
- **기산점/금액/비용 추정이 불가하면**: 해당 평가 요소는 **Medium**으로 설정
|
|
- `VALIDATION WARNING: [요소명] 산정 불가 - [사유 1줄]` 기록
|
|
- 예: `VALIDATION WARNING: 시효긴급도 산정 불가 - 권리발생일 미확인`
|
|
|
|
### 2.4 임시 저장 방식
|
|
- **파일 쓰기 금지**: Task 1~3 결과는 메모리(대화 컨텍스트 내 JSON 블록)로만 유지
|
|
- **최종 단계에서만 파일 쓰기**: Task 4에서 `write_file("청구전작업.md", ...)` 1회 실행
|
|
|
|
### 2.5 Output Discipline
|
|
각 Task는 다음 순서:
|
|
1. `<Analysis>`: 3~5 bullets 체크리스트
|
|
2. `<Execution>`: 핵심 실행
|
|
3. `<Validation>`: 필수 필드 존재 확인
|
|
4. `"TASK n COMPLETE"` 출력
|
|
|
|
---
|
|
|
|
## 3. 입력 파일
|
|
|
|
### 3.1 Stage 1 산출물 (필수)
|
|
|
|
| 파일명 | 용도 | 참조 필드 |
|
|
|--------|------|----------|
|
|
| `BO.json` | 청구권 후보 식별 | id, Performer, Action, ActionType, Legal_Keywords, Evidence |
|
|
| `client_goal.json` | 원고 목표 파악 | primary_goal, parties, constraints |
|
|
| `evidence_indexed.json` | 증거 현황 확인 | evidence_index, doc_type |
|
|
| `Fact_Ledger.json` | 사실 신뢰도 확인 | fact_id, source_bo_id, credibility |
|
|
| `client_meeting.md` | 배경 정보 (참조용) | - |
|
|
|
|
### 3.2 추가 입력 파일 (필수)
|
|
|
|
| 파일명 | 용도 |
|
|
|--------|------|
|
|
| `case_kinds.json` | 사건종류 taxonomy (소송대분류 > 분쟁유형 > 사건종류) |
|
|
| `적격피고자제외조건.json` | 피고 적격성 판단 기준 (제외조건, 경제성원칙) |
|
|
|
|
### 3.3 외부 DB (Weaviate)
|
|
|
|
**컬렉션/테넌트**: `Legal_Books` / `Criteria_individual_consolidated_claim`
|
|
**용도**: 청구 병합/단독 판단 기준, 단순/선택/예비 병합 유형 기준
|
|
|
|
---
|
|
|
|
## 4. Tasks (4개 구조)
|
|
|
|
### Task 1 - Preflight: 파일 로드 및 DB 조회
|
|
|
|
<Analysis>
|
|
- list_docs로 7개 필수 파일 존재 확인
|
|
- 각 JSON 파싱
|
|
- Weaviate에서 병합 기준 조회 (정확히 1회)
|
|
</Analysis>
|
|
|
|
<Execution>
|
|
|
|
**[1-1] 파일 로드**
|
|
1. `list_docs("*")`로 파일 확인
|
|
2. 필수 파일 7개 읽기
|
|
3. JSON 파싱 및 메모리 저장
|
|
|
|
**[1-2] Weaviate DB 조회**
|
|
|
|
다음 파라미터로 **정확히 1회** 호출 (Stage 전체에서 재조회 금지):
|
|
```
|
|
search_hybrid(
|
|
collection_name="Legal_Books",
|
|
tenant="Criteria_individual_consolidated_claim",
|
|
query="민사소송 청구의 객관적 병합 요건 단독 제기 판단 기준 주위적 예비적 청구 구분 단순병합 선택적병합",
|
|
limit=5,
|
|
alpha=0.3
|
|
)
|
|
```
|
|
|
|
- 반환값의 `properties`에서 기준/요건/예시/예외 내용 추출
|
|
- **5개 불릿으로 압축**하여 `DB_CRITERIA` 변수에 저장
|
|
- 에러 시: `DB_CRITERIA = "조회실패"` 설정
|
|
|
|
</Execution>
|
|
|
|
<Validation>
|
|
- [ ] 7개 파일 모두 로드됨
|
|
- [ ] DB_CRITERIA 변수 설정됨 (정상 조회 또는 "조회실패")
|
|
</Validation>
|
|
|
|
TASK 1 COMPLETE
|
|
|
|
---
|
|
|
|
### Task 2 - 청구권 분석 (스코어링 + 원고/피고 + 사건종류)
|
|
|
|
<Analysis>
|
|
- client_goal.json에서 원고 주된 목적 파악
|
|
- BO.json, Fact_Ledger.json에서 청구권 후보 식별
|
|
- 각 청구권 3단계 등급 평가
|
|
- 원고/피고 적격성 판단
|
|
- case_kinds.json 기반 사건종류 결정
|
|
</Analysis>
|
|
|
|
<Execution>
|
|
|
|
**[2-1] 청구권 식별 및 등급 평가**
|
|
|
|
BO.json의 Legal_Keywords와 ActionType을 분석하여 청구권 후보 식별.
|
|
각 청구권에 대해 **3단계 등급(High/Medium/Low)**으로 평가:
|
|
|
|
| 평가 요소 | High (3점) | Medium (2점) | Low (1점) |
|
|
|-----------|------------|--------------|-----------|
|
|
| 승소 가능성 | Fact_Ledger credibility=high, 직접증거 존재 | credibility=medium, 간접증거만 | credibility=low, 증거공백 |
|
|
| 집행 가능성 | 피고 자산 단서 2개 이상 | 자산 단서 1개 | 무자력 또는 자산 불명 |
|
|
| 소송경제성 | 청구금액 1억 이상 | 5천만~1억 | 5천만 미만 |
|
|
| 시효 긴급도 | 잔여 6개월 이내 | 잔여 1년 이내 | 잔여 1년 초과 |
|
|
|
|
**불명확성 처리:**
|
|
- 기산점 확인 불가 → 시효긴급도 = Medium + WARNING
|
|
- 청구금액 미확정 → 소송경제성 = Medium + WARNING
|
|
- 자산 정보 없음 → 집행가능성 = Low
|
|
|
|
**우선순위 산정:**
|
|
- 4개 요소 합산 (최대 12점)
|
|
- 동점 시: 시효긴급도 > 승소가능성 > 집행가능성 > 소송경제성
|
|
|
|
**[2-2] 원고/피고 파악**
|
|
|
|
원고:
|
|
- client_goal.json의 parties.plaintiffs에서 식별
|
|
- 권리 귀속 명확 → "확정" / 불명확 → "후보" + 사유 1줄
|
|
|
|
피고:
|
|
- 적격피고자제외조건.json 기준 적용
|
|
- 제외조건 해당 시 → 제외 또는 대체 지정
|
|
- **무자력만으로 자동 제외 금지** → `[EXECUTION_RISK: HIGH]` 태깅
|
|
- 불명확 시 → "불명확" + 보수적(최소) 확정
|
|
|
|
**[2-3] 사건종류 결정**
|
|
|
|
case_kinds.json taxonomy 기준 exact-match:
|
|
- taxonomy에 존재하는 문자열만 복사
|
|
- 불확실하면 back-off (사건종류 null → 분쟁유형까지만)
|
|
|
|
**메모리 저장 형식:**
|
|
```json
|
|
{
|
|
"claims": [...], // 청구권 배열 (우선순위 정렬)
|
|
"plaintiffs": [...],
|
|
"defendants": [...],
|
|
"case_types": [...],
|
|
"warnings": [...] // VALIDATION WARNING 목록
|
|
}
|
|
```
|
|
|
|
</Execution>
|
|
|
|
<Validation>
|
|
- [ ] claims 배열이 비어있지 않음
|
|
- [ ] 각 claim에 claim_id, scores, priority 존재
|
|
- [ ] plaintiffs, defendants 배열 존재
|
|
- [ ] case_types 배열 존재
|
|
</Validation>
|
|
|
|
TASK 2 COMPLETE
|
|
|
|
---
|
|
|
|
### Task 3 - 청구방식 결정 (조건부 실행)
|
|
|
|
**조건부 스킵 규칙:**
|
|
```
|
|
IF claims.length == 1:
|
|
claim_structure = {"structure_type": "단독", "rationale": "청구권 1개"}
|
|
SKIP Task 3 → GOTO Task 4
|
|
```
|
|
|
|
<Analysis>
|
|
- Task 1의 DB_CRITERIA 참조
|
|
- 청구 단위(Claim Unit) 구성
|
|
- 병합 vs 단독 판단
|
|
- 병합 유형 선택
|
|
</Analysis>
|
|
|
|
<Execution>
|
|
|
|
**[3-1] 청구 단위(Claim Unit) 구성**
|
|
|
|
각 청구권에 대해 다음을 포함하는 Claim Unit 생성:
|
|
- (a) 사건 라벨: taxonomy 경로
|
|
- (b) 관련 BO: BO id 목록
|
|
- (c) **핵심 사실 키워드 정확히 5개**: 당사자/행위/금액/시기/증거핵심
|
|
- (d) 청구취지 요지 1줄
|
|
- (e) 매핑 청구권 ID
|
|
|
|
**[3-2] 병합 vs 단독 판단**
|
|
|
|
**DB_CRITERIA 정상 조회 시**: DB 기준 최우선 적용
|
|
|
|
**DB_CRITERIA = "조회실패" 시**: Fallback 결정 트리 적용:
|
|
```
|
|
├─ 청구권 수 = 1 → 단독 제기
|
|
├─ 청구권 수 ≥ 2 AND 모든 피고 동일 → 단순병합
|
|
├─ 청구권 수 ≥ 2 AND 피고 일부 상이:
|
|
│ ├─ 사실관계 공통 → 단순병합
|
|
│ └─ 사실관계 분리 → 분리 (각각 단독)
|
|
├─ 청구권 양립 불가 → 선택적 병합
|
|
├─ 주위/예비 관계 명확 → 예비적 병합
|
|
└─ 불명확 → 예비적 병합 + "불명확" 표기
|
|
```
|
|
|
|
**[3-3] 병합 유형 선택**
|
|
|
|
- **단순병합**: 청구들이 양립 가능
|
|
- **선택적 병합**: 청구들이 양립 불가, 어느 하나만 인용
|
|
- **예비적 병합**: 주위 청구 기각 대비 예비 청구
|
|
|
|
</Execution>
|
|
|
|
<Validation>
|
|
- [ ] claim_structure.structure_type이 허용값 중 하나 (단독/단순병합/선택적병합/예비적병합)
|
|
- [ ] db_criteria_applied 또는 fallback_applied 플래그 존재
|
|
</Validation>
|
|
|
|
TASK 3 COMPLETE
|
|
|
|
---
|
|
|
|
### Task 4 - 최종 문서 작성 및 저장
|
|
|
|
<Analysis>
|
|
- Task 2, 3 메모리 데이터 종합
|
|
- 청구전작업.md 구조 설계 (2,000단어 이내)
|
|
- Self-Check 수행
|
|
</Analysis>
|
|
|
|
<Execution>
|
|
|
|
**[4-1] 문서 구조** (전체 2,000단어 이내)
|
|
|
|
```markdown
|
|
# 청구 전 작업 보고서
|
|
|
|
## 1. 사건 개요
|
|
[primary_goal 기반 1~2문단]
|
|
|
|
## 2. 청구권 분석
|
|
|
|
### 2.1 청구권 우선순위 요약
|
|
| 순위 | 청구권 | 승소 | 집행 | 경제 | 시효 | 종합 |
|
|
|------|--------|------|------|------|------|------|
|
|
| 1~N | ... | H/M/L | H/M/L | H/M/L | H/M/L | 점수 |
|
|
|
|
### 2.2 상위 청구권 상세 (Top 5만)
|
|
[각 청구권: 청구취지 1문장 + 청구원인 1문장 + 근거 3불릿]
|
|
|
|
### 2.3 기타 청구권 (6위 이하, 있는 경우)
|
|
[테이블로만 표시, 상세 기술 없음]
|
|
|
|
## 3. 당사자 결정
|
|
### 3.1 원고
|
|
| 원고명 | 지위 | 적격 상태 |
|
|
### 3.2 피고
|
|
| 피고명 | 지위 | 적격 상태 | 집행리스크 |
|
|
### 3.3 청구권별 당사자 매핑
|
|
| 청구권 | 원고 | 피고 |
|
|
|
|
## 4. 사건종류 결정
|
|
| 청구권 | 소송대분류 | 분쟁유형 | 사건종류 |
|
|
|
|
## 5. 청구방식 결정
|
|
### 5.1 청구 구조: [단독/단순병합/선택적병합/예비적병합]
|
|
### 5.2 판단 근거: [DB 기준 적용 / Fallback 적용]
|
|
### 5.3 Claim Unit 요약 (키워드 5개씩)
|
|
|
|
## 6. 검증 경고 (있는 경우)
|
|
[VALIDATION WARNING 목록]
|
|
|
|
## 7. 후속 단계 고려사항
|
|
[Stage 4 진행 시 주의사항, 1~3문장]
|
|
```
|
|
|
|
**[4-2] 작성 원칙**
|
|
|
|
- 법조계 문장 작성 전통 준수
|
|
- 표 적극 활용
|
|
- **청구권 상세는 Top 5만** (6위 이하는 테이블만)
|
|
- **청구권당 상한**: 청구취지 1문장 + 청구원인 1문장 + 근거 3불릿
|
|
|
|
**[4-3] Self-Check**
|
|
|
|
문서 저장 전 다음 검증 수행:
|
|
- [ ] taxonomy 문자열이 case_kinds.json에 존재하는지 확인
|
|
- [ ] 모든 청구권에 원고/피고 매핑 존재
|
|
- [ ] claim_structure.structure_type이 유효값인지 확인
|
|
- [ ] 전체 문서 길이가 2,000단어 이내인지 확인
|
|
|
|
검증 실패 시: 해당 항목 수정 후 저장
|
|
|
|
**[4-4] 파일 저장**
|
|
|
|
`write_file("청구전작업.md", content, overwrite=true)`
|
|
|
|
</Execution>
|
|
|
|
<Validation>
|
|
- [ ] 청구전작업.md 파일 생성 완료
|
|
- [ ] 문서 내 모든 섹션 존재
|
|
- [ ] VALIDATION WARNING 섹션에 경고 기록됨 (있는 경우)
|
|
</Validation>
|
|
|
|
TASK 4 COMPLETE
|
|
|
|
---
|
|
|
|
## 5. 최종 체크리스트
|
|
|
|
- [ ] 7개 입력 파일 로드 완료
|
|
- [ ] Weaviate DB 조회 완료 (1회) 또는 Fallback 적용
|
|
- [ ] 청구권 등급 평가 완료 (High/Medium/Low)
|
|
- [ ] 불명확 항목에 VALIDATION WARNING 기록
|
|
- [ ] 원고/피고 적격성 판단 완료 (집행리스크 태깅 포함)
|
|
- [ ] 사건종류 결정 완료 (taxonomy exact-match)
|
|
- [ ] 청구방식 결정 완료 (DB 기준 또는 Fallback 결정 트리)
|
|
- [ ] 청구권 상세는 Top 5만 기술
|
|
- [ ] 청구전작업.md 저장 완료 (2,000단어 이내)
|
|
- [ ] Self-Check 통과
|
|
|
|
---
|
|
|
|
## Appendix A: 등급 평가 기준
|
|
|
|
### A.1 승소 가능성
|
|
|
|
| 등급 | 기준 |
|
|
|------|------|
|
|
| High | Fact_Ledger credibility=high, 처분문서/직접증거 존재 |
|
|
| Medium | credibility=medium, 간접증거만 존재 / **기준 불명확 시 기본값** |
|
|
| Low | credibility=low, 진술만, 증거공백 |
|
|
|
|
### A.2 집행 가능성
|
|
|
|
| 등급 | 기준 |
|
|
|------|------|
|
|
| High | 자산 단서 2개 이상 (부동산, 예금, 급여, 차량 등) |
|
|
| Medium | 자산 단서 1개 |
|
|
| Low | 무자력 명시 또는 자산 단서 없음 / **정보 없음 시 기본값** |
|
|
|
|
### A.3 소송경제성
|
|
|
|
| 등급 | 기준 |
|
|
|------|------|
|
|
| High | 청구금액 1억원 이상 |
|
|
| Medium | 청구금액 5천만~1억원 / **금액 미확정 시 기본값** |
|
|
| Low | 청구금액 5천만원 미만 |
|
|
|
|
### A.4 시효 긴급도
|
|
|
|
| 등급 | 기준 |
|
|
|------|------|
|
|
| High | 소멸시효/제척기간 잔여 6개월 이내 |
|
|
| Medium | 잔여 1년 이내 / **기산점 불명확 시 기본값** |
|
|
| Low | 잔여 1년 초과 또는 시효 완성 |
|
|
|
|
---
|
|
|
|
## Appendix B: Fallback 결정 트리 (DB 조회 실패 시)
|
|
|
|
```
|
|
[청구권 수 판단]
|
|
├─ 청구권 = 1개
|
|
│ └─ 결정: 단독 제기
|
|
│
|
|
├─ 청구권 ≥ 2개
|
|
│ ├─ [피고 동일성 판단]
|
|
│ │ ├─ 모든 피고 동일
|
|
│ │ │ └─ 결정: 단순병합
|
|
│ │ │
|
|
│ │ └─ 피고 일부 상이
|
|
│ │ ├─ [사실관계 공통성 판단]
|
|
│ │ │ ├─ 사실관계 공통 (동일 거래/계약)
|
|
│ │ │ │ └─ 결정: 단순병합
|
|
│ │ │ │
|
|
│ │ │ └─ 사실관계 분리
|
|
│ │ │ └─ 결정: 분리 (각각 단독)
|
|
│ │
|
|
│ ├─ [청구 양립성 판단]
|
|
│ │ ├─ 청구들이 양립 불가 (택일 관계)
|
|
│ │ │ └─ 결정: 선택적 병합
|
|
│ │ │
|
|
│ │ └─ 주위/예비 관계 명확
|
|
│ │ └─ 결정: 예비적 병합
|
|
│ │
|
|
│ └─ [불명확]
|
|
│ └─ 결정: 예비적 병합 + "불명확" 표기
|
|
```
|
|
|
|
---
|
|
|
|
## Appendix C: Weaviate 에러 대응
|
|
|
|
| 에러 유형 | 반환 형태 | 대응 |
|
|
|-----------|----------|------|
|
|
| tenant 누락 | `{"error": "...Please specify a tenant."}` | tenant 파라미터 확인 후 재시도 |
|
|
| 컬렉션 미존재 | `{"error": "..."}` | DB_CRITERIA = "조회실패" |
|
|
| 네트워크 에러 | 타임아웃 또는 연결 실패 | DB_CRITERIA = "조회실패" |
|
|
|
|
DB_CRITERIA = "조회실패" 시:
|
|
1. Fallback 결정 트리 적용
|
|
2. 최종 문서에 "DB 기준 미적용 - Fallback 적용" 명시
|
|
|
|
|
|
tools:
|
|
mcpServers:
|
|
localdocs:
|
|
type: streamable-http
|
|
url: "http://mcp-localdocs:8012/mcp"
|
|
description: Get the content of local documents
|
|
|
|
prevs: [stage1_BO_extraction]
|
|
nexts: [stage3_자료_조회_쿼리]
|
|
|
|
- name: stage3.5.1_요건사실정보추출쿼리생성
|
|
description: 요건사실 작성을 위해 외부 DB에서 자료를 검색하는 쿼리 생성
|
|
llm_provider: anthropic
|
|
llm_model: claude-opus-4-5
|
|
|
|
tools:
|
|
mcpServers:
|
|
weaviate:
|
|
type: streamable-http
|
|
url: "https://weaviate.eroomai.com/mcp"
|
|
description: Get the content from weaviate
|
|
localdocs:
|
|
type: streamable-http
|
|
url: "http://mcp-localdocs:8012/mcp"
|
|
description: Get the content of local documents
|
|
|
|
prompts:
|
|
- role: user
|
|
content: |
|
|
## 1) System Constraints (CRITICAL)
|
|
|
|
**Output**: JSON ONLY. Write file + print same JSON. No prose.
|
|
|
|
**PLAN ONLY**: MUST NOT call search_hybrid/search_near_text/search_bm25.
|
|
|
|
**Query Count Invariant (STRICT)**:
|
|
- Query count is bounded by DISTINCT claim_type count, NOT by claim count
|
|
- If n claims exist but only k distinct claim_types, generate at most: k*2 (doctrine+calc) + 1 (global) + 1 (actio_value if applicable)
|
|
- Violation of this invariant → automatic DEGRADED status + excess queries deleted
|
|
|
|
**Noise Policy (DIFFERENTIATED)**:
|
|
- doctrine_bundle: STRICT exclusion of case-specific facts (amounts, dates, names)
|
|
- calculation_bundle: ALLOW categorical keywords (지연손해금, 법정이율, 원물반환, 가액배상)
|
|
|
|
**Anchor Rule**: doctrine queries MUST START WITH "요건사실 항변 입증책임"
|
|
|
|
**Determinism Principle**: Every decision point must resolve to a deterministic state. No "proceed with ambiguity."
|
|
|
|
---
|
|
|
|
## 2) Inputs
|
|
|
|
**REQUIRED**: 청구전작업.md
|
|
**OPTIONAL**: Weaviate_DB_Structure_updated.md (preferred for offline validation)
|
|
|
|
---
|
|
|
|
## 3) Output
|
|
|
|
Write ONE json file: `Queries_facts_satisfying_the_legal_elements.json`
|
|
Print the SAME JSON to stdout.
|
|
|
|
---
|
|
|
|
## 4) Tools & Error Handling (CRITICAL UPDATE)
|
|
|
|
**File tools**: list_docs("*"), read_doc(doc_name), write_file(path, content, overwrite=true)
|
|
|
|
**Weaviate metadata tools** (validation only):
|
|
- list_collections()
|
|
- list_tenants(collection_name)
|
|
|
|
**Error Detection (GENERALIZED)**:
|
|
Trigger retry if ANY of the following:
|
|
- Tool returns string starting with "Error:"
|
|
- Tool returns JSON object containing "error" key: `{"error": "..."}`
|
|
- Tool returns null or undefined
|
|
|
|
**Retry rule**: On error detection, retry ONCE with same args. If still failing:
|
|
1. Add entry to validation_warnings
|
|
2. Set resolution_state.status = FALLBACK_APPLIED or UNRESOLVED
|
|
3. Continue best-effort
|
|
|
|
**Max attempts**: Do not call same tool with same args more than twice.
|
|
|
|
---
|
|
|
|
## 5) Tool Contract (Stage 3.5.2 Execution)
|
|
|
|
Stage 3.5.2 will execute: `search_hybrid(collection_name, query, alpha, limit, tenant)`
|
|
|
|
planned_calls MUST include only: collection_name, tenant, query_text, fallback_query_text, alpha, limit
|
|
|
|
Do NOT include: fusion_type, bm25_operator, query_properties (unsupported)
|
|
|
|
---
|
|
|
|
## 6) Step A — Parse Claims (with Fallback)
|
|
|
|
### 6.1 Primary Parsing (Table-based)
|
|
1. read_doc("청구전작업.md")
|
|
2. Locate table "청구권 우선순위 요약" or "2.1 청구권 우선순위 요약"
|
|
3. Extract per row: claim_id, claim_title (청구권명), relief_summary (청구취지)
|
|
|
|
### 6.2 Fallback Parsing (Pattern-based)
|
|
If primary table not found or parsing fails:
|
|
1. Scan section "청구권별 상세" or "2.2 상위 청구권 상세"
|
|
2. Extract claim_id by regex: `C-\d{3}`
|
|
3. Extract claim_title from header pattern: `#### [claim_id] {claim_title}`
|
|
4. Extract relief_summary from "**청구취지:**" line
|
|
|
|
### 6.3 Claim Type Classification (Strict Enum)
|
|
|
|
| 키워드 포함 여부 | claim_type |
|
|
|------------------|------------|
|
|
| "대여금" OR "대출금" | Loan_Claim |
|
|
| "보증" OR "보증채무" | Guarantee_Claim |
|
|
| "구상" OR "대위변제" | Indemnity_Claim |
|
|
| "사해행위" OR "채권자취소" | Actio_Pauliana |
|
|
| None of above | Unknown_Claim |
|
|
|
|
**Unknown_Claim 처리**: resolution_state = UNRESOLVED, human_review_required = true
|
|
|
|
---
|
|
|
|
## 7) Step B — Build Scope Catalog
|
|
|
|
**Goal**: Validate tenants deterministically.
|
|
|
|
**Preferred (offline)**: Parse Weaviate_DB_Structure_updated.md → build valid_tenants_by_collection
|
|
|
|
**Fallback (online)**: list_collections() ONCE, list_tenants(collection) ONCE per used collection
|
|
|
|
**Validation Result States**:
|
|
- All tenants validated → CONFIRMED
|
|
- Some tenants not found, fallback used → FALLBACK_APPLIED
|
|
- Validation impossible → UNRESOLVED + human_review_required = true
|
|
|
|
---
|
|
|
|
## 8) CLAIM_QUERY_MAP (CANONICAL, IMMUTABLE)
|
|
|
|
```json
|
|
{
|
|
"Loan_Claim": ["doctrine_bundle", "calculation_bundle"],
|
|
"Guarantee_Claim": ["doctrine_bundle", "calculation_bundle"],
|
|
"Indemnity_Claim": ["doctrine_bundle", "calculation_bundle"],
|
|
"Actio_Pauliana": ["doctrine_bundle", "calculation_bundle", "value_of_claim_bundle"],
|
|
"Unknown_Claim": ["doctrine_bundle"]
|
|
}
|
|
```
|
|
|
|
**Rule**: Query types outside this map are PROHIBITED. Generating unlisted query type → UNRESOLVED.
|
|
|
|
---
|
|
|
|
## 9) Strategy Tables
|
|
|
|
### 9.1 Collections
|
|
| purpose | collection |
|
|
|---------|------------|
|
|
| doctrine_bundle | Legal_Books |
|
|
| calculation_bundle | Legal_Books |
|
|
| global_costs | Law_and_rules |
|
|
| value_of_claim_bundle | Legal_Books |
|
|
|
|
### 9.2 Doctrine Bundle Strategy
|
|
|
|
| claim_type | alpha | lexicon_pool | MUST_INCLUDE | tenant_candidates |
|
|
|------------|-------|--------------|--------------|-------------------|
|
|
| Loan_Claim | 0.25 | 대여금, 금전소비대차, 변제기, 이자, 지연손해금, 기한의이익, 소멸시효, 상계, 변제, 이행지체 | 대여금, 변제기 | Loan_Claim_legally_required_facts, Loan_Claim, Criteria_individual_consolidated_claim |
|
|
| Guarantee_Claim | 0.25 | 보증채무, 연대보증, 주채무, 보증한도, 부종성, 보충성, 최고검색항변권, 보증인, 근보증, 특정채무보증, 보증인보호, 서면요건 | 연대보증, 최고검색항변권 | Loan_Claim_legally_required_facts, Loan_Claim, Criteria_individual_consolidated_claim |
|
|
| Indemnity_Claim | 0.30 | 구상금, 구상권, 대위변제, 법정대위, 통지, 변제자대위, 변제액, 소멸시효, 구상권행사, 변제충당 | 구상금, 대위변제 | Indemnity_Claim_legally_required_facts, Criteria_individual_consolidated_claim |
|
|
| Actio_Pauliana | 0.45 | 사해행위, 채권자취소권, 피보전채권, 무자력, 사해의사, 수익자, 전득자, 제척기간, 선의, 악의, 원상회복, 원물반환, 가액배상, 상대적무효 | 무자력, 사해의사, 제척기간 | Actio_Pauliana_legally_required_facts, Actio_Pauliana_overview_legally_required_facts, Criteria_individual_consolidated_claim |
|
|
| Unknown_Claim | 0.35 | 요건사실, 청구원인, 항변, 재항변, 입증책임 | 요건사실 | Criteria_individual_consolidated_claim |
|
|
|
|
### 9.3 Calculation Bundle Strategy
|
|
|
|
| claim_type | alpha | lexicon_pool | tenant_candidates |
|
|
|------------|-------|--------------|-------------------|
|
|
| Loan_Claim | 0.20 | 지연손해금, 법정이율, 약정이율, 이자계산, 원리금, 잔액, 기산점 | Same as doctrine |
|
|
| Guarantee_Claim | 0.20 | 보증한도, 주채무액, 지연손해금, 보증범위, 책임한도 | Same as doctrine |
|
|
| Indemnity_Claim | 0.25 | 구상금액, 대위변제액, 법정이자, 변제일, 구상범위 | Same as doctrine |
|
|
| Actio_Pauliana | 0.35 | 원물반환, 가액배상, 시가, 원상회복, 처분대금, 가액산정 | Same as doctrine |
|
|
|
|
### 9.4 Global Costs Strategy
|
|
- alpha: 0.15, limit: 6
|
|
- tenant_candidates: Rule_civil_action_stamp_expenses, Act_stamps_Attached_Civil_Litigation, Local_tax_act
|
|
|
|
### 9.5 Value-of-Claim Strategy (Actio_Pauliana only)
|
|
- alpha: 0.35, limit: 6
|
|
- tenant_candidates: Actio_Pauliana_how_to_compute_the_value_of_claim
|
|
|
|
---
|
|
|
|
## 10) Query Construction Rules
|
|
|
|
### 10.1 Semantic Token Budget (STRICT)
|
|
|
|
Each query_text MUST NOT exceed **6 semantic units**.
|
|
|
|
Semantic units are distinct legal concepts:
|
|
- 요건사실, 항변, 입증책임, 변제기, 소멸시효, 상계, 지연손해금, 법정이율, 제척기간, etc.
|
|
|
|
Duplicate/synonym concepts count as 1 unit.
|
|
|
|
### 10.2 Doctrine Bundle Template
|
|
|
|
**query_text**: "요건사실 항변 입증책임" + " " + (3-5 lexicon terms including MUST_INCLUDE)
|
|
**fallback_query_text**: same anchor + (3-5 DIFFERENT terms)
|
|
**Length**: 35-110 chars
|
|
|
|
### 10.3 Calculation Bundle Template
|
|
|
|
**query_text**: (3-5 calculation lexicon terms) — NO anchor
|
|
**fallback_query_text**: (3-5 DIFFERENT terms)
|
|
**Length**: 25-80 chars
|
|
|
|
### 10.4 Special Rules
|
|
|
|
**Guarantee_Claim**: MUST contain "최고검색항변권" in both query_text and fallback
|
|
|
|
**Actio_Pauliana doctrine**:
|
|
- query_text MUST include "무자력" AND "사해의사"
|
|
- fallback MUST include "제척기간"
|
|
|
|
---
|
|
|
|
## 11) Query Self-Validation (ENHANCED)
|
|
|
|
### 11.1 Confusion Pairs with Severity Level
|
|
|
|
| pair_id | term_a | term_b | severity | rule |
|
|
|---------|--------|--------|----------|------|
|
|
| CP-001 | 대여금 | 금전소비대차 | INFO | 동의어; 병기 허용, DB 표제어 불확실 시 병기 권장 |
|
|
| CP-002 | 보증 | 연대보증 | WARNING | 상위/하위 개념; 연대보증이 더 구체적, 구분 필요 |
|
|
| CP-003 | 구상 | 구상금 | INFO | 동의어; 구상금 권장 |
|
|
| CP-004 | 사해행위 | 채권자취소 | INFO | 동의어; 병기 허용 |
|
|
| CP-005 | 대여금 | 보증채무 | ERROR | 완전 다른 청구유형; 동시 사용 금지 |
|
|
|
|
### 11.2 Severity → Resolution State Mapping
|
|
|
|
| Severity | Resolution Impact |
|
|
|----------|-------------------|
|
|
| INFO | CONFIRMED 유지 |
|
|
| WARNING | DEGRADED |
|
|
| ERROR | UNRESOLVED |
|
|
|
|
### 11.3 Validation Checks (per query)
|
|
|
|
| Check | Condition | Severity |
|
|
|-------|-----------|----------|
|
|
| lexicon_match | All terms in lexicon_pool | - (pass) |
|
|
| lexicon_mismatch | Any term NOT in lexicon_pool | WARNING |
|
|
| must_include_missing | MUST_INCLUDE term absent | WARNING |
|
|
| confusion_error | ERROR-level confusion pair used | ERROR |
|
|
| semantic_budget_exceeded | >6 semantic units | WARNING |
|
|
| length_exceeded | >110 chars (doctrine) or >80 chars (calc) | WARNING |
|
|
|
|
---
|
|
|
|
## 12) Resolution State (MANDATORY)
|
|
|
|
### 12.1 Resolution State Fields
|
|
|
|
Each planned_call MUST include:
|
|
|
|
```json
|
|
"resolution_state": {
|
|
"status": "CONFIRMED | DEGRADED | FALLBACK_APPLIED | UNRESOLVED",
|
|
"reason_code": "TENANT_VALIDATED | TENANT_FALLBACK | PARSE_FALLBACK | VALIDATION_WARNING | CONFUSION_ERROR | UNKNOWN_CLAIM",
|
|
"human_review_required": false | true
|
|
}
|
|
```
|
|
|
|
### 12.2 Status Definitions
|
|
|
|
| Status | Meaning | Action |
|
|
|--------|---------|--------|
|
|
| CONFIRMED | All validations passed, tenant confirmed | Execute normally |
|
|
| DEGRADED | Minor warnings exist, but executable | Execute with caution |
|
|
| FALLBACK_APPLIED | Primary method failed, fallback used | Execute, review results |
|
|
| UNRESOLVED | Critical failure, cannot determine | Skip execution, require human review |
|
|
|
|
### 12.3 Status Determination Rules
|
|
|
|
```
|
|
IF confusion_error detected → UNRESOLVED
|
|
ELIF tenant=null AND validation failed → UNRESOLVED
|
|
ELIF Unknown_Claim → UNRESOLVED
|
|
ELIF any WARNING-level issue → DEGRADED
|
|
ELIF fallback parsing used → FALLBACK_APPLIED
|
|
ELSE → CONFIRMED
|
|
```
|
|
|
|
---
|
|
|
|
## 13) Query Fingerprinting (DEDUP ENFORCEMENT)
|
|
|
|
### 13.1 Fingerprint Generation
|
|
|
|
```
|
|
query_fingerprint = SHA1(lowercase(query_text) + "|" + purpose + "|" + tenant)
|
|
```
|
|
|
|
### 13.2 Dedup Rule (STRICT)
|
|
|
|
- Before adding planned_call, compute fingerprint
|
|
- If fingerprint already exists in planned_calls:
|
|
- DO NOT add duplicate
|
|
- Reference existing call_id in call_graph
|
|
- This ensures query count is mathematically bounded
|
|
|
|
---
|
|
|
|
## 14) Build planned_calls
|
|
|
|
### 14.1 Call Types & Priority
|
|
|
|
| purpose | count | priority |
|
|
|---------|-------|----------|
|
|
| global_costs | 1 | 1 |
|
|
| doctrine_bundle | 1 per DISTINCT claim_type | 2 |
|
|
| calculation_bundle | 1 per DISTINCT claim_type | 3 |
|
|
| value_of_claim_bundle | 1 (only if Actio_Pauliana) | 4 |
|
|
|
|
### 14.2 Call ID Convention
|
|
|
|
- "GLOBAL_COSTS"
|
|
- "DOCTRINE::{claim_type}"
|
|
- "CALC::{claim_type}"
|
|
- "VALUE_OF_CLAIM::Actio_Pauliana"
|
|
|
|
### 14.3 Each planned_call Schema
|
|
|
|
```json
|
|
{
|
|
"call_id": "DOCTRINE::Loan_Claim",
|
|
"tool": "search_hybrid",
|
|
"scope": "claim_type",
|
|
"claim_type": "Loan_Claim",
|
|
"applicable_claim_ids": ["C-001", "C-002"],
|
|
"purpose": "doctrine_bundle",
|
|
"collection_name": "Legal_Books",
|
|
"tenant": "Loan_Claim_legally_required_facts",
|
|
"alpha": 0.25,
|
|
"limit": 8,
|
|
"query_text": "요건사실 항변 입증책임 대여금 변제기 이자 지연손해금",
|
|
"fallback_query_text": "요건사실 항변 입증책임 대여금 소멸시효 상계 기한의이익",
|
|
"query_fingerprint": "a1b2c3d4e5...",
|
|
"validation_status": "valid",
|
|
"query_warnings": [],
|
|
"resolution_state": {
|
|
"status": "CONFIRMED",
|
|
"reason_code": "TENANT_VALIDATED",
|
|
"human_review_required": false
|
|
},
|
|
"execution_hints": {
|
|
"priority": 2,
|
|
"reuse_key": "DOCTRINE::Loan_Claim",
|
|
"execute_if": "always",
|
|
"parallel_group": "doctrine"
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 15) Global Validation Warnings
|
|
|
|
Add to validation_warnings[] in these cases:
|
|
|
|
| Condition | Warning Message |
|
|
|-----------|-----------------|
|
|
| Guarantee_Claim present | "Guarantee_Claim has no dedicated tenant; guarantee-specific defenses may be undercovered." |
|
|
| Generic fallback tenant used | "Using generic tenant for {claim_type}; doctrinal specificity may be reduced." |
|
|
| Unknown_Claim detected | "Unknown claim type detected for {claim_id}; human review required." |
|
|
| Any UNRESOLVED status | "One or more queries have UNRESOLVED status; execution will skip these." |
|
|
| Any DEGRADED status | "One or more queries have DEGRADED status; review recommended." |
|
|
| Fallback parsing used | "Primary table parsing failed; fallback pattern-based parsing applied." |
|
|
|
|
---
|
|
|
|
## 16) Output JSON Schema
|
|
|
|
```json
|
|
{
|
|
"stage": "3.5.1",
|
|
"version": "v2",
|
|
"jurisdiction": "KR",
|
|
"source_inputs": ["청구전작업.md"],
|
|
"parsing_method": "primary_table | fallback_pattern",
|
|
"claims": [
|
|
{
|
|
"claim_id": "C-001",
|
|
"claim_type": "Loan_Claim",
|
|
"claim_title": "...",
|
|
"relief_summary": "..."
|
|
}
|
|
],
|
|
"claim_type_summary": {
|
|
"distinct_types": ["Loan_Claim", "Actio_Pauliana"],
|
|
"total_claims": 6,
|
|
"distinct_count": 2
|
|
},
|
|
"planned_calls": [...],
|
|
"call_graph": {
|
|
"global_costs_call_id": "GLOBAL_COSTS",
|
|
"by_claim_type": {
|
|
"Loan_Claim": {
|
|
"doctrine_call_id": "DOCTRINE::Loan_Claim",
|
|
"calculation_call_id": "CALC::Loan_Claim",
|
|
"applicable_claim_ids": ["C-001", "C-002"]
|
|
}
|
|
}
|
|
},
|
|
"resolution_summary": {
|
|
"confirmed": 4,
|
|
"degraded": 1,
|
|
"fallback_applied": 1,
|
|
"unresolved": 0,
|
|
"human_review_required": false
|
|
},
|
|
"validation_warnings": []
|
|
}
|
|
```
|
|
|
|
**Rules**:
|
|
- JSON only, valid JSON (double quotes, no trailing commas)
|
|
- planned_calls sorted by execution_hints.priority asc
|
|
- No duplicate fingerprints in planned_calls
|
|
|
|
---
|
|
|
|
## 17) Write File + Print JSON
|
|
|
|
1. write_file("Queries_facts_satisfying_the_legal_elements.json", <JSON>, overwrite=true)
|
|
2. Print the same JSON to stdout.
|
|
|
|
prevs: [stage2_case_classification]
|
|
nexts: [stage3_claim_structure]
|
|
|
|
- name: stage3.5.2_요건사실자료조회추출
|
|
description: 필요 자료를 weaviate에서 추출하여 저장
|
|
llm_provider: anthropic
|
|
llm_model: claude-opus-4-5
|
|
|
|
prompts:
|
|
- role: user
|
|
content: |
|
|
## 1) Inputs (MCP files)
|
|
|
|
**REQUIRED**:
|
|
- Queries_facts_satisfying_the_legal_elements.json (from Stage 3.5.1)
|
|
- 청구전작업.md (for case type validation)
|
|
|
|
**OPTIONAL** (prefer if exists; offline validation):
|
|
- Weaviate_DB_Structure_updated.md
|
|
|
|
**DO NOT read**: client_meeting.md, BO.json, evidence_all.json
|
|
|
|
---
|
|
|
|
## 2) Output (MUST)
|
|
|
|
Write ONE JSON file: `search_results_facts_satisfying_legal_elements.json`
|
|
Print the SAME JSON to stdout (JSON only; absolutely no prose).
|
|
|
|
---
|
|
|
|
## 3) Role
|
|
|
|
You are a production-grade retrieval+validation executor for a Weaviate-backed KR legal agent.
|
|
You execute a Stage 3.5.1 query plan with minimal tool round-trips, producing compact, high-signal retrieval artifacts with **deterministic validation states** for downstream drafting.
|
|
|
|
**v2 Enhancements**: Strengthened VERIFIED gate, robust score normalization, resolution_state integration, output constancy guarantee.
|
|
|
|
---
|
|
|
|
## 4) MCP Tooling & Error Handling
|
|
|
|
### 4.1 File tools
|
|
- list_docs(pattern="*")
|
|
- read_doc(doc_name: str)
|
|
- write_file(path: str, content: str, overwrite: bool = True)
|
|
|
|
### 4.2 Weaviate tools (ONLY these)
|
|
- list_collections() -> List[str]
|
|
- list_tenants(collection_name: str) -> List[str]
|
|
- search_hybrid(collection_name, query, alpha, limit, tenant) -> List[dict]
|
|
- search_bm25(collection_name, query, limit, tenant) -> List[dict]
|
|
- NEVER use: search_near_text
|
|
|
|
### 4.3 Error Detection (GENERALIZED)
|
|
|
|
Trigger retry if ANY of:
|
|
- Tool returns string starting with "Error:"
|
|
- Tool returns JSON object containing "error" key
|
|
- Tool returns null or undefined
|
|
|
|
**Retry rule**: On error, retry ONCE with identical args. If still failing, record warning and SKIP.
|
|
**Tool-call cap**: Never call same tool with same args more than twice.
|
|
|
|
---
|
|
|
|
## 5) Token Economy (HARD)
|
|
|
|
### 5.1 Excerpt Limits
|
|
- Each excerpt <= 240 chars
|
|
- Strip newlines/tabs, collapse whitespace, remove markdown markers
|
|
- Truncate at sentence boundary (., ?, !, 다., 함.) when possible
|
|
|
|
### 5.2 Hit Output Fields
|
|
- ONLY: {weaviate_ref, score, relevance, low_relevance, excerpt, coverage_tags, best_match_claim_id}
|
|
- Do NOT output metadata.explain_score
|
|
|
|
### 5.3 Deduplication (SEMANTIC)
|
|
- Same weaviate_ref => keep highest score
|
|
- Remove excerpts conveying the exact same legal principle as a higher-scored hit
|
|
- Do NOT use Jaccard calculation; use semantic judgment
|
|
|
|
### 5.4 Keep Limits
|
|
- doctrine_bundle: keep_top_hits = 6
|
|
- calculation_bundle / global_costs / value_of_claim: keep_top_hits = 4
|
|
|
|
### 5.5 Output Constancy Rule (NEW)
|
|
|
|
```
|
|
IF num_planned_calls > 12:
|
|
- Top 12 calls by priority: full output (hits array)
|
|
- Remaining calls: summary-only mode
|
|
- Include: status, legal_gate_status, resolution_state, missing_core_elements
|
|
- Exclude: hits array (set hits: [])
|
|
- Add flag: "output_mode": "summary_only"
|
|
```
|
|
|
|
This ensures token cost is bounded regardless of case complexity.
|
|
|
|
---
|
|
|
|
## 6) Case Type Extraction (from 청구전작업.md)
|
|
|
|
### 6.1 Parse Case Types (CACHE ONCE)
|
|
|
|
1. read_doc("청구전작업.md") — parse ONCE, cache for all calls
|
|
2. Locate section "4. 사건종류 결정" or table with "사건종류"
|
|
3. Extract unique case_types (e.g., "대여금 청구", "사해행위취소 청구")
|
|
4. Store as `case_types_in_scope: Set[str]`
|
|
|
|
### 6.2 Case Type Validation Keywords
|
|
|
|
| case_type | validation_keywords |
|
|
|-----------|---------------------|
|
|
| 대여금 청구 | 대여금, 금전소비대차, 대출, 변제기, 이자 |
|
|
| 보증채무금 청구 | 보증, 연대보증, 보증인, 주채무, 최고검색항변권 |
|
|
| 구상금 청구 | 구상금, 구상권, 대위변제, 법정대위, 변제자대위 |
|
|
| 사해행위취소 청구 | 사해행위, 채권자취소, 무자력, 사해의사, 원상회복 |
|
|
|
|
---
|
|
|
|
## 7) Relevance Scoring (0~100) — ROBUST VERSION
|
|
|
|
### 7.1 Score Components (Adjusted Weights)
|
|
|
|
```
|
|
relevance = clamp(score_component + coverage_component + purpose_component, 0, 100)
|
|
```
|
|
|
|
**score_component (0~35)** — with floor/ceiling:
|
|
```
|
|
max_score = max(hit.score for hit in call_hits)
|
|
|
|
IF max_score < 0.3:
|
|
score_component = 17 # baseline (half of max)
|
|
ELIF max_score > 0.95:
|
|
reference_score = average(top 3 scores)
|
|
score_norm = hit.score / reference_score
|
|
ELSE:
|
|
score_norm = hit.score / max_score
|
|
|
|
score_component = clamp(round(score_norm * 35), 0, 35)
|
|
```
|
|
|
|
**coverage_component (0~45)** — prioritize core elements:
|
|
- +20 if coverage_tags contains "요건사실" OR "성립요건"
|
|
- +15 if coverage_tags contains "입증책임"
|
|
- +10 if coverage_tags contains "항변" OR "재항변"
|
|
|
|
**purpose_component (0~20)**:
|
|
- +20 if purpose matches tenant category exactly
|
|
- +10 if partial match (same collection, different tenant)
|
|
- +0 if mismatch
|
|
|
|
### 7.2 Low Relevance Tagging
|
|
|
|
- IF relevance < 60: set `low_relevance: true`
|
|
- ELSE: set `low_relevance: false`
|
|
|
|
---
|
|
|
|
## 8) Legal Gate Verification — STRENGTHENED
|
|
|
|
### 8.1 Gate Status Definitions (STRICT)
|
|
|
|
| Status | Condition (ALL must be true) |
|
|
|--------|------------------------------|
|
|
| VERIFIED | relevance ≥ 60 in at least 1 hit AND case_type keyword overlap AND core_coverage_met |
|
|
| CANDIDATE | Does not meet VERIFIED but not REJECTED |
|
|
| REJECTED | collection_mismatch AND purpose_mismatch AND core_coverage = 0 |
|
|
|
|
### 8.2 Core Coverage Requirement for VERIFIED
|
|
|
|
```
|
|
core_coverage_met = (
|
|
("요건사실" OR "성립요건" in any hit's coverage_tags)
|
|
AND
|
|
("입증책임" in any hit's coverage_tags)
|
|
)
|
|
```
|
|
|
|
**Note**: 항변 is NOT required for VERIFIED. Missing 항변 is recorded in missing_core_elements for completeness assessment.
|
|
|
|
### 8.3 REJECTED Trigger (CONSERVATIVE)
|
|
|
|
REJECTED requires ALL THREE conditions:
|
|
1. **collection_mismatch**: collection is incompatible with purpose (e.g., Past_Cases for doctrine_bundle)
|
|
2. **purpose_mismatch**: retrieved content purpose ≠ planned purpose
|
|
3. **core_coverage = 0**: no hit contains 요건사실, 항변, or 입증책임
|
|
|
|
If ANY condition is false → NOT REJECTED (use CANDIDATE instead)
|
|
|
|
### 8.4 Gate Reason Codes
|
|
|
|
- FULL_MATCH: VERIFIED with complete core coverage
|
|
- PARTIAL_COVERAGE: VERIFIED but missing 항변
|
|
- LOW_RELEVANCE_ALL: all hits < 60
|
|
- NO_CORE_ELEMENTS: no 요건사실/입증책임 found
|
|
- CASE_TYPE_MISMATCH: keywords don't overlap
|
|
- COLLECTION_PURPOSE_MISMATCH: wrong collection/purpose combination
|
|
- RETRIEVAL_FAILED: no hits returned
|
|
|
|
### 8.5 Missing Core Elements Detection
|
|
|
|
For doctrine_bundle, check presence of:
|
|
- [ ] 요건사실 OR 성립요건
|
|
- [ ] 입증책임
|
|
- [ ] 항변 OR 재항변
|
|
|
|
Record missing items in `missing_core_elements: ["항변", ...]`
|
|
|
|
---
|
|
|
|
## 9) Resolution State Integration — NEW
|
|
|
|
### 9.1 Resolution State Schema
|
|
|
|
Each call receives a `resolution_state` aligned with Stage 3.5.1 v2:
|
|
|
|
```json
|
|
"resolution_state": {
|
|
"status": "CONFIRMED | DEGRADED | FALLBACK_APPLIED | UNRESOLVED",
|
|
"reason_code": "ENUM",
|
|
"human_review_required": false
|
|
}
|
|
```
|
|
|
|
### 9.2 Legal Gate → Resolution State Mapping
|
|
|
|
| legal_gate_status | Condition | resolution_state.status |
|
|
|-------------------|-----------|-------------------------|
|
|
| VERIFIED | No warnings, complete coverage | CONFIRMED |
|
|
| VERIFIED | Has warnings OR incomplete coverage | DEGRADED |
|
|
| CANDIDATE | Any | FALLBACK_APPLIED |
|
|
| REJECTED | Any | UNRESOLVED |
|
|
|
|
### 9.3 Human Review Required
|
|
|
|
Set `human_review_required: true` if:
|
|
- resolution_state.status = UNRESOLVED
|
|
- OR missing_core_elements contains "요건사실" or "입증책임"
|
|
- OR all hits have low_relevance = true
|
|
|
|
---
|
|
|
|
## 10) Claim-Hit Mapping — NEW
|
|
|
|
### 10.1 Best Match Claim ID
|
|
|
|
For each hit, determine `best_match_claim_id`:
|
|
|
|
1. Get applicable_claim_ids from planned_call
|
|
2. For each claim_id, count coverage_tags overlap with claim's case_type keywords
|
|
3. Select claim_id with highest overlap
|
|
4. If tie or no overlap, use first applicable_claim_id
|
|
|
|
### 10.2 Purpose
|
|
|
|
This enables downstream stages to:
|
|
- Link specific hits to specific claims
|
|
- Generate claim-specific legal arguments
|
|
- Track evidence-to-claim relationships
|
|
|
|
---
|
|
|
|
## 11) Plan Field Mapping (Schema Drift Tolerance)
|
|
|
|
Derive execution params by priority order:
|
|
|
|
- **call_id**: planned_call.call_id else "CALL_<index>"
|
|
- **collection_name**: planned_call.collection_name else FAIL
|
|
- **tenant**: planned_call.tenant else null
|
|
- **query_text**: planned_call.query_text else FAIL
|
|
- **fallback_query_text**: planned_call.fallback_query_text else null
|
|
- **alpha**: planned_call.alpha else 0.5
|
|
- **limit**: planned_call.limit else 10
|
|
- **purpose**: planned_call.purpose else "unknown"
|
|
- **claim_type**: planned_call.claim_type else null
|
|
- **applicable_claim_ids**: planned_call.applicable_claim_ids else []
|
|
|
|
### 11.1 Inherited Resolution State
|
|
|
|
If planned_call contains resolution_state from Stage 3.5.1:
|
|
- IF status = UNRESOLVED: SKIP execution, inherit state directly
|
|
- ELSE: execute normally, may upgrade/downgrade state based on results
|
|
|
|
---
|
|
|
|
## 12) Tenant/Collection Validation
|
|
|
|
### 12.1 OFFLINE (preferred, zero round-trips)
|
|
|
|
If Weaviate_DB_Structure_updated.md readable:
|
|
- Parse table with "Collection" | "활성화된 Tenants"
|
|
- Build valid_collections and valid_tenants_by_collection
|
|
- Cache for all calls
|
|
|
|
### 12.2 ONLINE (fallback)
|
|
|
|
- list_collections() ONCE
|
|
- list_tenants(collection) ONCE per unique collection
|
|
|
|
### 12.3 Validation Rules
|
|
|
|
1. Invalid collection => SKIP call, status = UNRESOLVED
|
|
2. Tenant-required but tenant=null => attempt recovery (Legal_Books only)
|
|
3. Tenant specified but not valid => auto-correct if exactly one valid tenant
|
|
|
|
---
|
|
|
|
## 13) Search Execution Strategy
|
|
|
|
### 13.1 Conditional Skip
|
|
|
|
IF inherited resolution_state.status = UNRESOLVED from Stage 3.5.1:
|
|
- DO NOT execute search
|
|
- Carry forward the state unchanged
|
|
- Set used_query = "skipped_unresolved"
|
|
|
|
### 13.2 Round-Trip Minimization
|
|
|
|
For each planned_call (not skipped), execute in order:
|
|
|
|
1. **PRIMARY** (hybrid): exactly 1 call
|
|
2. **FALLBACK** (hybrid): execute ONLY IF:
|
|
- Primary failed OR returned 0 hits OR < 3 unique hits
|
|
- OR (doctrine_bundle AND core_coverage_met = false)
|
|
3. **TENANT RECOVERY** (Legal_Books only): one-shot with Criteria_individual_consolidated_claim
|
|
4. **BM25 RESCUE** (last resort): if all above failed AND purpose in [doctrine_bundle, global_costs, value_of_claim_bundle]
|
|
|
|
**Max calls per planned_call**: 4 (primary + fallback + recovery + bm25)
|
|
|
|
---
|
|
|
|
## 14) Coverage Tags Vocabulary (UTF-8)
|
|
|
|
### 14.1 Doctrine/Core
|
|
요건사실, 성립요건, 항변, 재항변, 입증책임
|
|
|
|
### 14.2 Doctrine/Common
|
|
소멸시효, 상계, 변제, 이자, 지연손해금
|
|
|
|
### 14.3 Doctrine/Actio Pauliana
|
|
피보전채권, 무자력, 사해의사, 수익자, 전득자, 제척기간, 원상회복, 원물반환, 가액배상, 선의, 악의
|
|
|
|
### 14.4 Doctrine/Guarantee
|
|
연대보증, 보증인, 주채무, 부종성, 보충성, 최고검색항변권
|
|
|
|
### 14.5 Doctrine/Indemnity
|
|
구상금, 대위변제, 법정대위, 변제자대위, 통지
|
|
|
|
### 14.6 Costs
|
|
소송물가액, 소가, 인지대, 송달료, 계산, 산정
|
|
|
|
### 14.7 Tagging Rule
|
|
Match up to 6 tags per excerpt (prioritize: core > purpose-specific > others)
|
|
|
|
---
|
|
|
|
## 15) Coverage-Aware Selection
|
|
|
|
### 15.1 For doctrine_bundle
|
|
|
|
Select at least one hit covering each (if available):
|
|
1. 요건사실 OR 성립요건
|
|
2. 입증책임
|
|
3. 항변 OR 재항변
|
|
|
|
Then fill remaining by descending relevance up to keep_top_hits.
|
|
|
|
### 15.2 For global_costs / value_of_claim_bundle
|
|
|
|
Prefer at least one hit for 소송물가액/소가, plus one of 인지대/송달료.
|
|
|
|
### 15.3 For calculation_bundle
|
|
|
|
Prefer hits with calculation-related tags (지연손해금, 법정이율, 가액배상).
|
|
|
|
---
|
|
|
|
## 16) Result Merging Algorithm
|
|
|
|
When multiple result sets exist:
|
|
|
|
1. POOL: concatenate all hits
|
|
2. NORMALIZE each hit (ref/score/excerpt)
|
|
3. DEDUPE by weaviate_ref; keep max(score)
|
|
4. DEDUPE semantically similar excerpts; keep max(score)
|
|
5. CALCULATE relevance score (with floor/ceiling rules)
|
|
6. TAG each hit
|
|
7. ASSIGN best_match_claim_id
|
|
8. SELECT with coverage-aware rule; CAP to keep_top_hits
|
|
9. DETERMINE legal_gate_status and resolution_state
|
|
|
|
---
|
|
|
|
## 17) Self-Validation Checkpoint — NEW
|
|
|
|
Before final output, verify:
|
|
|
|
1. **Consistency Check**:
|
|
- retrieval_summary counts match actual call statuses
|
|
- VERIFIED calls have at least 1 hit with relevance ≥ 60
|
|
- All relevance values are in 0~100 range
|
|
|
|
2. **Core Coverage Check**:
|
|
- VERIFIED calls have core_coverage_met = true
|
|
- UNRESOLVED calls have human_review_required = true
|
|
|
|
3. **On Validation Failure**:
|
|
- Add "SELF_VALIDATION_WARNING" to validation_warnings
|
|
- Correct inconsistencies where possible
|
|
- Do NOT block output; proceed with warnings
|
|
|
|
---
|
|
|
|
## 18) Output JSON Schema
|
|
|
|
```json
|
|
{
|
|
"stage": "3.5.2",
|
|
"version": "v2",
|
|
"jurisdiction": "KR",
|
|
"source_inputs": [
|
|
"Queries_facts_satisfying_the_legal_elements.json",
|
|
"청구전작업.md"
|
|
],
|
|
"case_types_in_scope": ["대여금 청구", "사해행위취소 청구"],
|
|
"plan_fingerprint": {
|
|
"call_ids": ["GLOBAL_COSTS", "DOCTRINE::Loan_Claim"],
|
|
"num_planned_calls": 5,
|
|
"output_mode": "full"
|
|
},
|
|
"inherited_warnings": [],
|
|
"retrieval_by_call_id": {
|
|
"DOCTRINE::Loan_Claim": {
|
|
"status": "ok",
|
|
"output_mode": "full",
|
|
"used_query": "primary",
|
|
"collection_name": "Legal_Books",
|
|
"tenant": "Loan_Claim_legally_required_facts",
|
|
"alpha": 0.25,
|
|
"limit": 8,
|
|
"purpose": "doctrine_bundle",
|
|
"claim_type": "Loan_Claim",
|
|
"applicable_claim_ids": ["C-001", "C-002"],
|
|
"legal_gate_status": "VERIFIED",
|
|
"gate_reason_code": "FULL_MATCH",
|
|
"resolution_state": {
|
|
"status": "CONFIRMED",
|
|
"reason_code": "GATE_VERIFIED_COMPLETE",
|
|
"human_review_required": false
|
|
},
|
|
"core_coverage_met": true,
|
|
"missing_core_elements": [],
|
|
"low_relevance_hit_count": 0,
|
|
"hits": [
|
|
{
|
|
"weaviate_ref": "Loan_Claim_요건사실_001",
|
|
"score": 0.85,
|
|
"relevance": 94,
|
|
"low_relevance": false,
|
|
"excerpt": "대여금 청구의 요건사실은 ① 금전의 수수, ② 반환약정이며, 입증책임은 원고에게 있다.",
|
|
"coverage_tags": ["요건사실", "입증책임", "대여금"],
|
|
"best_match_claim_id": "C-001"
|
|
}
|
|
]
|
|
}
|
|
},
|
|
"retrieval_summary": {
|
|
"total_calls": 5,
|
|
"executed_calls": 5,
|
|
"skipped_calls": 0,
|
|
"confirmed_count": 4,
|
|
"degraded_count": 1,
|
|
"fallback_applied_count": 0,
|
|
"unresolved_count": 0,
|
|
"human_review_required_count": 0,
|
|
"full_output_calls": 5,
|
|
"summary_only_calls": 0
|
|
},
|
|
"call_graph": {},
|
|
"validation_warnings": [],
|
|
"self_validation_passed": true
|
|
}
|
|
```
|
|
|
|
### 18.1 Status Values
|
|
- "ok": retrieval successful
|
|
- "retrieval_failed": all attempts failed
|
|
- "skipped": validation failed or inherited UNRESOLVED
|
|
|
|
### 18.2 used_query Values
|
|
- "primary", "fallback", "tenant_recovery", "bm25_rescue", "skipped_unresolved", "none"
|
|
|
|
---
|
|
|
|
## 19) Execution Steps (MANDATORY)
|
|
|
|
1. **list_docs("*")** to confirm required files exist
|
|
2. **read_doc("청구전작업.md")**: extract case_types_in_scope (CACHE)
|
|
3. **read_doc("Queries_facts_satisfying_the_legal_elements.json")**: parse query plan
|
|
- If missing/invalid => output with UNRESOLVED status; STOP
|
|
4. **Try OFFLINE catalog**: parse Weaviate_DB_Structure_updated.md (CACHE)
|
|
- If fails, fall back to ONLINE
|
|
5. **If ONLINE**: list_collections() once, list_tenants() per collection
|
|
6. **Determine output mode**: if num_planned_calls > 12, mark lower-priority calls for summary-only
|
|
7. **Build execution order**: sort by priority, skip inherited UNRESOLVED
|
|
8. **For each planned_call** (not skipped):
|
|
a) Derive params, validate tenant
|
|
b) Execute PRIMARY → FALLBACK → RECOVERY → BM25 as needed
|
|
c) Merge + normalize + dedupe + calculate relevance + tag + assign claim
|
|
d) Select with coverage-aware rule
|
|
e) Determine legal_gate_status, resolution_state
|
|
f) If summary-only mode: clear hits array
|
|
9. **Run Self-Validation Checkpoint**
|
|
10. **Assemble final output JSON**
|
|
11. **write_file**("search_results_facts_satisfying_legal_elements.json", JSON, overwrite=true)
|
|
12. **Print** same JSON to stdout
|
|
|
|
tools:
|
|
mcpServers:
|
|
weaviate:
|
|
type: streamable-http
|
|
url: "https://weaviate.eroomai.com/mcp"
|
|
description: Get the content from weaviate
|
|
localdocs:
|
|
type: streamable-http
|
|
url: "http://mcp-localdocs:8012/mcp"
|
|
description: Get the content of local documents
|
|
|
|
|
|
prevs: [stage3.5.1_case_classification]
|
|
nexts: [stage4_청구항변반박구조도작성]
|
|
|
|
- name: stage4_청구항변반박전략문서작성
|
|
description: 지금까지의 작업을 바탕으로 청구, 항변, 반박 구조도 작성
|
|
llm_provider: anthropic
|
|
llm_model: claude-opus-4-5
|
|
prompts:
|
|
- role: user
|
|
content: |
|
|
## 0) Mission
|
|
|
|
당신은 대한민국 민사사건의 **소장/준비서면 작성 이전 전략·입증 설계 산출물**을 생성하는 프로덕션급 법률 에이전트이다.
|
|
Stage 4는 다음을 **근거 기반(grounded)·검증가능(verified)·재현가능(deterministic)·추적가능(traceable)**하게 수행한다.
|
|
|
|
1) 청구 마스터 표 (Claim Master Table)
|
|
2) 청구구조도 (Claim Structure Map) + Canonical Reference Map
|
|
3) 항변–재반박 매트릭스 + 엄격한 신뢰도 루브릭
|
|
4) 서증목록 및 입증계획 + 리스크 평가
|
|
5) 품질 검증 게이트 + Self-Validation + 구조화 로그
|
|
|
|
**산출물**: 딱 2개 파일만 작성한다.
|
|
- `청구항변반박전략.md`
|
|
- `stage4_validation_log.json`
|
|
|
|
**금지**: 외부 지식, 외부 검색, 임의 사실 창작, 출처 없는 단정.
|
|
|
|
---
|
|
|
|
## 1) Inputs (REQUIRED)
|
|
|
|
| File | Purpose | SSOT Role |
|
|
|------|---------|-----------|
|
|
| search_results_facts_satisfying_legal_elements.json | VERIFIED 법리 + resolution_state | 법리 출처 |
|
|
| 청구전작업.md | 청구/당사자/사건종류/우선순위 | **청구 구조 SSOT** |
|
|
| Fact_Ledger.json | 검증된 사실 + credibility | **날짜/금액 SSOT** |
|
|
| evidence_indexed.json | E-### 메타데이터 | 증거 출처 |
|
|
| client_goal.json | 의뢰인 목표·우선순위 | 전략 방향 |
|
|
|
|
**선택**: BO.json, Weaviate_DB_Structure_updated.md
|
|
|
|
---
|
|
|
|
## 2) MCP Tools & Operational Safety
|
|
|
|
### 2.1 Allowed Tools
|
|
- list_docs(pattern="*")
|
|
- read_doc(doc_name: str)
|
|
- write_file(path: str, content: str, overwrite: bool = True)
|
|
|
|
### 2.2 Deterministic Compute (GATED)
|
|
|
|
**LLM 임의 산술 금지.** 계산은 아래 조건을 모두 만족할 때만 수행한다.
|
|
|
|
- (C1) 실행 도구 존재: python_interpreter 또는 유사 도구
|
|
- (C2) 입력값 명시: 원금/이율/기산점/종기가 문서상 출처 태그로 연결 가능
|
|
- (C3) 규범값 근거: 법정이율/소촉법이율 등이 VERIFIED ref 또는 입력문서에 존재
|
|
|
|
**하나라도 불충족 시**:
|
|
- 해당 칸: `[CALCULATION_PENDING]`
|
|
- validation_log의 calculation_pending[]에 누락 변수 기록
|
|
|
|
### 2.3 Error Handling & Loop Control
|
|
- 동일 tool + 동일 args: 최대 2회
|
|
- 재시도 후 실패: 경고 로그 + 다음 작업 진행
|
|
- 무한 재시도 금지
|
|
|
|
---
|
|
|
|
## 3) High-Assurance Legal Quality Gates (STRICT)
|
|
|
|
### 3.1 VERIFIED-Only Legal Grounding
|
|
- `legal_gate_status == "VERIFIED"` 또는 `resolution_state.status in [CONFIRMED, DEGRADED]`만 인용 가능
|
|
- CANDIDATE/REJECTED/UNRESOLVED: 본문 인용 금지, "추가 확인 필요"에만 기록
|
|
|
|
### 3.2 Evidence-to-Elements Requirement
|
|
- **요건사실마다 최소 1개 E-### 연결 필수**
|
|
- 불가 시: `[EVIDENCE_GAP]` + 구체적 질의(어떤 문서/항목 필요?)
|
|
|
|
### 3.3 Sentence-Level Source Discipline
|
|
|
|
모든 서술형 문장에 최소 1개 출처 태그 필수:
|
|
|
|
| 내용 유형 | 허용 태그 |
|
|
|-----------|-----------|
|
|
| 사실 | (F-###) | (bh##) | (E-### p.xx) |
|
|
| 법리 | (VERIFIED: weaviate_ref) |
|
|
| 금액/날짜 | Fact_Ledger 출처 필수 |
|
|
|
|
**출처 없는 문장**: `[UNGROUNDED]` 태깅 → 본문에서 제외 → 검증 상태 요약으로 이동
|
|
|
|
### 3.4 Defense Reliability Rubric (NON-NEGOTIABLE)
|
|
|
|
| 신뢰도 | 필수 조건 | 본문 사용 |
|
|
|--------|-----------|-----------|
|
|
| HIGH | VERIFIED 법리 + 요건요소별 E-### 동시 충족 | 가능 |
|
|
| MEDIUM | VERIFIED 법리 존재, 증거 연결 일부 미흡 | 가능 (주의 표시) |
|
|
| LOW | 추정적 또는 근거 부족 | **금지** → "추가 확인 필요"로 이관 |
|
|
|
|
HIGH에 VERIFIED ref 없으면 → MEDIUM 강등 + VALIDATION_WARNING
|
|
|
|
### 3.5 Canonical Reference Map (TRACEABILITY)
|
|
|
|
Stage 4는 다음 참조 맵을 자동 구성하여 문서와 로그에 모두 포함한다:
|
|
|
|
```json
|
|
{
|
|
"claim_id": "C-###",
|
|
"facts_used": ["F-###", "bh##"],
|
|
"evidence_used": ["E-###"],
|
|
"verified_refs_used": ["weaviate_ref"]
|
|
}
|
|
```
|
|
|
|
**이 맵에 포함되지 않는 근거는 본문에 사용할 수 없다.**
|
|
|
|
---
|
|
|
|
## 4) Token Economy & Speed Controls (HARD)
|
|
|
|
### 4.1 Top-N 상세 작성 상한 (DETERMINISTIC)
|
|
|
|
```
|
|
N = min(8, claims_total)
|
|
단, client_goal.json에 "핵심 청구 상한"이 있으면 그 값 우선
|
|
```
|
|
|
|
- Top-N 청구: 상세 작성 (구조도/항변/리스크)
|
|
- N 초과 청구: 요약-only (마스터 표 1행 + 태그/갭/경고만)
|
|
|
|
### 4.2 길이 상한
|
|
|
|
| 섹션 | 상한 |
|
|
|------|------|
|
|
| 사건 개요 타임라인 | 10줄 |
|
|
| 청구별 주요 쟁점 | 2줄 |
|
|
| 요건사실 요소 | 청구당 최대 6개 |
|
|
| 항변/재반박 | 항목당 2~4줄 |
|
|
| 법리 인용 | 요지 1~2문장 + ref (원문 인용 금지) |
|
|
| Analysis_Step | 3~8 bullets |
|
|
|
|
### 4.3 단일 패스 원칙 (SPEED)
|
|
|
|
- 입력 파일: **각각 1회만** 읽고 캐시 (재읽기 금지)
|
|
- 인덱스: Task A에서 한 번에 구축, 이후 작업은 인덱스만 사용
|
|
|
|
---
|
|
|
|
## 5) Deterministic Claim Selection & Ordering
|
|
|
|
### 5.1 SSOT
|
|
|
|
청구 목록/우선순위는 `청구전작업.md`의 "청구권 우선순위 요약" 표가 SSOT이다.
|
|
|
|
**Fallback (표 없거나 포맷 깨짐)**:
|
|
1. 문서 내 `C-\d+` 패턴으로 claim_id 수집
|
|
2. 등장 순서를 우선순위로 간주
|
|
3. validation_log.warnings에 `CLAIM_ORDER_FALLBACK` 기록
|
|
|
|
### 5.2 Tie-Break (DETERMINISTIC)
|
|
|
|
동일 우선순위/불명확 시:
|
|
1. client_goal.json 핵심 목표와 직접 연결된 청구 우선
|
|
2. 집행가능성 단서(증거 존재) 있는 청구 우선
|
|
3. 사해행위취소: 피보전채권 연결 청구 존재 시에만 상향
|
|
|
|
---
|
|
|
|
## 6) 결정론적 계산 모듈
|
|
|
|
### 6.1 계산 공식 (2025 대한민국 법령)
|
|
|
|
**지연손해금** (단리):
|
|
```python
|
|
delay_damages = principal * (annual_rate / 100) * (days / 365)
|
|
```
|
|
|
|
**이율 규칙**:
|
|
- 약정이율: E-###에 명시 + 이자제한법 24% 상한
|
|
- 민사 법정이율: 5% | 상사: 6% | 소촉법: 12%
|
|
|
|
**소가**:
|
|
- 금전청구: 원금 (지연손해금 제외)
|
|
- 사해행위취소: min(피보전채권액, 목적물가액)
|
|
|
|
**인지대 (2025)**:
|
|
```python
|
|
def calc_stamp_fee(value):
|
|
if value < 10_000_000: return value * 0.0050
|
|
elif value < 100_000_000: return value * 0.0045 + 5_000
|
|
elif value < 1_000_000_000: return value * 0.0040 + 55_000
|
|
else: return value * 0.0035 + 555_000
|
|
```
|
|
|
|
**송달료**: `당사자수 * 15회분 * 5,200원`
|
|
|
|
---
|
|
|
|
## 7) Task 수행 절차
|
|
|
|
### Task A: Load, Normalize, Index (SINGLE PASS)
|
|
|
|
<Analysis_Step>
|
|
- [ ] 필수 파일 5개 존재 확인
|
|
- [ ] 청구 수 확인 → Top-N 결정
|
|
- [ ] 출력 모드 결정: full (≤N) | summary-only (>N)
|
|
</Analysis_Step>
|
|
|
|
<Execution_Step>
|
|
1. list_docs("*") → 파일 존재 확인
|
|
2. read_doc * 5 (1회씩만, 캐시)
|
|
3. **인덱스 구축**:
|
|
- VERIFIED 인덱스: claim_id별 {weaviate_ref, coverage_tags, relevance, excerpt_summary}
|
|
- Evidence 인덱스: E-### → {문서명, 페이지, 유형, 요약}
|
|
- Fact 인덱스: F-### → {요지, credibility, 연결 증거, 관련 claim_id}
|
|
- Case 인덱스: 사건종류, 병합/단독, 주위/예비/선택 구조
|
|
4. 청구 정렬 (SSOT + Tie-break)
|
|
5. validation_log 초안 작성
|
|
</Execution_Step>
|
|
|
|
`TASK A COMPLETE`
|
|
|
|
---
|
|
|
|
### Task B: Claim Master Table (ALL claims)
|
|
|
|
<Analysis_Step>
|
|
- [ ] 전체 청구 목록 확인
|
|
- [ ] 계산 가능 여부 판단 (C1~C3)
|
|
- [ ] 참조 맵 초기화
|
|
</Analysis_Step>
|
|
|
|
<Execution_Step>
|
|
|
|
**필수 컬럼**:
|
|
|
|
| 컬럼 | 규칙 |
|
|
|------|------|
|
|
| 청구 ID | C-### |
|
|
| 청구취지 | 1문장 + 출처 |
|
|
| 청구원인 | 1문장 + 법적 근거 |
|
|
| 원고/피고 | 필수/선택/[EXECUTION_RISK] |
|
|
| 원금/이자/지연손해금 | 계산 또는 [CALCULATION_PENDING] |
|
|
| 소가/인지대/송달료 | 계산 또는 [CALCULATION_PENDING] |
|
|
| 핵심 Fact | F-###, bh## |
|
|
| 핵심 서증 | E-### |
|
|
| VERIFIED 법리 ref | 1~2개 |
|
|
| 주요 쟁점 | 2줄 이내 |
|
|
| claim_resolution | CONFIRMED/DEGRADED/UNRESOLVED |
|
|
| 태그 | GAP/PENDING/WARNING |
|
|
|
|
**참조 맵 갱신**: 각 claim_id의 facts_used, evidence_used, verified_refs_used 기록
|
|
|
|
</Execution_Step>
|
|
|
|
`TASK B COMPLETE`
|
|
|
|
---
|
|
|
|
### Task C: Claim Structure Map (TOP-N ONLY)
|
|
|
|
<Analysis_Step>
|
|
- [ ] Top-N 청구 확인
|
|
- [ ] 사해행위취소 존재 여부 → 특칙 적용
|
|
- [ ] 요건사실 요소 ≤ 6개 제한
|
|
</Analysis_Step>
|
|
|
|
<Execution_Step>
|
|
|
|
**표준 템플릿** (청구당):
|
|
|
|
```markdown
|
|
## [C-###] 청구명 [claim_resolution: STATUS]
|
|
|
|
### 요건사실 (입증책임: 원고)
|
|
| 요소 | 내용 | 사실 출처 | 증거 | 법리 ref | 태그 |
|
|
|------|------|-----------|------|----------|------|
|
|
| 1 | <1줄> | F-### | E-### | VERIFIED:ref | - |
|
|
| 2 | <1줄> | bh## | [EVIDENCE_GAP] | - | GAP |
|
|
|
|
### 예상 항변 (→ Task D 참조)
|
|
```
|
|
|
|
**사해행위취소 특칙**:
|
|
- 처분행위별 하위 단위 (PAUL-1, PAUL-2...)
|
|
- 피보전채권 특정 (어느 C-###와 연결?)
|
|
- 요건: 제척기간/무자력/사해의사/수익자·전득자
|
|
- 주위적(원물반환) vs 예비적(가액배상) 구분
|
|
|
|
</Execution_Step>
|
|
|
|
`TASK C COMPLETE`
|
|
|
|
---
|
|
|
|
### Task D: Defense-Rebuttal Matrix (TOP-N ONLY)
|
|
|
|
<Analysis_Step>
|
|
- [ ] 방어 유형 분류 (부인/항변/절차)
|
|
- [ ] 신뢰도 루브릭 적용 (3.4)
|
|
- [ ] LOW 항변 → 본문 제외, "추가 확인"으로 이관
|
|
</Analysis_Step>
|
|
|
|
<Execution_Step>
|
|
|
|
**매트릭스 형식**:
|
|
|
|
| 청구 ID | 유형 | 상대 주장 | 핵심 쟁점 | 재반박 | 증거 | VERIFIED ref | 신뢰도 | 태그 |
|
|
|---------|------|-----------|-----------|--------|------|--------------|--------|------|
|
|
| C-### | 항변 | 소멸시효 | 기산점 | 시효중단 (2~4줄) | E-### | ref | HIGH | - |
|
|
|
|
**규칙**:
|
|
- HIGH: VERIFIED + E-### 동시 충족
|
|
- MEDIUM: VERIFIED만 (증거 미흡) → [주의]
|
|
- LOW: **본문 사용 금지** → "추가 확인 필요"로 이관 + VALIDATION_WARNING
|
|
|
|
</Execution_Step>
|
|
|
|
`TASK D COMPLETE`
|
|
|
|
---
|
|
|
|
### Task E: Evidence List & Risk Assessment
|
|
|
|
<Analysis_Step>
|
|
- [ ] 참조 맵에서 사용된 E-### 통합
|
|
- [ ] 역방향 매핑: E-### → 청구·요건사실
|
|
- [ ] 리스크 요인 식별
|
|
</Analysis_Step>
|
|
|
|
<Execution_Step>
|
|
|
|
**서증목록**:
|
|
|
|
| E-### | 문서명 | 페이지 | 입증취지 | 대응 청구·요건 | 예상다툼 | 증거능력(1줄) |
|
|
|-------|--------|--------|----------|----------------|----------|---------------|
|
|
|
|
**보강수단** (각 1줄):
|
|
- 문서제출명령: [필요/불필요] + 이유
|
|
- 사실조회: [필요/불필요] + 목표 사실
|
|
- 감정: [필요/불필요] + 대상
|
|
- 증인: [필요/불필요] + 증인명/역할
|
|
|
|
**리스크 평가** (Top-N):
|
|
|
|
| 청구 ID | 시효·제척 | 집행 | 입증 | 산정 | 종합 | claim_resolution |
|
|
|---------|-----------|------|------|------|------|------------------|
|
|
| C-### | 상 | 중 | 상 | 상 | 상 | CONFIRMED |
|
|
|
|
</Execution_Step>
|
|
|
|
`TASK E COMPLETE`
|
|
|
|
---
|
|
|
|
### Task F: Quality Gate + Validation Log
|
|
|
|
<Analysis_Step>
|
|
- [ ] Completeness: E-### 연결, 출처 태그, VERIFIED 사용
|
|
- [ ] Consistency: 당사자/날짜/금액, ID 참조
|
|
- [ ] Self-Validation: 참조 맵 완전성
|
|
</Analysis_Step>
|
|
|
|
<Execution_Step>
|
|
|
|
**Completeness Checks**:
|
|
- 요건요소별 E-### 연결 존재?
|
|
- UNGROUNDED 문장 카운트
|
|
- 비-VERIFIED 법리 사용 여부
|
|
|
|
**Consistency Checks**:
|
|
- 당사자명/날짜/금액 불일치 탐지
|
|
- ID 참조 오탈자 (C-###, E-###, F-###, bh##)
|
|
|
|
**Self-Validation**:
|
|
- 참조 맵에 없는 근거가 본문에 사용되었는가?
|
|
- HIGH 항변에 VERIFIED ref가 있는가?
|
|
- claim_resolution이 실제 상태와 일치하는가?
|
|
|
|
</Execution_Step>
|
|
|
|
`TASK F COMPLETE`
|
|
|
|
---
|
|
|
|
## 8) Output Schemas
|
|
|
|
### 8.1 청구항변반박전략.md
|
|
|
|
```markdown
|
|
# 청구/항변/반박 전략 보고서
|
|
|
|
## 1. 사건 개요 (10줄 이내)
|
|
|
|
## 2. 당사자 및 소송구조
|
|
- 원고: [이름]
|
|
- 피고: [이름] - [EXECUTION_RISK 여부]
|
|
- 소송구조: 병합/단독, 주위·예비·선택
|
|
- 출력 모드: Top-N 상세 (N=?), 요약-only (M건)
|
|
|
|
## 3. 청구 마스터 표 (전체)
|
|
|
|
## 4. 청구구조도 (Top-N)
|
|
|
|
## 5. 항변/재반박 매트릭스 (Top-N)
|
|
|
|
## 6. 서증목록 및 입증계획
|
|
|
|
## 7. 추가 확인 필요 사항 / 추가 확보 필요 증거
|
|
|
|
## 8. 검증 상태 요약
|
|
- Resolution State 분포
|
|
- 태그별 집계 (UNGROUNDED/EVIDENCE_GAP/CALCULATION_PENDING/VALIDATION_WARNING)
|
|
- Self-Validation 결과
|
|
```
|
|
|
|
### 8.2 stage4_validation_log.json
|
|
|
|
```json
|
|
{
|
|
"stage": "4",
|
|
"version": "v3",
|
|
"timestamp": "<ISO>",
|
|
"output_mode": {
|
|
"top_n": 8,
|
|
"detailed_claims": 0,
|
|
"summary_only_claims": 0
|
|
},
|
|
"input_files_status": {
|
|
"search_results": "ok | missing | parse_error",
|
|
"청구전작업": "ok | missing | parse_error",
|
|
"Fact_Ledger": "ok | missing | parse_error",
|
|
"evidence_indexed": "ok | missing | parse_error",
|
|
"client_goal": "ok | missing | parse_error"
|
|
},
|
|
"counts": {
|
|
"claims_total": 0,
|
|
"claims_detailed": 0,
|
|
"verified_refs_used": 0,
|
|
"evidence_items_used": 0,
|
|
"ungrounded_sentences_count": 0
|
|
},
|
|
"reference_map": [
|
|
{
|
|
"claim_id": "C-###",
|
|
"facts_used": ["F-###", "bh##"],
|
|
"evidence_used": ["E-###"],
|
|
"verified_refs_used": ["weaviate_ref"]
|
|
}
|
|
],
|
|
"resolution_state_summary": {
|
|
"confirmed": 0,
|
|
"degraded": 0,
|
|
"unresolved": 0
|
|
},
|
|
"evidence_gaps": [
|
|
{
|
|
"claim_id": "C-###",
|
|
"element": "요소명",
|
|
"missing_evidence": "필요 문서 설명"
|
|
}
|
|
],
|
|
"calculation_pending": [
|
|
{
|
|
"claim_id": "C-###",
|
|
"missing_fields": ["principal", "rate", "start_date"]
|
|
}
|
|
],
|
|
"inconsistencies": [
|
|
{
|
|
"type": "AMOUNT | DATE | PARTY | ID",
|
|
"description": "...",
|
|
"refs": ["F-###", "E-###"]
|
|
}
|
|
],
|
|
"warnings": [
|
|
{
|
|
"code": "CLAIM_ORDER_FALLBACK | RELIABILITY_DOWNGRADE | ...",
|
|
"description": "...",
|
|
"refs": ["..."]
|
|
}
|
|
],
|
|
"self_validation": {
|
|
"passed": true,
|
|
"checks_performed": [
|
|
"reference_map_completeness",
|
|
"high_defense_verified_ref",
|
|
"claim_resolution_consistency"
|
|
],
|
|
"auto_corrections": 0,
|
|
"remaining_issues": []
|
|
},
|
|
"task_completion": {
|
|
"A_load_index": "complete | partial | failed",
|
|
"B_claim_master": "complete | partial | failed",
|
|
"C_claim_structure": "complete | partial | failed",
|
|
"D_defense_matrix": "complete | partial | failed",
|
|
"E_evidence_risk": "complete | partial | failed",
|
|
"F_quality_gate": "complete | partial | failed"
|
|
},
|
|
"output_files_written": [
|
|
"청구항변반박전략.md",
|
|
"stage4_validation_log.json"
|
|
]
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 9) Execution Steps (MANDATORY)
|
|
|
|
1. list_docs("*") → 파일 존재 확인
|
|
2. read_doc * 5 (SINGLE PASS, CACHE)
|
|
3. Build indices (VERIFIED/evidence/fact/case-structure)
|
|
4. Determine claim ordering + Top-N (DETERMINISTIC)
|
|
5. Task B: Claim Master Table (ALL)
|
|
6. Compute if C1~C3 satisfied; else PENDING
|
|
7. Task C: Claim Structure Map (TOP-N)
|
|
8. Task D: Defense-Rebuttal Matrix (TOP-N)
|
|
9. Task E: Evidence List & Risk Assessment
|
|
10. Task F: Quality Gate + Self-Validation
|
|
11. write_file("stage4_validation_log.json")
|
|
12. write_file("청구항변반박전략.md")
|
|
13. Print completion summary
|
|
|
|
---
|
|
|
|
## 10) Conditional Skip Rules
|
|
|
|
| 조건 | 스킵 대상 |
|
|
|------|-----------|
|
|
| 사해행위취소 없음 | 사해행위 특칙 섹션 |
|
|
| 모든 청구 CONFIRMED | UNRESOLVED 경고 섹션 |
|
|
| claims_total ≤ 3 | Top-N 분기 로직 |
|
|
| python_interpreter 없음 | 계산 실행 (PENDING 처리) |
|
|
| LOW 항변만 존재 | 항변 매트릭스 본문 (전체 "추가 확인"으로 이관) |
|
|
|
|
tools:
|
|
mcpServers:
|
|
localdocs:
|
|
type: streamable-http
|
|
url: "http://mcp-localdocs:8012/mcp"
|
|
description: Get the content of local documents
|
|
|
|
prevs: [stage3_자료_저장]
|
|
nexts: [stage3_2_defense_structure]
|
|
|
|
- name: stage4.5.1_판례검색쿼리생성
|
|
description: 판례검색 쿼리 생성
|
|
llm_provider: anthropic
|
|
llm_model: claude-opus-4-5
|
|
prompts:
|
|
- role: user
|
|
content: |
|
|
## 0. 역할 및 목적
|
|
|
|
당신은 **대한민국 민사소송 판례 리서치 쿼리 설계 에이전트**이다.
|
|
|
|
**목적**: 청구항변반박전략.md에서 정보를 추출하고, 판례 검색용 쿼리 플랜(JSON)을 생성한다.
|
|
|
|
**핵심 원칙**:
|
|
1. **원문 기반 추출**: 청구항변반박전략.md에서 원문을 그대로 추출하여 query_context 구성
|
|
2. **자기완결 unit**: 각 unit은 쿼리 생성에 필요한 모든 정보를 query_context에 포함
|
|
3. **경량 출력**: 최종 JSON에는 units만 포함 (정본 tuple은 내부 처리용, 출력 제외)
|
|
|
|
---
|
|
|
|
## 1. 입력
|
|
|
|
| 구분 | 파일 |
|
|
|------|------|
|
|
| 필수 | 청구항변반박전략.md |
|
|
| 참조 | Rule_Set_법리키워드.md, Rule_Set_사실관계키워드.md, Rule_Set_조문요건요소키워드.md |
|
|
|
|
---
|
|
|
|
## 2. 처리 흐름 (Internal → Output)
|
|
|
|
```
|
|
[Internal Processing - 출력하지 않음]
|
|
청구항변반박전략.md 파싱
|
|
├─ 청구 마스터표 → (청구취지, 청구원인, 주요쟁점)
|
|
├─ 청구구조도 → case_type_raw, 요건사실[]
|
|
└─ 항변/재반박 매트릭스 → (상대주장, 핵심쟁점, 재반박)
|
|
|
|
[Output - JSON 파일로 출력]
|
|
units[] → 각 unit은 query_context + queries 포함
|
|
```
|
|
|
|
**출력 원칙**:
|
|
- 정본 tuple(canonical_tuples)은 **내부 처리 단계**에서만 사용
|
|
- 최종 JSON 출력에는 **units 배열만** 포함
|
|
- unit.query_context에 쿼리 생성에 필요한 원문 정보를 직접 포함
|
|
|
|
---
|
|
|
|
## 3. 내부 처리: 정보 추출 (출력하지 않음)
|
|
|
|
### 3.1 청구 마스터표에서 추출
|
|
|
|
| 필드 | 추출 대상 |
|
|
|------|-----------|
|
|
| claim_id | 청구 ID (C-001, C-002, ...) |
|
|
| claim_purpose | 청구취지 원문 |
|
|
| claim_cause | 청구원인 원문 |
|
|
| main_issue | 주요쟁점 원문 |
|
|
|
|
### 3.2 청구구조도에서 추출
|
|
|
|
| 필드 | 추출 대상 |
|
|
|------|-----------|
|
|
| case_type_raw | header의 사건 종류 원문 |
|
|
| requirement_facts[] | 요건사실 표의 (요소, 내용) 쌍 |
|
|
|
|
### 3.3 항변/재반박 매트릭스에서 추출
|
|
|
|
| 필드 | 추출 대상 |
|
|
|------|-----------|
|
|
| claim_id | 연결된 청구 ID |
|
|
| defense_index | 행 순번 (1부터) |
|
|
| opponent_claim | 상대 주장 원문 |
|
|
| key_issue | 핵심 쟁점 원문 |
|
|
| rebuttal | 재반박 원문 |
|
|
|
|
### 3.4 추출 규칙
|
|
|
|
- 원문의 개행은 `\n`으로 보존
|
|
- 빈 셀은 `""`로 기록
|
|
- 요약, 동의어 치환, 문장 재배열 금지
|
|
|
|
---
|
|
|
|
## 4. case_type 정규화 및 Target 결정
|
|
|
|
| 키워드 포함 | case_type_normalized | collection | tenant |
|
|
|-------------|---------------------|------------|--------|
|
|
| 사해행위, 채권자취소 | 사해행위취소 | Analyzed_Cases | Cases_Actio_Pauliana |
|
|
| 대여금, 금전소비대차 | 대여금 | Past_Cases | Cases_Loan_Claim |
|
|
| 보증, 연대보증 | 보증 | Past_Cases | Cases_Guarantee_Claim |
|
|
| 구상, 대위변제 | 구상 | Past_Cases | Cases_Indemnity_Claim |
|
|
|
|
**정규화 절차**: 대괄호/청구ID 제거 → 접미어 제거 → 표준 매핑
|
|
|
|
---
|
|
|
|
## 5. Unit 생성 (출력 대상)
|
|
|
|
### 5.1 Unit 구조
|
|
|
|
```json
|
|
{
|
|
"unit_id": "<claim_id>-<RQ|DEF-nn>",
|
|
"unit_type": "requirement|defense",
|
|
"claim_id": "<C-00X>",
|
|
"case_type_normalized": "<정규화값>",
|
|
"target": {
|
|
"collection": "<Collection>",
|
|
"tenant": "<Tenant>"
|
|
},
|
|
"query_context": {
|
|
"primary_text": "<쿼리 생성용 핵심 원문>",
|
|
"elements": ["<요소명>"] | null,
|
|
"issue_focus": "<쟁점 초점 원문>"
|
|
},
|
|
"queries": []
|
|
}
|
|
```
|
|
|
|
### 5.2 Requirement Unit (청구별 1개)
|
|
|
|
**unit_id**: `<claim_id>-RQ` (예: C-001-RQ)
|
|
|
|
**query_context 구성**:
|
|
| 필드 | 소스 |
|
|
|------|------|
|
|
| primary_text | claim_purpose (청구취지 원문) |
|
|
| elements | requirement_facts[].element 전체 (요소명 배열) |
|
|
| issue_focus | main_issue (주요쟁점 원문) |
|
|
|
|
### 5.3 Defense Unit (매트릭스 행별 1개)
|
|
|
|
**unit_id**: `<claim_id>-DEF-<nn>` (예: C-001-DEF-01)
|
|
|
|
**query_context 구성**:
|
|
| 필드 | 소스 |
|
|
|------|------|
|
|
| primary_text | opponent_claim (상대 주장 원문) |
|
|
| elements | null |
|
|
| issue_focus | key_issue + " - " + rebuttal (핵심쟁점과 재반박 결합) |
|
|
|
|
---
|
|
|
|
## 6. 3-Layer 키워드 추출 및 쿼리 생성
|
|
|
|
### 6.1 키워드 추출 (query_context 기반)
|
|
|
|
| Layer | 개수 | 추출 소스 | Rule Set |
|
|
|-------|------|-----------|----------|
|
|
| L1 (법리) | 2-4 | issue_focus | Rule_Set_법리키워드.md |
|
|
| L2 (사실관계) | 2-4 | primary_text (추상화) | Rule_Set_사실관계키워드.md |
|
|
| L3 (조문요건) | 1-3 | elements + issue_focus | Rule_Set_조문요건요소키워드.md |
|
|
|
|
**L3 형식**: "민법 제406조 - 사해의사" (조문 단독 출력 금지)
|
|
|
|
### 6.2 Alpha 결정
|
|
|
|
| alpha_basis | alpha | 조건 |
|
|
|-------------|-------|------|
|
|
| 법리 | 0.55 | 요건 해석, 입증책임 쟁점 |
|
|
| 사실관계 | 0.65 | 사실 인정, 패턴 매칭 중심 |
|
|
| 조문요건 | 0.45 | 특정 조문요건 충족 여부 |
|
|
| 복합 (기본값) | 0.55 | 위 조건 불명확 시 |
|
|
|
|
### 6.3 Query 객체
|
|
|
|
```json
|
|
{
|
|
"qid": "<unit_id>-Q<n>",
|
|
"topic": "<15자 이내>",
|
|
"alpha_basis": "<법리|사실관계|조문요건|복합>",
|
|
"keywords": {
|
|
"L1": ["kw1", "kw2"],
|
|
"L2": ["kw1", "kw2"],
|
|
"L3": ["kw1"]
|
|
},
|
|
"semantic_sentence": "<35단어 이내>",
|
|
"variants": []
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 7. Variant 생성
|
|
|
|
### 7.1 Variant 파라미터
|
|
|
|
| variant | bm25_operator | limit | fusion_type | 생성 조건 |
|
|
|---------|---------------|-------|-------------|-----------|
|
|
| primary | and | 15 | relative_score | **필수** (모든 query) |
|
|
| broad | or | 25 | relative_score | 쟁점 다양성 큼 또는 예외 탐색 필요 |
|
|
| narrow | and | 10 | ranked | 단일 요건요소 정밀 타격 |
|
|
|
|
### 7.2 Call 객체
|
|
|
|
```json
|
|
{
|
|
"tool": "search_hybrid",
|
|
"args": {
|
|
"collection_name": "<Collection>",
|
|
"tenant": "<Tenant>",
|
|
"query": "<L1+L2+L3+semantic_sentence 통합>",
|
|
"alpha": <0.45|0.55|0.65>,
|
|
"limit": <10|15|25>,
|
|
"bm25_operator": "<and|or>",
|
|
"fusion_type": "<relative_score|ranked>"
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 8. Query Caps
|
|
|
|
| unit_type | max queries |
|
|
|-----------|-------------|
|
|
| requirement | 3 |
|
|
| defense | 2 |
|
|
|
|
---
|
|
|
|
## 9. 출력 JSON Schema
|
|
|
|
**파일**: `queries_case_research.json`
|
|
|
|
```json
|
|
{
|
|
"version": "query_plan_v2.4",
|
|
"stage": "4.5.1",
|
|
"metadata": {
|
|
"source_doc": "청구항변반박전략.md",
|
|
"counts": {
|
|
"units": 0,
|
|
"queries": 0
|
|
},
|
|
"defaults": {
|
|
"query_properties": ["raw_case_id", "raw_case_holding_and_reasoning"],
|
|
"include_vector": false
|
|
}
|
|
},
|
|
"units": [
|
|
{
|
|
"unit_id": "<claim_id>-<RQ|DEF-nn>",
|
|
"unit_type": "requirement|defense",
|
|
"claim_id": "<C-00X>",
|
|
"case_type_normalized": "<정규화값>",
|
|
"target": {
|
|
"collection": "<Collection>",
|
|
"tenant": "<Tenant>"
|
|
},
|
|
"query_context": {
|
|
"primary_text": "<원문>",
|
|
"elements": ["<요소>"] | null,
|
|
"issue_focus": "<원문>"
|
|
},
|
|
"queries": [
|
|
{
|
|
"qid": "<unit_id>-Q<n>",
|
|
"topic": "<15자 이내>",
|
|
"alpha_basis": "<법리|사실관계|조문요건|복합>",
|
|
"keywords": {
|
|
"L1": [],
|
|
"L2": [],
|
|
"L3": []
|
|
},
|
|
"semantic_sentence": "<35단어 이내>",
|
|
"variants": [
|
|
{
|
|
"variant": "primary|broad|narrow",
|
|
"call": {}
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
],
|
|
"validation_errors": []
|
|
}
|
|
```
|
|
|
|
⚠️ **출력 제외 항목**: `canonical_tuples` 섹션은 출력하지 않음
|
|
|
|
---
|
|
|
|
## 10. 실행 절차
|
|
|
|
```
|
|
STEP 1: 청구항변반박전략.md 파싱 (내부 처리)
|
|
├─ 청구 마스터표 → (claim_id, claim_purpose, claim_cause, main_issue)
|
|
├─ 청구구조도 → (case_type_raw, requirement_facts[])
|
|
└─ 항변/재반박 매트릭스 → (opponent_claim, key_issue, rebuttal)
|
|
|
|
STEP 2: case_type 정규화 → target(collection, tenant) 결정
|
|
|
|
STEP 3: Unit 생성 (출력 대상)
|
|
├─ Requirement unit: claim_id당 1개
|
|
│ └─ query_context 구성 (primary_text=claim_purpose, elements=요소배열, issue_focus=main_issue)
|
|
└─ Defense unit: 매트릭스 행당 1개
|
|
└─ query_context 구성 (primary_text=opponent_claim, elements=null, issue_focus=key_issue+rebuttal)
|
|
|
|
STEP 4: 쿼리 생성
|
|
├─ L1/L2/L3 키워드 추출 (query_context + Rule Set)
|
|
├─ alpha_basis → alpha 결정
|
|
├─ semantic_sentence 생성
|
|
└─ variant 조건 평가 → call 객체 생성
|
|
|
|
STEP 5: Query Caps 검증, validation_errors 수집
|
|
|
|
STEP 6: queries_case_research.json 출력 (units만 포함, canonical_tuples 제외)
|
|
```
|
|
|
|
---
|
|
|
|
## 11. 종료 조건
|
|
|
|
- [ ] 모든 claim_id에 requirement unit 1개
|
|
- [ ] 모든 매트릭스 행에 defense unit 1개
|
|
- [ ] 모든 unit.query_context 완비
|
|
- [ ] 모든 query에 L1/L2/L3 + primary variant 포함
|
|
- [ ] Query Caps 준수
|
|
- [ ] validation_errors가 비어있거나 허용 경고만 포함
|
|
- [ ] 출력이 순수 JSON (canonical_tuples 미포함)
|
|
|
|
---
|
|
|
|
## 12. Error Handling
|
|
|
|
| 에러 | 처리 |
|
|
|------|------|
|
|
| 빈 셀 | `""` 기록 + `EMPTY:<unit_id>:<field>` |
|
|
| case_type 정규화 실패 | 키워드 fallback + `NORMALIZATION_FALLBACK:<unit_id>` |
|
|
| L3 조문 추론 저신뢰 | alpha_basis를 복합으로 + `L3_LOW_CONFIDENCE:<qid>` |
|
|
| Query Caps 초과 | topic 병합 |
|
|
|
|
---
|
|
|
|
## 13. 금지 사항
|
|
|
|
| 금지 | 설명 |
|
|
|------|------|
|
|
| canonical_tuples 출력 | 정본 tuple은 내부 처리용, JSON 출력에 포함 금지 |
|
|
| 원문 변형 | query_context 필드의 요약/재서술/동의어 치환 |
|
|
| 조문 단독 | L3에서 요건요소 없이 조문만 출력 |
|
|
| null 포함 | call 객체에 null 필드 |
|
|
| 로그 혼합 | JSON 파일에 주석/로그 |
|
|
|
|
tools:
|
|
mcpServers:
|
|
localdocs:
|
|
type: streamable-http
|
|
url: "http://mcp-localdocs:8012/mcp"
|
|
description: Get the content of local documents
|
|
weaviate:
|
|
type: streamable-http
|
|
url: "https://weaviate.eroomai.com/mcp"
|
|
description: Get the content from weaviate
|
|
prevs: [stage3_claim_structure]
|
|
nexts: [stage4_precedent_analysis]
|
|
|
|
- name: stage4.5.2_판례검색_판례보고서생성
|
|
description: 판례검색 쿼리 병렬처리용 조건부 프롬프트 작성 및 실행
|
|
llm_provider: anthropic
|
|
llm_model: claude-opus-4-5
|
|
prompts:
|
|
- role: user
|
|
content: |
|
|
## A) Tools & Error Handling (MANDATORY)
|
|
|
|
### A.1 MCP tools you may use
|
|
(localdocs)
|
|
- read_doc(doc_name)
|
|
- write_file(path, content, overwrite=True)
|
|
|
|
(outsourcing)
|
|
- run_dag(execution_name, task_procedure, tasks, system_prompt, tools)
|
|
- get_execution_result(execution_id)
|
|
- check_execution_status(execution_id)
|
|
- get_execution_logs(execution_id, tail=200)
|
|
|
|
(weaviate)
|
|
- search_hybrid(collection_name, tenant, query, alpha, limit, bm25_operator, fusion_type, query_properties)
|
|
|
|
|
|
## B) Preflight (outside DAG)
|
|
|
|
1) localdocs.read_doc("queries_case_research.json")
|
|
- If output starts with "Error:", retry once via function_call.read_doc
|
|
- If still Error → print:
|
|
INPUT_FILE_NOT_FOUND_OR_UNREADABLE: queries_case_research.json
|
|
**terminate**
|
|
|
|
2) Strict JSON parse:
|
|
- top-level "units" must be an array
|
|
- N = len(units); if N==0 → print:
|
|
EMPTY_UNITS: queries_case_research.json
|
|
**terminate**
|
|
|
|
|
|
## C) Manifest generation (unit_order.json) — single write
|
|
|
|
Filename rules:
|
|
- sanitize unit_id for filenames only: replace / \ : * ? " < > | with "_"
|
|
- out_file collision: if duplicate, suffix "__{i}"
|
|
|
|
Write unit_order.json (pretty JSON, UTF-8):
|
|
{
|
|
"version": "unit_order_v3_0",
|
|
"n": N,
|
|
"units": [
|
|
{ "index": 1, "unit_id": "...", "out_file": "..._case_research.md", "stub_file": "unit_1_case_research.json" },
|
|
...
|
|
{ "index": N, "unit_id": "...", "out_file": "..._case_research.md", "stub_file": "unit_N_case_research.json" }
|
|
]
|
|
}
|
|
|
|
Write:
|
|
- localdocs.write_file("unit_order.json", content, overwrite=True)
|
|
- Retry once via function_call.write_file on "Error:"
|
|
- If still Error → MANIFEST_WRITE_FAILED: unit_order.json ; **terminate**
|
|
|
|
Keep unit_order_obj in memory (dict). Do not overwrite with strings.
|
|
|
|
|
|
## D) Canonical objects (build in memory)
|
|
|
|
### D.1 tools_obj (canonical; dict)
|
|
{
|
|
"mcpServers": {
|
|
"weaviate": {
|
|
"type": "streamable-http",
|
|
"url": "https://weaviate.eroomai.com/mcp",
|
|
"description": "Get the content from weaviate"
|
|
},
|
|
"localdocs": {
|
|
"type": "streamable-http",
|
|
"url": "http://mcp-localdocs:8012/mcp",
|
|
"description": "Get the content of local documents"
|
|
}
|
|
}
|
|
}
|
|
|
|
### D.2 task_procedure_obj (canonical builder)
|
|
NON-NEGOTIABLE:
|
|
- Every node MUST have BOTH keys: "nexts" (list) and "wait_until" (list)
|
|
- Empty lists MUST be explicitly present
|
|
|
|
Build:
|
|
- expected_unit_tasks = ["unit_task_1", ..., "unit_task_N"]
|
|
- IN: nexts=expected_unit_tasks, wait_until=[]
|
|
- unit_task_i: nexts=["join_task"], wait_until=[]
|
|
- join_task: nexts=["OUT"], wait_until=expected_unit_tasks
|
|
- OUT: nexts=[], wait_until=["join_task"]
|
|
|
|
### D.3 tasks_obj (canonical builder; MUST be fully expanded)
|
|
- tasks_obj MUST be a dict; no placeholders
|
|
- Must contain "join_task" and "unit_task_1"..."unit_task_N"
|
|
|
|
LLM config:
|
|
- unit_task_i: anthropic / claude-sonnet-4-5-20250929
|
|
- join_task: anthropic / claude-sonnet-4-5-20250929
|
|
|
|
Build unit_task_i:
|
|
{
|
|
"llm_provider": "anthropic",
|
|
"llm_model": "claude-sonnet-4-5-20250929",
|
|
"prompts": [{
|
|
"role": "user",
|
|
"content": (
|
|
"You are executing unit_task_{i}.\\n\\n"
|
|
"UNIT_INDEX: {i}\\n"
|
|
"EXPECTED_UNIT_ID: {expected_unit_id}\\n"
|
|
"OUT_FILE: {out_file}\\n"
|
|
"STUB_FILE: {stub_file}\\n\\n"
|
|
"Read queries_case_research.json, locate the unit, run all qid(s) per SYSTEM_PROMPT.\\n"
|
|
"Write OUT_FILE and STUB_FILE.\\n\\n"
|
|
"Then print exactly:\\n"
|
|
"\\"unit_task_{i} completed\\"\\n"
|
|
"**terminate**"
|
|
)
|
|
}]
|
|
}
|
|
|
|
Build join_task:
|
|
{
|
|
"llm_provider": "anthropic",
|
|
"llm_model": "claude-sonnet-4-5-20250929",
|
|
"prompts": [{
|
|
"role": "user",
|
|
"content": (
|
|
"You are executing join_task.\\n\\n"
|
|
"1) Read: unit_order.json (strict JSON).\\n"
|
|
"2) For each unit entry in manifest order:\\n"
|
|
" - Read out_file; if missing/empty/error, substitute a placeholder failure table.\\n"
|
|
" - Append to merged report under heading '## <unit_id>' (original unit_id).\\n"
|
|
" - Track ERROR_FOUND = True if any unit content contains an error tag or is missing/invalid.\\n\\n"
|
|
"MERGE OUTPUT:\\n"
|
|
"Start with '# 판례검색 결과' then a blank line.\\n"
|
|
"For each unit:\\n"
|
|
" '## <unit_id>' then newline, then the unit table, then a blank line.\\n\\n"
|
|
"PLACEHOLDER FAILURE TABLE (use when out_file missing/empty/invalid):\\n"
|
|
"| key | value |\\n"
|
|
"| --- | --- |\\n"
|
|
"| unit_id | <unit_id> |\\n"
|
|
"| case_type_raw | |\\n"
|
|
"| raw_case_id 1 | 검색 실패 |\\n"
|
|
"| 요약 | 오류: parse_error |\\n"
|
|
"| raw_case_id 2 | - |\\n"
|
|
"| 요약 | - |\\n\\n"
|
|
"VALIDATION / ERROR DETECTION (set ERROR_FOUND=True if any):\\n"
|
|
"- table missing '| key | value |'\\n"
|
|
"- contains '오류: parse_error' OR '오류: tool_error' OR '오류: empty_result'\\n"
|
|
"- contains '검색 실패'\\n\\n"
|
|
"WRITE REPORT:\\n"
|
|
"write_file('case_research_report.md', merged_content, overwrite=True)\\n"
|
|
"Retry once with function_call.write_file if needed.\\n"
|
|
"If still fails, print 'REPORT_WRITE_FAILED' and **terminate** without cleanup.\\n\\n"
|
|
"CLEANUP (overwrite-empty) AFTER report write success:\\n"
|
|
"- Always cleanup intermediates:\\n"
|
|
" * for each out_file: write_file(out_file, '', overwrite=True)\\n"
|
|
" * write_file('unit_order.json', '', overwrite=True)\\n"
|
|
"- STUB POLICY (success delete / failure preserve):\\n"
|
|
" * If ERROR_FOUND == False: for each stub_file: write_file(stub_file, '', overwrite=True)\\n"
|
|
" * If ERROR_FOUND == True: do NOT touch stub_file(s)\\n\\n"
|
|
"Then print exactly:\\n"
|
|
"\\"join_task completed\\"\\n"
|
|
"**terminate**"
|
|
)
|
|
}]
|
|
}
|
|
|
|
### D.4 system_prompt_str (v3.0 — INTEGRATED FALLBACK + DEFERRED SUMMARIZATION)
|
|
Set system_prompt_str EXACTLY to the following text:
|
|
|
|
```
|
|
DAG task agent. Minimize tokens. Follow user prompt strictly.
|
|
|
|
=== ERROR RULES ===
|
|
localdocs "Error:" → retry once via function_call.*. No third attempt.
|
|
Labels: parse_error (JSON/missing fields), tool_error (tool failures), empty_result (no candidates)
|
|
|
|
=== HARD CONSTRAINTS (금지 사항) ===
|
|
❌ broad 호출 없이 holding fetch 단독 실행 금지
|
|
❌ ranking 단계에서 요약 생성 금지
|
|
❌ fallback 실패를 tool_error/empty_result로 분류 금지
|
|
❌ raw_case_id 필터 없는 재검색 금지
|
|
|
|
=== COST CONTROL (MANDATORY) ===
|
|
1. NO BULK SUMMARIZATION:
|
|
* 요약은 오직 최종 선정된 TOP-2에 대해서만 허용
|
|
* 다른 후보에 대해 요약 생성/출력 금지
|
|
2. Ranking query_properties (기본):
|
|
* query_properties = ["raw_case_id","raw_case_summary_of_decision"]
|
|
* ranking 단계에서 holding_and_reasoning 요청 금지 (Integrated fallback 예외)
|
|
3. Variant call budget:
|
|
* Ranking calls: 최대 3회 per qid (primary, narrow, broad)
|
|
* ID-target fallback: 최대 1회 per qid (예외적 상황에서만)
|
|
|
|
=== UNIT TASK (unit_task_*) ===
|
|
Inputs: UNIT_INDEX (int), EXPECTED_UNIT_ID (string), OUT_FILE (string), STUB_FILE (string)
|
|
|
|
Algorithm:
|
|
|
|
1. Read queries_case_research.json via localdocs.read_doc (retry once).
|
|
Error → write OUT_FILE with tool_error table, write STUB_FILE status=tool_error, stop.
|
|
|
|
2. Parse JSON; extract units array. Fail → parse_error.
|
|
|
|
3. Locate unit: prefer units[UNIT_INDEX-1]; if unit_id mismatch, scan array.
|
|
Not found → parse_error.
|
|
|
|
4. Extract: unit_id, case_type_raw|normalized, target.collection_name, target.tenant, queries list
|
|
|
|
5. For each qid in order — TWO PHASES:
|
|
|
|
=== PHASE A — RANKING (NO SUMMARIZATION) ===
|
|
|
|
A1) Initialize:
|
|
candidates = {} # raw_case_id -> best record
|
|
variants_tried = []
|
|
weaviate_calls = 0
|
|
integrated_holding = False # broad에서 holding 포함 여부
|
|
id_target_fallback = 0 # ID-target fallback 횟수
|
|
status = "ok"
|
|
needs_holding_fetch = False # Integrated fallback 조건 추적
|
|
|
|
A2) Prioritize variants strictly:
|
|
primary → narrow → broad (ignore extra variants beyond these three)
|
|
|
|
A3) Per-variant call limits (ADAPTIVE LIMIT):
|
|
- For primary and narrow: effective_limit = min(parsed_limit, 5); default 5
|
|
- For broad: effective_limit = min(parsed_limit, 8); default 8
|
|
|
|
A4) For each variant in order (stop at 3 calls):
|
|
|
|
* Extract args from variant.call.args:
|
|
query (required)
|
|
alpha (float or None)
|
|
limit (int or default)
|
|
bm25_operator (use args value if present, else default "and")
|
|
fusion_type (use args value if present, else default "relative_score")
|
|
|
|
* INTEGRATED FALLBACK 조건 체크 (broad variant 호출 직전에만):
|
|
IF variant.variant == "broad":
|
|
Check condition A: 현재 top 후보 중 snip_len < 40 존재
|
|
Check condition B: prior variants(primary/narrow)에서 후보 수 < 2
|
|
IF (condition A OR condition B):
|
|
query_properties = ["raw_case_id","raw_case_summary_of_decision","raw_case_holding_and_reasoning"]
|
|
integrated_holding = True
|
|
ELSE:
|
|
query_properties = ["raw_case_id","raw_case_summary_of_decision"]
|
|
ELSE:
|
|
query_properties = ["raw_case_id","raw_case_summary_of_decision"]
|
|
|
|
* Call weaviate.search_hybrid with:
|
|
collection_name=target.collection_name, tenant=target.tenant, query=query,
|
|
alpha=alpha, limit=effective_limit, bm25_operator=bm25_operator, fusion_type=fusion_type,
|
|
query_properties=query_properties
|
|
|
|
* weaviate_calls += 1; variants_tried.append(variant.variant)
|
|
* Tool error → status="tool_error"; break
|
|
* Empty result list → continue
|
|
|
|
* For each result:
|
|
raw_case_id = properties.raw_case_id
|
|
base_score = metadata.score
|
|
full_snip = properties.raw_case_summary_of_decision (may be "")
|
|
snip = first 350 chars of full_snip (SCORING SNIPPET - v3.0 확장)
|
|
holding_text = properties.raw_case_holding_and_reasoning if integrated_holding else ""
|
|
|
|
Compute hits in snip (case-insensitive substring):
|
|
L1/L2/L3 hits → hit_score=min(20, 3*L1+2*L2+L3)
|
|
topic_hit=1 if a meaningful topic token appears in snip else 0
|
|
final_score = base_score + 0.01*hit_score + 0.02*topic_hit
|
|
gate_pass = (L1>=1) OR (hit_score>=4) OR (topic_hit==1)
|
|
|
|
Dedup: keep highest final_score per raw_case_id.
|
|
Store per candidate:
|
|
{raw_case_id, final_score, base_score, hit_score, topic_hit, snip, snip_len, holding_text, gate_pass}
|
|
|
|
* After updating candidates, compute current top-1/top-2 by final_score.
|
|
* Early-stop condition (QUALITY-SAFE):
|
|
Stop variants ONLY if:
|
|
(unique candidates >= 2) AND (top1.gate_pass == True)
|
|
Otherwise continue to next variant.
|
|
|
|
A5) Outcome:
|
|
* If status=="tool_error" → keep.
|
|
* Else if candidates empty → status="empty_result".
|
|
* Else status remains "ok".
|
|
|
|
|
|
=== PHASE B — SUMMARIZATION (DEFERRED, TOP-2 ONLY) ===
|
|
|
|
B1) If status=="ok":
|
|
* Sort candidates by final_score desc.
|
|
* Select top_1 and top_2 (or "-" if only one).
|
|
|
|
B2) 요약 소스 결정 (우선순위):
|
|
FOR each selected candidate (top_1, top_2):
|
|
IF candidate.holding_text is non-empty (len >= 40):
|
|
summary_source = holding_text (first 500 chars)
|
|
source_type = "holding"
|
|
ELIF candidate.snip is non-empty (len >= 40):
|
|
summary_source = snip
|
|
source_type = "summary"
|
|
ELSE:
|
|
summary_source = None
|
|
source_type = "empty"
|
|
|
|
B3) ID-TARGET FALLBACK (예외적 조건에서만):
|
|
* 발동 조건 (모두 충족 시에만):
|
|
- top_1.source_type == "empty" AND top_2.source_type == "empty" (둘 다 비어있음)
|
|
- AND integrated_holding == False (broad에서 holding 미포함이었음)
|
|
- AND id_target_fallback == 0
|
|
|
|
* 실행 규칙:
|
|
- raw_case_id 필터를 사용한 ID-target 질의만 허용
|
|
- Call weaviate.search_hybrid with:
|
|
collection_name=target.collection_name, tenant=target.tenant,
|
|
query=top_1.raw_case_id (또는 top_2.raw_case_id를 OR 조건으로),
|
|
limit=2 (고정),
|
|
query_properties=["raw_case_id","raw_case_holding_and_reasoning"]
|
|
- id_target_fallback = 1
|
|
- 반환 결과에서 top_1/top_2의 raw_case_id와 매칭되는 것만 사용
|
|
- 매칭된 holding_text로 summary_source 업데이트
|
|
|
|
* ID-target fallback 실패 시: → B4 Degraded Mode로 진행 (오류 처리 아님)
|
|
|
|
B4) DEGRADED MODE (Fallback 실패 처리):
|
|
* 적용 조건: summary_source == None인 top 후보가 있을 때
|
|
* 금지 규칙:
|
|
- tool_error 처리 금지
|
|
- empty_result 처리 금지
|
|
- 재시도 루프 금지
|
|
* 허용 규칙:
|
|
- 기존 snip 기반으로 요약 생성 (snip이 짧더라도 사용)
|
|
- 요약 끝에 "[요약 제한: holding 부재]" 태그 추가
|
|
- 후보 자체는 유지
|
|
|
|
B5) 요약 생성 (TOP-2 ONLY):
|
|
* 출력 개수: 최대 2건 / 최소 2건 확보 실패 시에도 degraded mode로 2건 출력
|
|
* 각 요약: 최대 250글자, 법리 중심 1문장
|
|
* 스타일:
|
|
"<topic>: <핵심 판시/법리>(<핵심 사실>)"
|
|
* 텍스트 없음 시: "요약 없음 [요약 제한: holding 부재]"
|
|
|
|
B6) If status in {"parse_error","tool_error","empty_result"}:
|
|
* raw_case_id 1="검색 실패"
|
|
* raw_case_id 2="-"
|
|
* summary1="오류: <status>"
|
|
* summary2="-"
|
|
|
|
|
|
6. Write OUT_FILE: single markdown table, 2 cols, 6 rows per qid block.
|
|
* Single qid: standard 6 rows (unit_id, case_type_raw, id1, 요약, id2, 요약)
|
|
* Multi-qid: append blocks; first row key="unit_id (kth qid)", value="<unit_id> / qid=<qid>"
|
|
|
|
7. Write STUB_FILE (JSON, minimal):
|
|
{
|
|
"version":"unit_stub_v3_0",
|
|
"unit_index":<int>,
|
|
"unit_id":"...",
|
|
"target":{"collection_name":"...","tenant":"..."},
|
|
"out_file":"...",
|
|
"qid_count":<int>,
|
|
"per_qid":[{
|
|
"qid":"...",
|
|
"status":"ok|parse_error|tool_error|empty_result",
|
|
"variants_tried":[...],
|
|
"weaviate_calls":<int>,
|
|
"integrated_holding":<bool>, # broad에서 holding 포함 여부
|
|
"id_target_fallback":<int>, # 0 or 1
|
|
"degraded_mode":<bool>, # degraded mode 적용 여부
|
|
"candidates_seen":<int>,
|
|
"summaries_generated":0|1|2,
|
|
"summary_sources":["holding"|"summary"|"snip"|"degraded", ...],
|
|
"top2":[{"raw_case_id":"...","final_score":<float>},{"raw_case_id":"...","final_score":<float>}]
|
|
}]
|
|
}
|
|
|
|
=== JOIN TASK ===
|
|
Follow user prompt exactly. No extra cleanup rules.
|
|
```
|
|
|
|
### D.5 spec_text_str (build with required headers)
|
|
N=<N>
|
|
unit_order.json
|
|
<pretty JSON of unit_order_obj>
|
|
task_procedure
|
|
<pretty JSON of task_procedure_obj>
|
|
tasks
|
|
<pretty JSON of tasks_obj>
|
|
system_prompt
|
|
<system_prompt_str verbatim>
|
|
tools
|
|
<pretty JSON of tools_obj>
|
|
|
|
|
|
## E) Self-Validation (before write/run_dag)
|
|
|
|
### E.1 Validation checks
|
|
1) task_procedure: all nodes exist (IN, unit_task_*, join_task, OUT)
|
|
2) Each node has nexts and wait_until (both lists)
|
|
3) Correct linkage: IN.wait_until=[], join_task.nexts=["OUT"], OUT.nexts=[]
|
|
4) tasks_obj is dict, contains join_task + all unit_tasks
|
|
5) spec_text has no placeholders/ellipsis/"...", all headers present
|
|
|
|
### E.2 Regeneration policy
|
|
- TP_* failure → rebuild task_procedure_obj once
|
|
- TASKS_* failure → rebuild tasks_obj once
|
|
- SERIAL_* failure → rebuild spec_text_str once
|
|
- Still fails → print DAG_SPEC_INVALID + CODE + **terminate**
|
|
|
|
|
|
## F) Write search_prompt.md (after validation passes)
|
|
|
|
localdocs.write_file("search_prompt.md", spec_text_str, overwrite=True)
|
|
Retry once; fail → SEARCH_PROMPT_WRITE_FAILED ; **terminate**
|
|
|
|
|
|
## G) Execute DAG
|
|
|
|
outsourcing.run_dag(
|
|
execution_name="stage_4_5_case_search_v3_0",
|
|
task_procedure=task_procedure_obj,
|
|
tasks=tasks_obj,
|
|
system_prompt=system_prompt_str,
|
|
tools=tools_obj
|
|
)
|
|
|
|
Retrieve results:
|
|
- get_execution_result(execution_id)
|
|
- if running: check_execution_status once, then get_execution_result once
|
|
- max 4 retrieval calls after run_dag
|
|
|
|
Post-check:
|
|
- localdocs.read_doc("case_research_report.md") (retry once)
|
|
- Missing/empty → REPORT_MISSING_OR_EMPTY ; **terminate**
|
|
|
|
|
|
## H) Completion Signal
|
|
|
|
CASE RESEARCH STAGE COMPLETE
|
|
|
|
|
|
tools:
|
|
mcpServers:
|
|
localdocs:
|
|
type: streamable-http
|
|
url: "http://mcp-localdocs:8012/mcp"
|
|
description: Get the content of local documents
|
|
weaviate:
|
|
type: streamable-http
|
|
url: "https://weaviate.eroomai.com/mcp"
|
|
description: Get the content from weaviate
|
|
outsourcing:
|
|
type: streamable-http
|
|
url: "https://outsourcing.mcp.eroomai.com/mcp"
|
|
description: Get the content of local documents
|
|
headers:
|
|
Authorization: "Bearer FftIOt6ppQKrzhaRX8x/olCvRVivoR9SWXYOYeXEREg="
|
|
|
|
|
|
prevs: [stage4_4_case_research]
|
|
nexts: [stage5_drafting_complaint]
|
|
|
|
- name: stage5_소장작성
|
|
description: 최종 소장(complaint) 작성
|
|
llm_provider: anthropic
|
|
llm_model: claude-opus-4-5
|
|
prompts:
|
|
- role: user
|
|
content: |
|
|
## 0. ROLE
|
|
|
|
대한민국 민사소송 **소장 컴파일러**. 전략 데이터 → 법원 제출용 문서로 **결정론적 조립**.
|
|
|
|
**원칙**: 데이터 절대주의 | 강제집행 가능 청구취지 | 법조계 문체(~함, ~임, ~습니다) | Hallucination 금지 | **수치 계산 금지**
|
|
|
|
---
|
|
|
|
## 1. PHASE 1: LOAD & MERGE
|
|
|
|
### 1.1 입력
|
|
| 파일 | 필수 | 추출 대상 |
|
|
|------|:----:|-----------|
|
|
| 청구항변반박전략.md | ✓ | `## 3. 청구 마스터 표` → claims[], `## 4. 청구구조도` → requirements[] |
|
|
| client_goal.json | ✓ | `parties.plaintiffs[]`, `parties.defendants[]`, `parties.third_parties[]` |
|
|
| case_research_report.md | | 존재 시 판례 인용용 |
|
|
|
|
### 1.2 필터 (CRITICAL)
|
|
```
|
|
claims[] ← 청구마스터표 WHERE claim_resolution == "CONFIRMED"
|
|
# DEGRADED/DROPPED/UNRESOLVED → 제외
|
|
```
|
|
|
|
### 1.3 변수 추출 (추론 금지, 직접 추출만)
|
|
```
|
|
PER claim:
|
|
{ID} ← 청구 ID (C-001 등)
|
|
{TYPE} ← claim_type_raw 필드에서 직접 추출 (추론 금지!)
|
|
{PURPOSE} ← 청구취지 컬럼
|
|
{CAUSE} ← 청구원인 컬럼
|
|
{DEFENDANTS} ← 피고 컬럼
|
|
{PRINCIPAL} ← 원금 (입력값 그대로, 계산 금지)
|
|
{DAMAGES_START} ← 지연손해금 기산일
|
|
{RATE} ← 이율 (입력값 그대로: "연 5%", "월 1%" 등)
|
|
{EVIDENCE_IDS} ← 핵심 서증
|
|
{TAGS} ← 태그
|
|
{RESTITUTION} ← 원상회복 방법 (사해취소 시: 가액배상|원물반환)
|
|
```
|
|
|
|
**⚠️ TYPE 결정 규칙 (재현성 보장)**:
|
|
- claim_type_raw 필드가 있으면 → **그대로 사용**
|
|
- 필드가 없거나 비어있으면 → 청구취지 키워드 기반 매칭:
|
|
| 키워드 | TYPE |
|
|
|--------|------|
|
|
| "대여금", "변제기" | 대여금 |
|
|
| "보증", "연대보증" | 보증 |
|
|
| "구상", "대위변제" | 구상 |
|
|
| "사해행위", "취소" | 사해행위취소 |
|
|
| "대위", "제3채무자" | 대위청구 |
|
|
|
|
### 1.4 복수 청구 병합 분석
|
|
|
|
**병합 그룹 생성**:
|
|
```
|
|
claim_groups[] ← GROUP claims[] BY:
|
|
- 동일 피고 + 동일 TYPE → merge_type: "동일피고_동일유형"
|
|
- 동일 피고 + 상이 TYPE → merge_type: "동일피고_상이유형"
|
|
- 주채무 + 보증/구상 → merge_type: "주종관계"
|
|
- 피보전채권 + 사해취소 → merge_type: "선후관계"
|
|
- 병합 불가 → merge_type: "독립"
|
|
```
|
|
|
|
**병합 규칙**:
|
|
| merge_type | 청구취지 처리 | 청구원인 처리 |
|
|
|------------|--------------|--------------|
|
|
| 동일피고_동일유형 | 원금 나열 (합산 금지) | 공통 사실 1회 → 개별 차이만 |
|
|
| 동일피고_상이유형 | 항 분리 | 당사자 1회 → 유형별 분리 |
|
|
| 주종관계 | 주채무 → 보증/구상 순서 | "위 채무에 관하여" 참조 |
|
|
| 선후관계 | 피보전채권 → 사해취소 순서 | "위 채권 보전을 위하여" 참조 |
|
|
|
|
### 1.5 관할 결정 (절차화)
|
|
|
|
**입력 필드 우선순위**:
|
|
```
|
|
1. client_goal.json > venue_court (명시된 경우) → 그대로 사용
|
|
2. 청구항변반박전략.md > "관할" 섹션 (있으면) → 그대로 사용
|
|
3. 자동 결정:
|
|
IF 청구에 "부동산/등기/말소" 포함:
|
|
→ 부동산 소재지 관할 (전속관할 가능성)
|
|
→ 소재지 추출: 청구구조도 > 목적물 필드
|
|
ELSE:
|
|
→ 피고 보통재판적 (피고 주소지)
|
|
→ 주소 추출: client_goal.json > defendants[0].address
|
|
4. 불명 시:
|
|
→ "○○지방법원(관할 미확정) 귀중" placeholder
|
|
```
|
|
|
|
**법원명 결정**:
|
|
| 주소 키워드 | 법원명 |
|
|
|-------------|--------|
|
|
| 서울 | 서울중앙지방법원 (또는 해당 구 지원) |
|
|
| 부산 | 부산지방법원 |
|
|
| 대구 | 대구지방법원 |
|
|
| ... | (주소 시/도에서 추출) |
|
|
| 불명 | ○○지방법원(관할 미확정) |
|
|
|
|
**소가 기준 사건 구분**:
|
|
- 소가 2억원 이하 → 단독사건
|
|
- 소가 2억원 초과 → 합의부
|
|
|
|
---
|
|
|
|
## 2. PHASE 2: COMPILE (Inline Validation)
|
|
|
|
### 2.1 지연손해금 처리 (계산 금지, 비율 문형 사용)
|
|
|
|
**⚠️ 핵심 원칙: LLM은 금액 계산을 수행하지 않는다.**
|
|
|
|
**처리 방법**:
|
|
| 항목 | 처리 |
|
|
|------|------|
|
|
| 청구취지 | **"비율로 계산한 돈" 문형 사용** (실무 표준) |
|
|
| 청구원인 | 기산일/이율만 서술, 금액 산출 금지 |
|
|
| 별지 산정표 | 원금/기산일/이율 기재, 최종금액란은 【법원 산정】 |
|
|
|
|
**비율 문형 (표준)**:
|
|
```
|
|
"금 {PRINCIPAL}원 및 이에 대하여 {DAMAGES_START}부터
|
|
이 사건 소장 부본 송달일까지는 연 {이율1}%,
|
|
그 다음 날부터 다 갚는 날까지는 연 {이율2}%의
|
|
각 비율로 계산한 돈을 지급하라."
|
|
```
|
|
|
|
**이율 기본값** (입력에 없으면):
|
|
| 유형 | 이율1 (기산일~송달일) | 이율2 (송달일~완제) |
|
|
|------|---------------------|---------------------|
|
|
| 민사 일반 | 연 5% | 연 12% |
|
|
| 상사 채권 | 연 6% | 연 12% |
|
|
| 약정 있음 | 약정이율 | 연 12% |
|
|
|
|
**예외 케이스** (기산점/이율 Override):
|
|
| 케이스 | 기산점 | 이율 | 비율 문형 |
|
|
|--------|--------|------|----------|
|
|
| 사해취소 가액배상 | **확정일 다음 날** | 연 5% 단일 | "이 판결 확정일 다음 날부터 다 갚는 날까지 연 5%의 비율로 계산한 돈" |
|
|
| 불법행위 | 불법행위일 | 민사법정→소촉법 | 표준 비율 문형 |
|
|
|
|
**금지 사항**:
|
|
- ❌ 일수 계산 (days 함수 사용 금지)
|
|
- ❌ 이자 금액 산출 (principal * rate * days / 365 등)
|
|
- ❌ 합계 금액 계산 (원금 + 이자)
|
|
- ❌ 이율 단위 변환 계산 (월→연 등)
|
|
|
|
### 2.2 청구취지 템플릿 (Trigger → Format)
|
|
|
|
**Defaults**: 민사이율=5, 소촉법이율=12, 기산점="소장 부본 송달일"
|
|
|
|
| TYPE | Template | ⚠️ Override |
|
|
|------|----------|-------------|
|
|
| 금전지급 | `"{n}. 피고{들}은 {연대하여}원고에게 금 {PRINCIPAL}원 및 이에 대하여 {DAMAGES_START}부터 이 사건 소장 부본 송달일까지는 연 {이율1}%, 그 다음 날부터 다 갚는 날까지는 연 {이율2}%의 각 비율로 계산한 돈을 지급하라."` | 상사→이율1=6, 약정→이율1=약정 |
|
|
| 금전지급_병합 | `"{n}. 피고 {피고명}은 원고에게, 가. 금 {원금1}원 및 이에 대하여... 나. 금 {원금2}원 및 이에 대하여... 각 지급하라."` | 합산 금지, 개별 나열 |
|
|
| 사해취소-가액 | `"{n}. 피고 {수익자}과 소외 {채무자} 사이에 별지 목록 기재 부동산에 관하여 {계약일} 체결된 {계약종류}은 금 {한도}원 한도 내에서 취소한다."\n"{n+1}. 피고는 원고에게 금 {가액}원 및 이에 대하여 이 판결 확정일 다음 날부터 다 갚는 날까지 연 5%의 비율로 계산한 돈을 지급하라."` | **기산점="확정일 다음 날"** |
|
|
| 사해취소-원물 | `"{n}. ...취소한다."\n"{n+1}. 피고는 소외 {채무자}에게 별지 목록 기재 부동산에 관하여 ...말소등기절차를 이행하라."` | |
|
|
| 대위청구 | `"{n}. 피고 {제3채무자}는 소외 {채무자}(주민등록번호: {주민번호}, 주소: {주소})에게 ...말소등기절차를 이행하라."` | **채무자 인적사항 필수** |
|
|
|
|
**종결**: `"{N+1}. 소송비용은 피고{들}가 부담한다."` + 금전청구 시 `"{N+2}. 제1항{내지 제N항}은 가집행할 수 있다."`
|
|
|
|
### 2.3 청구원인 구조 (병합 최적화 적용)
|
|
|
|
**기본 매트릭스**:
|
|
| TYPE | 필수 요소 | 법리 |
|
|
|------|----------|------|
|
|
| 대여금 | 당사자→대차계약(일시,금액,이율,변제기)→변제기도래→미변제→지연손해금→결론 | 불필요 |
|
|
| 보증 | 주채무발생→보증계약(연대여부)→주채무불이행→보증범위→결론 | 불필요 |
|
|
| 구상 | 주채무+연대보증→보증계약→대위변제(일시,금액)→구상권근거→결론 | 민법 §441 |
|
|
| 사해취소 | 피보전채권→사해행위(일시,대상,내용)→무자력→사해의사→수익자악의→원상회복→결론 | 민법 §406 |
|
|
|
|
**서술 규칙**: 주체→일시→상대방→목적물→행위 | 권리자 주어 | 요건사실만
|
|
**결론 형식**: `"따라서 피고{들}은 원고에게 {의무}할 의무가 있습니다."`
|
|
|
|
### 2.4 입증방법/첨부
|
|
```
|
|
입증: 갑 제{n}호증 {명칭} ← EVIDENCE_IDS 순차 매핑 (중복 제거)
|
|
첨부: 1. 위 입증방법 각 1통 / 2. 소장부본 {피고수}통 / 3. 송달료 납부서 1통
|
|
4. 위임장 1통 (소송대리인 시) / 5. 법인등기사항전부증명서 각 1통 (법인 시)
|
|
```
|
|
|
|
### 2.5 Inline QC (CRITICAL 5항목)
|
|
| # | 점검 | 위반 시 |
|
|
|---|------|---------|
|
|
| 1 | 사해취소 가액배상 기산점 == "확정일 다음 날" | **즉시 수정** |
|
|
| 2 | 대위청구 시 채무자 주민번호+주소 포함 | **즉시 수정** |
|
|
| 3 | CONFIRMED 청구만 포함 | 제외 누락 시 삭제 |
|
|
| 4 | 금액 계산 시도 여부 | **계산 흔적 발견 시 비율 문형으로 대체** |
|
|
| 5 | 별지 참조 ↔ 실제 별지 번호 일치 | **불일치 시 수정** |
|
|
|
|
### 2.6 별지(Annex) 자동 생성
|
|
|
|
**트리거 및 생성 규칙** (순서 고정):
|
|
|
|
| 트리거 | 별지 제목 | 생성 내용 |
|
|
|--------|-----------|----------|
|
|
| 청구취지/요건사실에 "별지 목록/부동산/목적물" 포함 | 별지 1. 목록 | 부동산 표시 테이블 (소재지/면적/등기정보) |
|
|
| 금전청구 복수 | 별지 n. 청구금액 내역표 | 원금/기산일/이율 테이블 (금액 계산 없음) |
|
|
| 증거 20개 이상 OR 전략에서 별지 요구 | 별지 n. 입증방법 목록 | 갑호증/증거ID/문서명 테이블 |
|
|
|
|
**별지 생성 절차**:
|
|
```
|
|
annex_registry[] ← []
|
|
번호 = 1
|
|
|
|
FOR EACH 트리거 IN [목록형, 금전복수, 증거다수]:
|
|
IF 트리거 충족:
|
|
annex_registry.append({번호, 제목, 내용})
|
|
번호 += 1
|
|
|
|
# 본문에서 "별지 n 목록 기재..."로 참조
|
|
```
|
|
|
|
**목록 별지 내용** (부동산/목적물):
|
|
```
|
|
| 번호 | 소재지 | 지목/용도 | 면적 | 등기정보 | 비고 |
|
|
|------|--------|----------|------|---------|------|
|
|
| 1 | {주소} | {지목} | {면적}㎡ | {등기소} {접수번호} | |
|
|
```
|
|
- 소스: 청구구조도 > 목적물 필드, 전략 문서 내 "별지/목록" 섹션
|
|
- 불명 필드: 【미상】 표시
|
|
|
|
**청구금액 내역표** (계산 없음):
|
|
```
|
|
| 순번 | 청구 | 원금 | 기산일 | 이율 | 비고 |
|
|
|------|------|------|--------|------|------|
|
|
| 1 | 대여금 | {원금} | {기산일} | 연 {이율}% → 연 12% | |
|
|
| 2 | 보증금 | {원금} | {기산일} | 연 {이율}% → 연 12% | |
|
|
```
|
|
- **금액 합계/이자 금액 산출 금지**
|
|
- 이율 변경 시점: "소장 부본 송달일" 또는 "판결 확정일"로 표기
|
|
|
|
---
|
|
|
|
## 3. PHASE 3: OUTPUT
|
|
|
|
### 3.1 소장.md 스켈레톤
|
|
```
|
|
# 소 장
|
|
|
|
## 1. 관할법원
|
|
{COURT_NAME} 귀중
|
|
|
|
## 2. 당사자
|
|
### 원고
|
|
- {원고 목록}
|
|
### 피고
|
|
- {피고 목록}
|
|
|
|
---
|
|
|
|
## 3. 청구취지
|
|
{청구취지 항목 - 비율 문형 사용}
|
|
|
|
---
|
|
|
|
## 4. 청구원인
|
|
### 1. 당사자의 지위
|
|
### 2. 관할
|
|
### 3. {청구명}에 관하여
|
|
### 4. 결론
|
|
|
|
---
|
|
|
|
## 5. 입증방법
|
|
## 6. 첨부서류
|
|
|
|
---
|
|
|
|
## 7. 별지 (해당 시)
|
|
### 별지 1. 목록
|
|
### 별지 2. 청구금액 내역표
|
|
...
|
|
|
|
---
|
|
|
|
{일자}
|
|
원고 소송대리인 변호사 {이름} (인)
|
|
```
|
|
|
|
### 3.2 출력 규칙
|
|
- 내부코드(F-001, E-001, C-001) 노출 금지
|
|
- 병합 시 개별 청구ID 노출 금지
|
|
- 별지 참조 ↔ 실제 별지 번호 일치 필수
|
|
- **계산된 금액(이자액, 합계 등) 출력 금지**
|
|
- Inline QC 위반 미수정 시 `[VALIDATION_WARNING]` 말미 추가
|
|
|
|
---
|
|
|
|
## 4. HARD CONSTRAINTS
|
|
|
|
| 금지 | 이유 |
|
|
|------|------|
|
|
| 입력 외 사실 생성 | Hallucination |
|
|
| **금액 계산 (일수/이자/합계)** | **LLM 연산 비결정성 → Hallucination** |
|
|
| TYPE 추론 (claim_type_raw 없을 때만 키워드 매칭) | 재현성 |
|
|
| 가액배상 기산점 "송달일" | 대법원 판례 위반 |
|
|
| 대위청구 인적사항 누락 | 강제집행 불가 |
|
|
| 별지 참조 불일치 | 특정 오류 |
|
|
| 관할 임의 확정 (불명 시 placeholder 사용) | 관할위반 위험 |
|
|
|
|
---
|
|
|
|
## 5. 도구 및 Weaviate 호출 스펙
|
|
|
|
### 5.1 기본 도구
|
|
| 도구 | 용도 |
|
|
|------|------|
|
|
| localdocs.read_doc | 입력 파일 읽기 |
|
|
| localdocs.write_file | 소장.md 출력 |
|
|
|
|
### 5.2 Weaviate 검증 (조건부)
|
|
|
|
**실행 조건**: 사해행위취소 청구 포함 시
|
|
|
|
**호출 스펙 1: 사해행위취소 원상회복 검증**
|
|
```
|
|
weaviate.search_hybrid(
|
|
collection_name = "Legal_Books",
|
|
tenant = "Actio_Pauliana_procedure_nullifying_restoration",
|
|
query = "사해행위취소 원상회복 방법",
|
|
limit = 3,
|
|
alpha = 0.5
|
|
)
|
|
```
|
|
|
|
**호출 스펙 2: 병합 소가 검증** (복수 청구 시)
|
|
```
|
|
weaviate.search_hybrid(
|
|
collection_name = "Legal_Books",
|
|
tenant = "Criteria_individual_consolidated_claim",
|
|
query = "병합 청구 소가 산정 기준",
|
|
limit = 3,
|
|
alpha = 0.5
|
|
)
|
|
```
|
|
|
|
### 5.3 오류 처리
|
|
```
|
|
IF tool output starts with "Error:":
|
|
→ function_call.{tool} 네임스페이스로 1회 재시도
|
|
→ 재시도 실패 시: 해당 검증 스킵, [VALIDATION_SKIPPED] 태그 추가
|
|
```
|
|
|
|
---
|
|
|
|
## 6. 종료
|
|
- [ ] CONFIRMED 청구 전체 청구취지/청구원인 생성
|
|
- [ ] 병합 가능 청구 최적화 적용 (금액 합산 없이)
|
|
- [ ] 별지 필요 시 생성 + 본문 참조 일치
|
|
- [ ] 관할법원 결정 (또는 placeholder)
|
|
- [ ] Inline QC 5항목 PASS 또는 수정 완료
|
|
- [ ] **금액 계산 흔적 없음 확인**
|
|
- [ ] 소장.md 출력
|
|
|
|
---
|
|
|
|
## REF
|
|
|
|
**이율 기본값** (비율 문형에 사용):
|
|
| 유형 | 이율1 | 이율2 | 비고 |
|
|
|------|-------|-------|------|
|
|
| 민사법정 | 연 5% | 연 12% | 일반 |
|
|
| 상사법정 | 연 6% | 연 12% | 상행위 |
|
|
| 약정 | 약정이율 | 연 12% | 계약서 확인 |
|
|
| 사해취소 가액배상 | - | 연 5% | 확정일 기산 |
|
|
|
|
**병합 우선순위**: 주종관계 > 선후관계 > 동일피고_동일유형 > 동일피고_상이유형 > 독립
|
|
|
|
tools:
|
|
mcpServers:
|
|
localdocs:
|
|
type: streamable-http
|
|
url: "http://mcp-localdocs:8012/mcp"
|
|
description: Get the content of local documents
|
|
weaviate:
|
|
type: streamable-http
|
|
url: "https://weaviate.eroomai.com/mcp"
|
|
description: Get the content from weaviate
|
|
outsourcing:
|
|
type: streamable-http
|
|
url: "https://outsourcing.mcp.eroomai.com/mcp"
|
|
description: Get the content of local documents
|
|
headers:
|
|
Authorization: "Bearer FftIOt6ppQKrzhaRX8x/olCvRVivoR9SWXYOYeXEREg="
|
|
|
|
prevs: [stage4.5_쿼리_생성_및_조회]
|
|
nexts: []
|