- Published on
o1·DeepSeek R1 - CoT 없이 정답률 올리는 7프롬프트
- Authors
- Name
- 스타차일드
- https://x.com/ETFBITX
서로 다른 추론모델(o1, DeepSeek R1 등)을 운영하다 보면, 같은 문제를 던져도 정답률이 들쭉날쭉하거나, 반대로 정답은 맞는데 설명이 과도하게 길어져 비용이 증가하는 상황을 자주 겪습니다. 특히 CoT(Chain-of-Thought)를 그대로 노출시키는 방식은 다음 이슈가 있습니다.
- 보안·정책 상 내부 추론을 그대로 출력하면 곤란한 케이스가 많음
- 장문 출력으로 토큰 비용 증가 및 지연 시간 악화
- 장황한 추론이 오히려 헛발질을 유도하거나, 사용자가 핵심을 놓침
이 글은 CoT를 노출하지 않고도 정답률을 올리는 프롬프트 패턴 7가지를 정리합니다. 핵심은 “생각을 보여달라”가 아니라, 역할 분리, 검증 루프, 제약 조건, 출력 스키마로 모델의 탐색 공간을 줄이고, 오류를 조기에 차단하는 것입니다.
관련해서 CoT 없이 추론을 강화하는 하이브리드 접근은 아래 글도 참고할 만합니다.
기본 원칙: CoT 대신 “검증 가능한 산출물”을 요구하라
추론모델은 내부적으로는 충분히 긴 추론을 수행할 수 있습니다. 다만 우리는 출력에서 이를 강제하지 않고, 대신 아래를 요구하는 편이 안전합니다.
- 최종 답만 또는 짧은 요약 근거만
- 근거는 “추론 과정”이 아니라 근거 유형(규칙/정의/계산 결과/출처) 중심
- 자기검증(checklist), 반례 탐색, **형식 검증(schema validation)**을 출력 요구사항으로 포함
즉, 모델이 스스로 오래 생각하더라도 사용자에게는 “검증 가능한 형태”로만 결과가 나오게 설계합니다.
패턴 1) 출력 스키마 강제: JSON 계약으로 사고를 정렬
정답률을 올리는 가장 손쉬운 방법은 출력 형식을 고정하는 것입니다. 형식이 고정되면 모델이 산만하게 떠들 여지가 줄고, 누락 필드가 곧 오류 신호가 됩니다.
템플릿
- 최종 답
- 신뢰도
- 핵심 근거(최대 3개)
- 체크리스트(예: 단위, 경계값, 예외)
너는 정확한 해답을 내는 분석가다.
추론 과정은 출력하지 말고, 아래 JSON 스키마로만 답하라.
스키마:
{
"answer": string,
"confidence": "low" | "medium" | "high",
"key_reasons": string[1..3],
"checks": string[1..5]
}
문제: {문제 본문}
제약: {제약 조건}
포인트
checks는 CoT가 아니라 검증 항목입니다. 모델이 스스로 검산/검토하도록 유도하지만, 과정은 노출하지 않습니다.- 운영에서는 이 JSON을 파싱해
confidence=low면 재질문, 다른 모델로 폴백, RAG 강화 등 후처리를 붙일 수 있습니다.
패턴 2) 제약 우선 선언: “금지/필수”를 맨 위에 못 박기
추론모델은 장문 지시를 읽지만, 실제로는 우선순위가 흐려지면 중요한 제약을 놓칩니다. 그래서 제약을 “먼저” 선언하고, 그 다음에 문제를 줍니다.
템플릿
규칙(반드시 준수):
1) 추론 과정은 출력하지 않는다.
2) 답은 {형식}으로만 출력한다.
3) {단위/범위/예외}를 반드시 반영한다.
4) 모호하면 필요한 추가 질문을 1개만 한다.
문제:
{문제}
출력 형식:
- Answer:
- Assumptions:
- Edge cases:
포인트
- “모호하면 질문” 규칙을 넣으면, 모델이 임의로 가정해서 틀릴 확률을 줄입니다.
- 질문을 1개로 제한하면 대화가 늘어지는 것을 막습니다.
패턴 3) SCR(자기검증 루프) 라이트 버전: 답·검증·수정 2단계
CoT를 공개하지 않고도 자기검증 루프를 돌릴 수 있습니다. 핵심은 “검증 결과만” 출력하게 하는 것입니다.
템플릿
너는 정답률을 최우선으로 한다.
단계 A: 최종 답을 제시한다.
단계 B: 아래 체크리스트로 스스로 검증하고, 문제가 있으면 답을 수정한다.
- 단위/형식 오류 없음
- 조건 누락 없음
- 반례 1개를 상상했을 때도 성립
출력은 아래 형식만:
Final: ...
Validation: pass | fail
If fail, Revised: ...
포인트
- 모델은 내부적으로 충분히 검토하지만, 외부에는
pass|fail과 수정본만 나옵니다. - 이 방식은 특히 수학/로직/코드 수정에서 효과가 큽니다.
패턴 4) 반례 우선 프롬프트: “틀릴 만한 케이스 3개”부터
정답률이 낮을 때 자주 보이는 원인은 “대표 케이스만 맞고 엣지에서 깨짐”입니다. 그래서 반례 탐색을 먼저 시킵니다.
템플릿
문제를 풀기 전에, 틀리기 쉬운 반례/엣지 케이스 3개를 먼저 나열하라.
그 다음 그 케이스들을 모두 만족하는 최종 답을 한 문장으로 제시하라.
추론 과정은 쓰지 말고, 반례와 최종 답만 출력하라.
문제: {문제}
포인트
- “반례를 먼저”는 모델의 탐색을 넓히되, 출력은 짧게 유지합니다.
- 코드 생성에서도 “실패 테스트”를 먼저 만들게 하면 품질이 올라갑니다.
패턴 5) 도구 사용 분리: 계산·검색은 외부로, 모델은 조립만
추론모델이 강하더라도, 숫자 계산/로그 추적/문서 검색은 실수할 수 있습니다. 도구 호출이 가능하다면 “모델은 계획과 조립”, “도구는 사실과 계산”으로 분리하세요.
예시: 함수 호출 스타일(의사 코드)
아래는 모델이 직접 계산하지 않고, calc()를 호출해 결과를 받아 최종 답을 구성하는 흐름입니다.
{
"task": "solve",
"tools": ["calc"],
"instruction": "계산이 필요하면 calc를 호출하고, 최종 답만 한국어로 요약해라. 추론 과정은 출력하지 마라.",
"input": "연 7% 복리로 3년 뒤 100만원은 얼마?"
}
도구 응답(예시):
{ "tool": "calc", "result": 1225043.0 }
모델 최종 출력(예시):
약 1,225,043원입니다.
포인트
- “계산은 도구”로 강제하면 환각을 줄이고 재현성을 올립니다.
- RAG를 붙일 때도 같은 원리로 “검색은 RAG, 결론은 모델”로 분리합니다.
RAG 비용과 캐시 최적화 관점은 아래 글이 도움 됩니다.
패턴 6) 다중 후보 생성 후 심사: N개 답안 + 심사 기준
한 번에 정답을 맞히기보다, 서로 다른 후보를 만들고 심사 기준으로 고르는 편이 정답률이 올라갑니다. 단, 여기서도 CoT는 숨기고 “후보와 심사 결과”만 받습니다.
템플릿
서로 다른 접근으로 답안 후보 3개를 만들어라(각각 한 문장).
그 다음 아래 심사 기준으로 최선의 후보 1개를 선택하라.
- 제약 조건 충족
- 모순 없음
- 엣지 케이스에 강함
출력 형식:
Candidates:
1) ...
2) ...
3) ...
Selected: 2
Final: ...
포인트
- 후보 생성은 다양성 확보, 심사는 일관성 확보입니다.
- 운영에서는
Candidates를 숨기고Final만 사용자에게 보여주는 정책도 가능합니다.
패턴 7) 실패 모드 선언: “모르면 모른다”를 정교하게 허용
정답률을 올린다는 것은 단순히 맞히는 비율만이 아니라, 틀린 답을 자신 있게 말하는 비율을 줄이는 것도 포함합니다. 그래서 실패 모드를 프롬프트에 포함시키는 것이 중요합니다.
템플릿
아래 조건 중 하나라도 해당하면, 답을 확정하지 말고 필요한 정보 2가지를 질문하라.
- 입력이 모호함
- 전제/데이터가 부족함
- 여러 해석이 가능함
그 외에는 최종 답을 한 문장으로 제시하라.
추론 과정은 출력하지 않는다.
문제: {문제}
포인트
- “질문 2개”처럼 상한을 두면 대화가 통제됩니다.
- 고객지원/장애대응 시나리오에서 특히 유용합니다.
실전 조합 레시피: 7패턴을 한 번에 쓰지 말고, 2~3개만 묶어라
패턴은 많을수록 좋지 않습니다. 지시가 과밀해지면 모델이 우선순위를 잃습니다. 아래 조합이 실전에서 무난합니다.
레시피 A: 일반 QA 정답률 개선
- 패턴 2(제약 우선) + 패턴 1(JSON 스키마) + 패턴 7(실패 모드)
레시피 B: 수학/로직/정책 판단
- 패턴 1(JSON) + 패턴 3(SCR 라이트) + 패턴 4(반례 우선)
레시피 C: RAG 기반 지식 질의
- 패턴 5(도구/검색 분리) + 패턴 1(JSON) + 패턴 7(불확실성 질문)
코드 예제: 재사용 가능한 프롬프트 템플릿(Next.js/Node)
아래는 서버에서 재사용하기 좋은 “스키마 강제 + 자기검증 + 실패 모드” 템플릿 예시입니다. 실제 모델 SDK는 다르지만, 문자열 템플릿 자체는 그대로 가져다 쓸 수 있습니다.
export function buildReasoningPrompt(input: {
problem: string;
constraints?: string[];
}) {
const constraints = (input.constraints ?? []).map((c, i) => `${i + 1}) ${c}`).join("\n");
return `규칙(반드시 준수):
1) 추론 과정은 출력하지 않는다.
2) 출력은 JSON만 허용한다.
3) 모호하거나 정보가 부족하면 questions 배열에 필요한 질문을 최대 2개까지 넣는다.
추가 제약:
${constraints || "(없음)"}
스키마:
{
"answer": string | null,
"confidence": "low" | "medium" | "high",
"key_reasons": string[],
"checks": string[],
"questions": string[]
}
문제:
${input.problem}
검증:
- 단위/범위/예외를 checks에 포함
- 답이 확정 가능하면 questions는 빈 배열
`;
}
운영 팁:
answer=null이고questions가 채워지면, UI에서 바로 사용자에게 추가 입력을 받는 플로우로 연결합니다.confidence=low면 동일 프롬프트로 재시도하기보다 패턴 6(다중 후보)로 전환하는 게 효과적입니다.
정리: CoT를 요구하지 말고, “정답이 나오기 쉬운 구조”를 설계하라
o1·DeepSeek R1 같은 추론모델은 내부적으로 충분히 깊게 생각할 수 있지만, 제품/운영 관점에서는 CoT 노출이 항상 최선이 아닙니다. 대신 아래 7패턴으로 출력 구조화, 제약 우선순위, 자기검증, 반례 탐색, 도구 분리, 다중 후보 심사, 실패 모드를 설계하면 CoT 없이도 정답률과 안정성을 함께 올릴 수 있습니다.
추가로 CoT 대신 학습/정렬 측면에서 접근하고 싶다면 아래 주제도 연결됩니다.
원하는 문제 유형(코딩, 수학, 장애대응, RAG QA 등)을 알려주면, 위 7패턴 중 어떤 조합이 가장 효율적인지와 함께 바로 복붙 가능한 템플릿으로 더 구체화해드릴 수 있습니다.