업무용 스크립트 요청문에 입력·출력·오류 원칙 담기
“자동화해 줘”를 실행 가능한 작업 설명으로 바꿉니다. 민감정보 없는 합성 샘플과 손으로 확인한 기대 결과를 붙여, 팀별 작업 기록 집계 스크립트를 요청하는 문장을 완성합니다.
문서 기반 AI 답변은 각 주장에 줄 번호 인용을 붙이면 훨씬 쉽게 검증할 수 있습니다. 작은 합성 문서를 사용해 AI에게 인용이 포함된 답변을 요청하고, Python으로 각 인용 범위를 자동 확인하는 방법을 설명합니다.
이런 분께보고서, 메모, 규정, 기타 텍스트 문서에 대해 AI 채팅 도우미에게 질문하고 답변의 근거를 쉽게 검증하고 싶은 사람을 위한 내용입니다.
AI 채팅 도우미가 문서에 대해 답할 때 중요한 것은 답변이 자연스럽게 들리는지가 아닙니다. 핵심은 각 주장이 제공된 문서에 실제로 근거하고 있는지 확인하는 것입니다. 줄 번호 인용을 요구하면 검토자가 문서 전체를 다시 검색하지 않고도 바로 원문으로 돌아갈 수 있습니다.
실용적인 검토 흐름은 두 단계로 나눌 수 있습니다. 먼저 프로그램으로 모든 인용이 실제 줄 번호를 가리키는지 확인하고 해당 줄을 다시 추출합니다. 그다음 사람이 인용된 문장이 실제 주장과 의미상 일치하는지 확인합니다. 자동 검증은 잘못되거나 존재하지 않는 참조를 찾는 데 유용하지만, 그것만으로 주장에 대한 의미적 근거가 충분하다는 사실까지 증명하지는 못합니다.
다음과 같은 합성 프로젝트 메모를 사용해 보겠습니다. 아래 7개 줄을 표시된 그대로 project_note.txt 파일에 저장합니다. 예제를 의도적으로 작게 만들었기 때문에 모든 답변과 인용을 손으로도 직접 확인할 수 있습니다.
| 줄 | 내용 |
|---|---|
| L1 | Project Atlas weekly note |
| L2 | Prototype test moved from 12 Sep to 16 Sep. |
| L3 | Reason: replacement sensor arrived late. |
| L4 | Analysis owner: Mina. |
| L5 | Draft results due 18 Sep. |
| L6 | Final review meeting scheduled 21 Sep. |
| L7 | Budget status unchanged. |
질문이 '일정에서 무엇이 변경되었고, 왜 변경되었으며, 이후 마감 일정은 무엇인가?'라고 가정합니다. 원문에는 프로토타입 시험이 12 Sep에서 16 Sep로 변경되었고, 이유는 교체 센서가 늦게 도착했기 때문이며, 초안 결과는 18 Sep까지 제출하고 최종 검토 회의는 21 Sep에 예정되어 있다고 명시되어 있습니다.
단순히 문서를 인용하라고 요청하지 말고, 나중에 스크립트로 분석할 수 있도록 정확한 형식을 지정하는 것이 좋습니다. 이 예제에서는 모든 사실 문장 끝에 [L2-L3] 또는 [L5] 같은 형식의 인용을 붙이도록 합니다.
적절한 답변은 다음과 같을 수 있습니다. 프로토타입 시험은 12 Sep에서 16 Sep로 변경되었으며, 교체 센서가 늦게 도착한 것이 이유입니다. [L2-L3] 초안 결과 제출 기한은 18 Sep이고, 이후 최종 검토 회의가 21 Sep에 예정되어 있습니다. [L5-L6]
이 답변에는 두 개의 인용 범위가 있습니다. 첫 번째 인용은 2번과 3번 줄로 연결되어야 하고, 두 번째 인용은 5번과 6번 줄로 연결되어야 합니다. 답변을 신뢰하기 전에 검증 스크립트로 해당 범위가 실제로 존재하는지 확인하고, 각 인용에 해당하는 원문을 그대로 출력해 볼 수 있습니다.
AI 답변을 ai_answer.txt에 저장합니다. 아래 스크립트는 project_note.txt와 ai_answer.txt를 읽고, 정규식으로 인용을 추출하고, 잘못된 범위를 거부하며, 검토 결과를 outputs/citation_check.txt에 저장합니다. 원본 문서와 AI 답변은 수정하지 않으며, 출력 보고서가 이미 존재하면 중단하도록 설계되어 있습니다.
import re
from pathlib import Path
DOCUMENT_FILE = Path("project_note.txt")
ANSWER_FILE = Path("ai_answer.txt")
OUTPUT_DIR = Path("outputs")
OUTPUT_FILE = OUTPUT_DIR / "citation_check.txt"
CITATION_RE = re.compile(r"\[L(\d+)(?:-L?(\d+))?\]")
def main():
if not DOCUMENT_FILE.is_file():
raise SystemExit(f"Document not found: {DOCUMENT_FILE}")
if not ANSWER_FILE.is_file():
raise SystemExit(f"AI answer not found: {ANSWER_FILE}")
if OUTPUT_FILE.exists():
raise SystemExit(f"Output already exists: {OUTPUT_FILE}")
lines = DOCUMENT_FILE.read_text(encoding="utf-8").splitlines()
answer = ANSWER_FILE.read_text(encoding="utf-8")
matches = list(CITATION_RE.finditer(answer))
if not matches:
raise SystemExit("No citations found in AI answer.")
report = []
report.append(f"document_lines={len(lines)}")
report.append(f"citations_found={len(matches)}")
report.append("")
invalid_count = 0
for index, match in enumerate(matches, start=1):
start = int(match.group(1))
end = int(match.group(2)) if match.group(2) else start
citation = match.group(0)
valid = 1 <= start <= end <= len(lines)
report.append(f"citation_{index}={citation}")
report.append(f"valid_range={valid}")
if not valid:
invalid_count += 1
report.append("source=INVALID LINE RANGE")
report.append("")
continue
for line_number in range(start, end + 1):
source_text = lines[line_number - 1]
report.append(f"L{line_number}: {source_text}")
report.append("")
report.append(f"invalid_citations={invalid_count}")
OUTPUT_DIR.mkdir(parents=True, exist_ok=True)
OUTPUT_FILE.write_text("\n".join(report) + "\n", encoding="utf-8")
print(f"Wrote: {OUTPUT_FILE}")
if __name__ == "__main__":
main()
이 합성 답변에서는 인용 2개가 발견되고 잘못된 인용 범위는 0개여야 합니다. [L2-L3]은 시험 날짜 변경과 교체 센서 지연을 가리키고, [L5-L6]은 초안 결과 마감일과 최종 검토 회의 일정을 가리킵니다.
| 인용 | 예상 추출 줄 | 수동 검토 결론 |
|---|---|---|
| [L2-L3] | L2와 L3 | 변경된 시험 날짜와 명시된 이유를 뒷받침합니다. |
| [L5-L6] | L5와 L6 | 초안 마감일과 최종 검토 회의 날짜를 뒷받침합니다. |
이번에는 [L8] 같은 잘못된 인용을 의도적으로 넣어 볼 수 있습니다. 합성 문서는 7줄뿐이므로 스크립트는 해당 범위를 잘못된 인용으로 표시해야 합니다. 이렇게 하면 문장 안에서는 그럴듯해 보여도 실제 원문에는 존재하지 않는 인용을 찾을 수 있습니다.
이 방법은 일반 텍스트 검토에는 잘 맞지만 PDF, 스프레드시트, OCR 결과, 동적으로 생성되는 문서에서는 줄 경계가 안정적이지 않을 수 있습니다. 이런 경우에는 페이지 번호, 문단 ID, 섹션 ID, 표 셀처럼 더 안정적인 인용 단위를 사용하는 편이 적절할 수 있습니다.
따라서 전체 흐름은 두 단계입니다. 먼저 인용 형식과 줄 범위를 자동 검증하고, 이후 사람이 각 인용 문장이 실제 답변을 뒷받침하는지 확인합니다. 두 단계를 함께 사용하면 출처 없이 생성된 AI 답변보다 문서 질의 결과를 훨씬 쉽게 감사하고 재검토할 수 있습니다.
2026-09-21 · hand-checked example · Python 3.12
설명과 예제는 직접 작성했습니다. 관련 동작과 개념은 아래 공식 자료에서 확인할 수 있습니다.