Claude 요약에 원문 인용을 붙이게 하고 grep 으로 검증
요약 문장마다 원문 그대로의 인용을 달게 시키고, grep -F 로 그 인용이 원문에 있는지 확인한 뒤, 없는 인용만 다시 묻는 방법입니다.
요약 문장마다 원문 인용을 달게 하고, 그 인용이 원문에 있는지 grep -F 로 확인합니다.
[1] 공개 문서에서 한 절만 잘라 둡니다. 여기서는 RFC 9110 의 9.3.1(GET)~9.3.2(HEAD) 105줄입니다.
$ curl -s https://www.rfc-editor.org/rfc/rfc9110.txt -o rfc9110.txt$ grep -n '^9.3.1\.\|^9.3.3\.' rfc9110.txt3920:9.3.1. GET4025:9.3.3. POST$ sed -n '3920,4024p' rfc9110.txt > doc.txt$ wc -lc doc.txt 105 5854 doc.txt[2] 프롬프트를 만듭니다. 인용은 80자 이하로 글자 그대로 복사하게 하고 출력 형식을 고정합니다. 그래야 인용만 뽑을 수 있습니다.
Summarize the document below in 5 bullet points. Rules:- Each bullet is one sentence, followed by a quote that supports it.- The quote must be copied character for character from the document, 80 characters or fewer. Do not fix spelling, do not use "...".- Output one line per bullet, in exactly this format: <summary sentence> || <quote>- No other text. <document>[3] 프롬프트에 문서를 붙여 claude -p 로 실행합니다. --tools "" 는 도구를 꺼서 붙여 넣은 문서만 보게 합니다.
$ (cat head.txt doc.txt; echo "</document>") > prompt.txt$ claude -p --model claude-sonnet-5-5 --tools "" < prompt.txt > out.txt$ cat out.txtGET requests a current selected representation of the target resource, and a successful response reflects the "sameness" identified by the target URI. || The GET method requests transfer of a current selected representation GET is the primary mechanism of information retrieval and the focus of nearly all performance optimizations. || GET is the primary mechanism of information retrieval and the focus A resource identifier need not map to a file, since resources may be content trees, database views, or gateways to other systems. || as a tree of content objects, a programmatic view on various database Clients should not send content in a GET request because it has no defined semantics and could be rejected as a possible request smuggling attack. || A client SHOULD NOT generate content in a GET HEAD is identical to GET except the server must not send content, and it is used to obtain metadata about the selected representation. || The HEAD method is identical to GET except that the server MUST NOT[4] 검증 스크립트를 만듭니다. RFC 는 문장이 줄 끝에서 꺾이므로, 원문의 공백·줄바꿈을 공백 하나로 합친 뒤 grep -F(글자 그대로)로 찾습니다.
#!/bin/bash# usage: verify.sh doc.txt out.txttr -s ' \n' ' ' < "$1" > /tmp/flat.$$n=0; miss=0while IFS= read -r l; do [ -z "$l" ] && continue n=$((n+1)); q=${l#* || } grep -qF -- "$q" /tmp/flat.$$ || { miss=$((miss+1)); echo "MISS $n: $q"; }done < "$2"rm -f /tmp/flat.$$echo "$n quotes, $miss missing"; [ "$miss" -eq 0 ][5] 검증합니다. 인용 5개는 모두 원문에 있었습니다. 실패하면 종료 코드 1 과 MISS 줄이 나옵니다. 실패 출력은 out.txt 의 네 번째 인용을 손으로 SHOULD NOT → MUST NOT 으로 바꾼 out-bad.txt 로 낸 것입니다(모델이 지어낸 인용이 아닙니다).
$ chmod +x verify.sh$ ./verify.sh doc.txt out.txt; echo "exit $?"5 quotes, 0 missingexit 0$ ./verify.sh doc.txt out-bad.txt; echo "exit $?"MISS 4: A client MUST NOT generate content in a GET5 quotes, 1 missingexit 1[6] 없는 인용이 나온 불릿만 다시 묻습니다. 실패한 줄과 문서를 보내고, 근거가 없으면 NO SUPPORT 로 답하게 합니다.
Your earlier answer contained a quote that does not appear in the document. grep -F could not find it: Clients should not send content in a GET request because it has no defined semantics and could be rejected as a possible request smuggling attack. || A client MUST NOT generate content in a GET Fix only that bullet. Find the sentence in the document below that supports it. If none does, reply with exactly: <summary sentence> || NO SUPPORTOtherwise reply with one line, same format as before:<summary sentence> || <quote copied character for character, 80 characters or fewer>No other text. <document>(문서 105줄)</document>[7] 답을 같은 검증에 다시 통과시킵니다.
$ claude -p --model claude-sonnet-5-5 --tools "" < prompt-fix.txt > fix.txt$ cat fix.txtClients should not send content in a GET request unless the origin server has indicated it will support it. || A client SHOULD NOT generate content in a GET$ ./verify.sh doc.txt fix.txt; echo "exit $?"1 quotes, 0 missingexit 0