콘텐츠로 이동

부록 C · 실제 LLM 대화 기록 (스냅샷)

자동 생성 문서 — 손으로 편집하지 마세요. 갱신: cd agent && uv run python scripts/export_llm_log.py./deploy-docs.sh

출처: logs/llm/llm-2026-07-03.jsonl · 생성: 2026-07-03T15:04 · 모델: openai/gpt-oss-120b

에이전트가 실제로 OpenRouter(gpt-oss-120b)와 주고받은 기록입니다. 거래 데이터는 전부 fixture(가짜)이며, 운영에서도 개인정보는 WAS 단계에서 마스킹됩니다(ADR-009).

시스템 프롬프트 (모든 호출 공통)

펼쳐서 보기 — app/llm/prompts.py 가 조립한 실제 전송본
당신은 카드 선결제 서비스의 거래 선택 어시스턴트입니다.

## 역할
사용자의 자연어 요청을 해석해서, 제공된 선결제 대상 거래 목록에서 조건에 맞는 거래를 고릅니다.
당신은 거래를 '고르기만' 합니다 — 결제 실행, 합계 계산, 사용자 안내 문구 작성은 시스템의 다른 부분이 담당합니다.

## 거래 데이터 필드
- tx_id: 거래 고유 ID (선택 결과로 반환할 값)
- merchant: 가맹점명
- approved_at: 승인 일시 (ISO 8601, 로컬 시간)
- amount: 결제 금액 (원)

## 판단 규칙
1. intent 결정 기준:
   - "select": 사용자가 조건에 맞는 거래를 찾거나 확인하려는 단계. "~하고 싶어", "~할래", "~보여줘" 같은
     희망·탐색 표현은 결제 단어가 있어도 select 입니다 (시스템이 목록을 먼저 보여주고 확인받습니다)
   - "pay": 사용자가 즉시 실행을 지시하는 경우만 — 명령형 지시("결제해줘", "진행해", "지금 바로 결제")
     또는 직전 제시 목록의 특정 항목 지칭("2번째 것만 결제해줘")
   - "clarify": 요청이 모호해서 조건을 되물어야 하는 경우 — question 에 되물을 문구를, 가능하면 options 에 선택지를 담기
   - "out_of_scope": 선결제와 무관한 요청 (리볼빙, 카드 발급, 한도 조회, 일상 잡담 등)
2. tx_ids 에는 반드시 제공된 목록에 실재하는 tx_id 만 넣습니다. 절대 지어내지 않습니다.
3. 제공된 거래 목록은 이미 선결제 대상으로 조회된 범위입니다. "이번달"처럼 목록 전체 범위를 가리키는 기간 표현은
   목록 전체를 대상으로 삼고, 그 위에 시간대·가맹점 등 나머지 조건만 적용합니다.
4. 시간대 해석 (approved_at 의 시각 기준): "아침"=05:00~11:59, "점심"=12:00~14:59, "저녁/밤"=17:00~23:59.
5. 직전 제시 목록(presented)이 주어지고 사용자가 "2번째", "첫 번째 거"처럼 서수로 지칭하면,
   그 목록의 order 값을 기준으로 해석합니다.
6. 조건에 맞는 거래가 하나도 없으면 intent="select", tx_ids=[] 로 답합니다 (시스템이 되묻기로 처리합니다).

## 판단 예시
- "이번달 아침에 스타벅스에서 커피 먹은 거 전부 결제하고 싶어" → intent="select" ("~하고 싶어"는 탐색·확인 단계)
- "아까 보여준 것 중 2번째 것만 결제해줘" → intent="pay" (제시된 항목에 대한 명령형 지시)
- "커피값 미리 낼게" (기간·가맹점 불명확, 후보가 여러 갈래) → intent="clarify"
- "카드 한도 좀 올려줘" → intent="out_of_scope"

## 출력 형식
반드시 아래 형식의 JSON 하나만 출력합니다. JSON 외의 텍스트·설명·코드펜스를 출력하지 않습니다.
{"intent": "select|pay|clarify|out_of_scope", "tx_ids": ["..."], "question": null, "options": null, "reason": "판단 근거 한 줄"}

user 프롬프트의 형태 (사례 1의 실제 전송본)

펼쳐서 보기 — 거래 목록 + 사용자 발화가 이렇게 담겨 간다
오늘 날짜: 2026-07-03

## 선결제 대상 거래 목록
[
  {
    "tx_id": "TX20260601-001",
    "merchant": "스타벅스 강남점",
    "approved_at": "2026-06-01T08:12:00",
    "amount": 6100
  },
  {
    "tx_id": "TX20260605-014",
    "merchant": "스타벅스 역삼점",
    "approved_at": "2026-06-05T08:45:00",
    "amount": 5600
  },
  {
    "tx_id": "TX20260610-002",
    "merchant": "버거하우스",
    "approved_at": "2026-06-10T12:30:00",
    "amount": 12000
  },
  {
    "tx_id": "TX20260618-007",
    "merchant": "스타벅스 선릉점",
    "approved_at": "2026-06-18T09:02:00",
    "amount": 6800
  },
  {
    "tx_id": "TX20260625-011",
    "merchant": "스타벅스 역삼점",
    "approved_at": "2026-06-25T19:40:00",
    "amount": 5600
  }
]

## 사용자 요청
이번달 아침에 스타벅스에서 커피 먹은 거 전부 결제하고 싶어

정상 사례

사례 1 — “이번달 아침에 스타벅스에서 커피 먹은 거 전부 결제하고 싶어”

하위 제공자 지연 토큰 (입력/출력) structured output trace_id
Together 2497ms 1203 / 173 미사용(프롬프트 강제)

모델 원문 응답:

{
  "intent": "select",
  "tx_ids": [
    "TX20260601-001",
    "TX20260605-014",
    "TX20260618-007"
  ],
  "question": null,
  "options": null,
  "reason": "사용자가 이번달 아침에 스타벅스에서 커피 먹은 거래 전부 결제하고 싶어 함, 해당 조건에 맞는 거래 3건 선택"
}

사례 2 — “아침에 스벅 간 거 다 미리 낼게”

하위 제공자 지연 토큰 (입력/출력) structured output trace_id
DekaLLM 4587ms 1191 / 159 미사용(프롬프트 강제)

모델 원문 응답:

{
  "intent": "select",
  "tx_ids": [
    "TX20260601-001",
    "TX20260605-014",
    "TX20260618-007"
  ],
  "question": null,
  "options": null,
  "reason": "아침(05:00~11:59) 시간대에 승인된 스타벅스 거래만 선택"
}

사례 3 — “오전에 스타벅스에서 쓴 커피값 전부 정리해줘”

하위 제공자 지연 토큰 (입력/출력) structured output trace_id
WandB 2969ms 1193 / 177 미사용(프롬프트 강제)

모델 원문 응답:

{
  "intent": "select",
  "tx_ids": [
    "TX20260601-001",
    "TX20260605-014",
    "TX20260618-007"
  ],
  "question": null,
  "options": null,
  "reason": "사용자가 오전에 스타벅스에서 사용한 거래를 모두 보고 싶어함"
}

사례 4 — “스타벅스에서 쓴 거 전부 보여줘”

하위 제공자 지연 토큰 (입력/출력) structured output trace_id
Mancer 2 3598ms 1189 / 118 미사용(프롬프트 강제)

모델 원문 응답:

{
  "intent": "select",
  "tx_ids": [
    "TX20260601-001",
    "TX20260605-014",
    "TX20260618-007",
    "TX20260625-011"
  ],
  "question": null,
  "options": null,
  "reason": "사용자가 스타벅스 거래 전부를 보고 싶다고 요청했으므로 select이며 해당 가맹점의 tx_id만 반환"
}

사례 5 — “버거하우스에서 쓴 거 지금 바로 결제해줘”

하위 제공자 지연 토큰 (입력/출력) structured output trace_id
WandB 2239ms 1190 / 126 미사용(프롬프트 강제)

모델 원문 응답:

{
  "intent": "pay",
  "tx_ids": [
    "TX20260610-002"
  ],
  "question": null,
  "options": null,
  "reason": "사용자가 '버거하우스에서 쓴 거 지금 바로 결제해줘'라며 즉시 결제를 지시했으며 해당 거래는 목록에 존재"
}

사례 6 — “리볼빙 신청하고 싶은데”

하위 제공자 지연 토큰 (입력/출력) structured output trace_id
DeepInfra 1237ms 1174 / 59 미사용(프롬프트 강제)

모델 원문 응답:

{
  "intent": "out_of_scope",
  "tx_ids": [],
  "question": null,
  "options": null,
  "reason": "리볼빙 신청은 선결제와 무관한 요청"
}

사례 7 — “새벽 2시에 결제한 내역 선결제해줘”

하위 제공자 지연 토큰 (입력/출력) structured output trace_id
Novita 1477ms 1194 / 188 미사용(프롬프트 강제)

모델 원문 응답:

{
  "intent": "select",
  "tx_ids": [],
  "question": null,
  "options": null,
  "reason": "Requested time 02:00 does not match any transaction in the list"
}

사례 8 — “이번달 아침에 스타벅스에서 커피 먹은 거 전부 결제하고 싶어”

하위 제공자 지연 토큰 (입력/출력) structured output trace_id
DekaLLM 8166ms 1199 / 178 미사용(프롬프트 강제) tr-9f8e7d

모델 원문 응답:

{
  "intent": "select",
  "tx_ids": [
    "TX20260601-001",
    "TX20260605-014",
    "TX20260618-007"
  ],
  "question": null,
  "options": null,
  "reason": "요청은 이번달 아침(05:00~11:59) 스타벅스 거래 전부 선택하는 것으로, 해당 조건에 맞는 3건을 반환"
}

오염 응답 사례 — ADR-010 의 증거

structured output(json_schema) 모드에서 일부 하위 제공자가 반환한 실제 오염 응답입니다. 깨진 이스케이프(\":) 뒤로 공백이 토큰 한도까지 이어집니다:

하위 제공자 지연 structured output
(기록 전) 25118ms 사용
{"intent": "select", "tx_ids": ["TX20260601-001", "TX20260605-014", "TX20260618-007"], "question\": null, "





















































… (이후 공백·개행 약 3,728자 — 생략)