Skip to content

대화 응답이 도구로 알 수 있는 사실을 모른다고 답하지 않게 - #93

Merged
SonAIengine merged 1 commit into
mainfrom
fix/conversation-response-declines-known-facts
Oct 24, 2026
Merged

SonAIengine merged 1 commit into
mainfrom
fix/conversation-response-declines-known-facts

Conversation

@SonAIengine

Copy link
Copy Markdown
Contributor

--conversation-responses는 도구가 필요 없는 질문에 답하게 하려고 들어왔지만, 모델에게 매 턴 무료 탈출구를 연다. CONVERSATION_RESPONSE_V1 지침이 한쪽으로만 기울어 있던 탓이다. 도구를 쓰지 말아야 할 때는 "Do not create tool steps merely to answer a conversation question"으로 명시하면서, 도구로 알 수 있는 사실을 모른다고 답하면 안 된다는 반대쪽 문장이 없었다. 그래서 작은 모델은 제일 싼 후보를 골랐다.

어떻게 찾았나

같은 모델(deepseek-flash)·같은 catalog(sh=/bin/bash)에서 플래그만 다르면 결과가 갈렸다.

조건 결과
--conversation-responses 있음 XGEN_RESPONDED — "실시간 주가 데이터에 접근할 수 없어"
없음 (계획 강제) XGEN_COMPLETED — 3,590원, 전일 대비 -125원, 거래량 2,457,715주

영수증으로 확인했다. 실행된 두 step 모두 xgeny.process/execute였고, 첫 호출은 Edge: Too Many Requests로 막혔는데 다른 엔드포인트로 갈아타서 성공했다. 도구를 못 집는 게 아니라 안 집어도 되니 안 집은 것이다.

수정

response_candidate가 사실의 부재를 보고하는 후보가 아님을 적었다. 답이 현재·외부·이 머신에 한정된 사실에 달려 있고 planningContext의 capability가 그것을 얻을 수 있으면 그 capability를 계획하게 한다.

조건을 "a capability in planningContext can obtain that fact"로 적어 문장이 스스로 범위를 한정한다. 도구가 없으면 모델은 그대로 답하므로 catalog 유무로 프롬프트를 조립해 나눌 필요가 없다.

수정 후 실측 (플래그를 켠 채, deepseek-flash)

질문 수정 전 수정 후
오늘 서울 날씨 거절 실제 값, 2/2
서울 미세먼지 수치 - 실제 값
지금 플래티어 주가 거절 거절, 2/2

주가만 남는 것은 도구 추론이 아니라 모델의 거절 반사다. 답변이 능력 부족이 아니라 "시세 제공처에서 확인해야 한다"로 나오고, 같은 부류인 날씨·미세먼지는 뒤집혔으며, 더 큰 모델(deepseek-v4-pro)은 수정 전에도 주가에 도구를 계획했다. 시세나 가격을 프롬프트에 명시해 뚫는 특례는 두지 않는다 — 그게 정확히 시나리오 분기다. 범용 문장 하나가 "현재·외부 사실" 부류를 고쳤고, 금융 시세는 모델 체급으로 남긴다.

아는 비용

프롬프트 바이트는 request-profile digest에 묶이므로 변경 전에 시작한 Run은 resume되지 않는다. 이 문자열을 처음 넣은 #91과 같은 성질이다. 테스트는 프롬프트 바이트나 digest 리터럴을 고정하지 않고 상대 성질과 마커 존재만 보므로 영향이 없다.

검증

  • cargo test --workspace --locked 691 passed, 0 failed, 4 ignored
  • cargo fmt --all -- --check, cargo clippy --workspace --all-targets --locked -- -D warnings
  • 위 실측은 실제 provider와 catalogued shell로 홈서버에서 수행

🤖 Generated with Claude Code

`--conversation-responses`는 도구가 필요 없는 질문에 답하게 하려고 들어왔지만,
모델에게 매 턴 무료 탈출구를 연다. `CONVERSATION_RESPONSE_V1` 지침이 한쪽으로만
기울어 있던 탓이다. 도구를 쓰지 말아야 할 때는 "Do not create tool steps merely
to answer a conversation question"으로 명시하면서, 도구로 알 수 있는 사실을
모른다고 답하면 안 된다는 반대쪽 문장이 없었다. 그래서 작은 모델은 제일 싼
후보를 골랐다.

실측으로 확인했다. 같은 모델(deepseek-flash)·같은 catalog(`sh=/bin/bash`)에서
플래그만 다르면 결과가 갈렸다. 플래그가 켜져 있으면 "실시간 정보는 확인할 수
없습니다"로 끝나고, 꺼서 계획을 강제하면 shell로 네트워크를 호출해 실제 값을
가져왔다. 첫 호출이 rate limit에 걸리자 다른 엔드포인트로 갈아타기까지 했으므로,
도구를 못 집는 게 아니라 안 집어도 되니 안 집은 것이다.

- `response_candidate`가 사실의 부재를 보고하는 후보가 아님을 적었다. 답이
  현재·외부·이 머신에 한정된 사실에 달려 있고 planningContext의 capability가
  그것을 얻을 수 있으면 그 capability를 계획하게 한다.
- 조건을 "a capability in planningContext can obtain that fact"로 적어 문장이
  스스로 범위를 한정한다. 도구가 없으면 모델은 그대로 답하므로 catalog 유무로
  프롬프트를 조립해 나눌 필요가 없다.

수정 후 실측(플래그를 켠 채, deepseek-flash):

| 질문 | 수정 전 | 수정 후 |
| --- | --- | --- |
| 오늘 서울 날씨 | 거절 | 실제 값, 2/2 |
| 서울 미세먼지 수치 | - | 실제 값 |
| 지금 플래티어 주가 | 거절 | 거절, 2/2 |

주가만 남는 것은 도구 추론이 아니라 모델의 거절 반사다. 답변이 능력 부족이
아니라 "시세 제공처에서 확인해야 한다"로 나오고, 같은 부류인 날씨·미세먼지는
뒤집혔으며, 더 큰 모델은 수정 전에도 주가에 도구를 계획했다. 시세나 가격을
프롬프트에 명시해 뚫는 특례는 두지 않는다. 범용 문장 하나가 "현재·외부 사실"
부류를 고쳤고, 금융 시세는 모델 체급으로 남긴다.

프롬프트 바이트는 request-profile digest에 묶이므로 변경 전에 시작한 Run은
resume되지 않는다. 이 문자열을 처음 넣은 변경과 같은 성질이다.

691 passed, 0 failed, 4 ignored. fmt, clippy 통과.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@SonAIengine
SonAIengine merged commit deef767 into main Oct 24, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant