ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Kanana-o를 활용한 사진 한 장을 상담 문구로 바꾸는 Agent Harness 개발기
    카테고리 없음 2026. 4. 29. 23:26
    반응형

    Kanana AI 앰배서더로 활동하면서 Kanana-o를 벤치마킹해보다가, 한 가지 생각이 계속 남았다.

    한국어 멀티모달 모델을 그냥 “사진 보고 답하는 챗봇”으로 쓰면 너무 아깝지 않나?

    이미지 속 문자나 고지서를 읽는 것 자체도 중요하지만, 실제 사용자는 OCR 결과만 원하는 게 아니다. 특히 어르신이나 디지털 약자에게 필요한 건 “이게 무슨 뜻인지”, “위험한 건지”, “상담원에게 뭐라고 말하면 되는지”까지 이어지는 안내다.

    그래서 이번에는 Kanana-o API를 활용해서 작은 MVP를 하나 만들었다. 이름은 한장상담이다.

    한장상담은 사진 한 장을 올리면 AI가 문서 유형을 분석하고, 핵심 정보를 추출하고, 위험도를 판단한 뒤, 어르신이 그대로 읽을 수 있는 상담 문구와 쉬운 설명을 만들어주는 CS 보조 서비스다.

    왜 한장상담인가

    가족 단톡방이나 부모님 휴대폰에서 자주 보는 장면이 있다.

    “이 문자 눌러도 돼?”

    “이거 돈 내라는 건가?”

    “병원 예약 문자인데 뭐라고 적혀 있는 거야?”

    “상담원한테 전화하면 뭐라고 말해야 하지?”

    이 문제는 단순히 글자를 읽는 문제가 아니다. 문서 유형, 금액, 날짜, 링크, 전화번호, 계좌번호, 인증번호 같은 정보를 함께 봐야 한다. 그리고 위험할 수 있는 요소가 있으면 바로 “하지 말 것”을 말해줘야 한다.

    그래서 MVP의 목표를 이렇게 잡았다.

    사진 한 장을 올리면, AI Agent가 문서 유형을 분석하고, 핵심 정보를 추출하고, 위험도를 판단한 뒤, 어르신이 이해하기 쉬운 설명과 상담 문구를 만들어준다.

    중요한 건 “한 번에 잘 답하는 모델”이 아니라, 여러 단계를 안전하게 통과시키는 제품 구조였다.

    단순 Vision Chatbot으로 만들지 않았다

    처음부터 의도적으로 단순한 이미지 챗봇 형태는 피했다.

    이미지를 넣고 “설명해줘”라고 하면 모델은 꽤 그럴듯한 답을 만든다. 하지만 CS 보조 서비스에서는 그럴듯함만으로 부족하다. 위험한 링크를 놓치면 안 되고, 계좌번호나 인증번호가 있으면 반드시 위험도를 올려야 하고, 모델 출력이 서비스에서 쓰기 좋은 구조인지도 검증해야 한다.

    그래서 한장상담은 아래처럼 Tool 단위로 쪼갰다.

    모델에게 한 번에 최종 답변을 맡기는 대신, Agent Harness가 실행 순서와 입력/출력 연결을 관리한다. 각 Tool의 출력은 Zod Schema로 검증하고, 위험도는 모델 판단만 믿지 않고 정책 레이어에서 다시 승격한다.

    이번 MVP의 핵심은 Vision 모델 호출 자체가 아니라, 모델을 제품 안에서 다룰 수 있는 형태로 묶는 하네스였다.

    MVP에 넣은 기능

    이번 버전은 의도적으로 작게 만들었다. 로그인, DB 저장, 실제 고객센터 연결, 실제 결제나 송금 대행은 넣지 않았다. “분석과 안내만 하는 보조 도구”로 선을 그었다.

    반드시 필요한 흐름만 넣었다.

    • 이미지 업로드
    • 이미지 미리보기
    • 샘플 이미지로 빠른 테스트
    • AI Agent 분석 실행
    • Agent 단계별 실행 로그 표시
    • 위험도 low / medium / high 표시
    • 상담원에게 말할 문장 생성
    • 브라우저 TTS로 결과 읽기
    • Zod Schema 검증
    • Tool 실패 시 fallback 처리
    • Risk Policy와 Safety Filter

    UI도 어르신 대상이라는 전제를 먼저 잡았다. 작은 글씨나 복잡한 설정을 줄이고, 버튼은 크게, 결과는 “결론 / 하지 말 것 / 지금 할 일” 순서로 먼저 보이게 했다.

    실제 화면

    홈 화면에서는 사진을 직접 올리거나, 샘플 케이스를 눌러 바로 테스트할 수 있다. 오른쪽에는 AI가 어떤 순서로 처리하는지 단계 로그가 보인다. 글 맨 위의 캡처가 이 첫 화면이다.

    처음에는 “Agent Harness”, “Tool” 같은 개발자 표현이 화면에 많았는데, 실제 사용자에게는 어렵다. 그래서 버튼 문구는 “사진 쉽게 설명받기”로 바꾸고, 결과 상단에는 기술 설명보다 행동 안내가 먼저 나오게 했다.

    택배 스미싱 의심 문자 샘플을 넣으면 아래처럼 분석된다.

     

    여기서 중요한 건 링크 원문을 그대로 노출하지 않는다는 점이다. 모델이 URL을 추출하더라도, 최종 UI에서는 “링크가 감지되었어요. 직접 누르지 말고 공식 앱에서 확인하세요.”처럼 안전 문구로 바꿔 보여준다.

    Agent Harness는 어떻게 동작하나

    한장상담의 Agent Harness는 다섯 단계를 순서대로 실행한다.

    단계 역할 출력
    문서 유형 분석 사진이 택배 문자, 통신사 요금, 병원 예약, 인증번호 등 무엇인지 분류 documentType, documentTypeLabel, confidence
    핵심 정보 추출 금액, 날짜, 전화번호, 링크, 계좌번호, 인증번호, 주요 문구 추출 keyInfo
    위험도 판단 금전, 링크, 계좌, 인증번호, 개인정보 여부로 위험도 결정 low / medium / high
    상담 문구 생성 어르신이 상담원에게 그대로 읽을 문장 생성 callScript, nextAction
    쉬운 설명 생성 최종 요약과 쉬운 안내문 생성 easySummary, finalAnswer

    이 구조의 장점은 실패 지점을 알 수 있다는 것이다. 예를 들어 문서 분류는 성공했지만 핵심 정보 추출이 실패하면, 전체 서비스를 죽이지 않고 기본 안내로 전환할 수 있다.

    또한 UI에는 각 단계가 그대로 표시된다. 사용자는 “AI가 뭔가 하고 있다”가 아니라, “문서 유형을 보고, 핵심 정보를 찾고, 위험도를 판단하고 있다”는 흐름을 볼 수 있다.

    모델 출력은 그대로 믿지 않았다

    이번 MVP에서 가장 신경 쓴 부분은 모델 출력 통제다.

    모델은 이미지에서 URL을 잘 읽고도 sensitiveInfo.urlfalse로 줄 수 있다. 금액을 읽고도 money flag를 놓칠 수 있다. 그래서 위험도 판단은 모델이 준 boolean만 믿지 않고 서버에서 한 번 더 재계산하게 했다.

    예를 들어 아래 정보가 하나라도 감지되면 위험도를 올린다.

    • 링크
    • 계좌번호
    • 인증번호
    • 금액 정보
    • 전화번호
    • 주소나 개인정보

    특히 링크, 계좌번호, 인증번호는 high risk로 승격한다. 이건 모델의 친절한 설명보다 우선한다.

    즉, 한장상담에서 모델은 “이해와 초안 생성”을 담당하고, 제품 하네스는 “검증과 안전한 노출”을 담당한다.

    Safety Filter를 붙인 이유

    CS 보조 서비스에서 가장 위험한 순간은 모델이 사용자를 대신해 행동을 유도할 때다.

    예를 들어 이런 문구는 최종 응답에 그대로 나오면 안 된다.

    • 송금하세요
    • 바로 결제하세요
    • 링크를 눌러 주세요
    • 인증번호를 알려 주세요
    • 원격제어 앱을 설치하세요
    • 카드번호를 입력하세요

    그래서 최종 답변, 상담 문구, 다음 행동 문구에 Safety Filter를 적용했다. 위험 행동을 유도하는 문구가 감지되면 아래처럼 안전한 문구로 대체한다.

    직접 송금, 결제, 인증번호 입력, 링크 클릭은 안내하지 않을게요. 공식 고객센터나 공식 앱에서 직접 확인해 주세요.

     

    또 URL, 계좌번호, 인증번호는 UI에 원문으로 노출하지 않고 안전 문구로 마스킹했다. 이건 실제 제품으로 갈수록 더 중요해진다. 모델이 잘못 말하는 것만 위험한 게 아니라, 모델이 너무 잘 읽어낸 위험 정보가 그대로 화면에 노출되는 것도 위험할 수 있기 때문이다.

    Zod Schema는 작은 안전벨트였다

    각 Tool의 출력은 전부 Zod Schema로 검증했다.

    문서 분류는 정해진 document type 중 하나여야 하고, confidence는 0에서 1 사이여야 한다. 핵심 정보는 문자열 길이와 배열 길이를 제한했다. 상담 문구와 최종 답변도 너무 길어지지 않게 제한했다.

    이렇게 하면 모델 응답이 살짝 흔들려도 서비스 쪽에서 빨리 감지할 수 있다.

    이번 MVP에서 넣은 검증 방향은 대략 이렇다.

    영역 검증
    업로드 요청 JSON content-type, data URL 형식, 이미지 타입, base64 크기
    문서 분류 enum 기반 document type, confidence 범위
    핵심 정보 필드 길이 제한, 주요 문구 개수 제한
    위험도 low / medium / high enum
    상담 문구 길이 제한, 위험 행동 필터
    최종 안내 길이 제한, 위험 행동 필터

    여기에 content-length 선검사와 간단한 요청 제한도 넣었다. MVP 수준이지만, 큰 JSON을 먼저 메모리에 올린 뒤 검증하는 구조는 피하고 싶었다.

    평가 케이스도 작게 넣었다

    케이스 기대 문서 유형 기대 위험도 꼭 포함해야 할 방향
    택배 스미싱 의심 문자 택배 안내 문자 high 링크, 스미싱 주의, 공식 경로 확인
    통신사 요금 안내 통신사 요금 medium 요금, 납부, 공식 앱 확인
    병원 예약 안내 병원 예약 low 예약, 방문, 신분증
    인증번호 문자 인증번호 high 인증번호 공유 금지
    아파트 관리비 고지서 관리비 고지서 medium 금액, 납부 기한, 공식 확인

    이건 거대한 벤치마크가 아니라, 제품이 최소한 망가지지 않는지 보는 작은 smoke test에 가깝다. 하지만 MVP 단계에서는 이런 작은 평가 세트가 꽤 유용하다. UI 데모와 블로그 설명이 같은 샘플을 공유할 수 있기 때문이다.

    Kanana-o는 어디에 쓰였나

    모델 호출부는 일부러 얇게 추상화했다.

    한장상담에서 모델은 callVisionModel()이라는 함수 뒤에 숨어 있다. 지금은 Kanana-o API에 맞춰 OpenAI-compatible chat completions 형태로 붙일 수 있게 해두었고, 실제 모델을 바꾸고 싶으면 이 함수나 환경변수만 바꾸면 된다.

    이 구조로 얻은 장점은 명확하다.

    • Kanana-o를 실제 Vision 모델로 연결할 수 있다.
    • 개발 중에는 mock mode로 UI와 하네스를 먼저 완성할 수 있다.
    • 나중에 OpenAI, Gemini, Claude 등 다른 모델과 비교하기 쉽다.
    • 모델이 바뀌어도 Agent Harness, Risk Policy, Safety Filter는 그대로 남는다.

    AI Native 제품을 만들 때 모델 선택은 중요하다. 하지만 모델 선택만큼 중요한 건 모델을 갈아 끼울 수 있는 구조다.

    만들면서 느낀 점

    이번 MVP를 만들면서 가장 크게 느낀 건, 멀티모달 AI 제품의 핵심이 “모델이 이미지를 잘 보느냐”에서 끝나지 않는다는 점이다.

    좋은 모델은 사진 속 문자를 읽고, 상황을 이해하고, 자연스러운 설명을 만든다. 하지만 실제 서비스는 그다음 질문을 해야 한다.

    이 출력은 검증됐나?

    위험한 행동을 유도하지 않나?

    사용자가 지금 무엇을 하면 되는지 한눈에 보이나?

    실패했을 때도 서비스가 안전하게 닫히나?

    한장상담은 이 질문에 대한 작은 답이다. Kanana-o 같은 멀티모달 모델을 앞단에 세우되, 그 뒤에 Tool 분리, Zod Schema, Risk Policy, Safety Filter, fallback을 붙여서 제품으로 쓸 수 있는 흐름을 만든다.

    아직 UI가 많이 AI스럽지만 GPT 이미지 생성과 클로드 디자인을 활용해 보강할 예정이다

    반응형
Designed by Tistory.