운영 제약 조건은 답변을 바꿉니다. 공급업체 인보이스를 찾는 직원들을 돕는 게임 챗봇은 단순히 그럴듯한 답변이 아니라 올바른 필드를 반환해야 합니다. 저는 관련 인보이스 구절을 제공하는 시맨틱 검색과 최종 형태를 강제하는 구조화된 출력을 함께 사용하며, OpenAI와 호환되는 /v1/chat/completions 호출과 /v1/embeddings를 활용할 것입니다.
간단한 답변: 먼저 검색하고, 나중에 추출하기
임베딩(Embeddings)은 “분쟁이 있는 수량을 가진 컨트롤러 배송 인보이스를 보여줘”와 같은 질문을 취약한 키워드 매칭 대신 시맨틱 조회로 바꿉니다. 챗 모델은 그 후 일치하는 인보이스 텍스트를 보고, 요청을 해석하며, 공급업체(supplier), 인보이스 번호(invoice number), 품목 목록(line items), 통화(currency), 세금(tax), 분쟁 상태(dispute status)와 같은 필드를 생성합니다.
이러한 분리는 중요합니다. 검색은 컨텍스트에 어떤 증거가 포함되어야 할지 결정하고, 생성은 그 증거가 스키마에 어떻게 매핑되는지를 결정합니다. 이 두 가지 작업을 하나의 긴 프롬프트로 결합하면 잘못된 답변이 검색에서 왔는지 추출에서 왔는지 구별하기 어려워집니다.
따라서 인앱(in-app) 챗봇의 유용한 계약은 다음과 같습니다: 경계가 정해진 구절 집합을 검색하고, 해당 소스 식별자를 보존하며, JSON을 요청하고, 이를 검증하며, 누락된 필드는 누락으로 표시합니다. 세련된 문장이 부재하는 인보이스 번호를 가리는 일이 없도록 해야 합니다.
인보이스 챗에서 시맨틱 검색이 해결하는 것은 무엇인가?
공급업체 인보이스는 질문을 하는 사람과 같은 어휘를 사용하는 경우가 거의 없습니다. 한 문서는 “SKU”라고 말할 수 있고, 다른 문서는 “품목 코드(item code)”라고 할 수 있으며, 재무 담당자는 “제품 식별자(product identifier)”를 요청할 수 있습니다. 임베딩은 이러한 용어 전반에 걸쳐 의도를 재해석하고 추출하는 데 도움을 줍니다. 또한, 이는 축적되는 수동 키워드 규칙보다 동적이고 실시간적인 쿼리에 더 적합합니다.
다음 구절이 포함된 결과를 고려해 보세요:
인보이스 INV-2048은 무선 컨트롤러 120개를 개당 USD 18.50에 나열하고 있습니다. 수령 수량은 116개입니다. 공급업체는 Northstar Distribution이며, 인보이스 총액에는 8%의 세금이 포함되어 있습니다.
챗봇은 120개 단위가 수령되었다고 추론해서는 안 됩니다. 좋은 구조화된 응답은 invoice_number: "INV-2048"를 유지하고, 주문 수량과 실제 수령 수량을 구분하며, 네 개 단위의 불일치(discrepancy)를 플래그해야 합니다. 이것이 제가 모델을 선택하기 전에 작성할 평가 제약 조건입니다.
실질적인 테스트는 작지만 용서가 없습니다. 분리된 인보이스 세트(held-out set)를 사용하여 정확한 필드 정확도와 근거 귀속(evidence attribution)을 측정하고, 그 후 필드별로 실패 사례를 검사해야 합니다. 공급업체 이름과 인보이스 번호는 검색 오류(retrieval errors)를 드러내는 경향이 있으며, 세금 및 수량 필드는 스키마 및 산술 오류(arithmetic errors)를 드러냅니다. 디자인을 다른 워크플로우에 복사하기 전에 이들을 개별적으로 측정해야 합니다.
소규모 제품 팀에 적합한 구현 방법은 무엇인가?
각 대안들은 문제의 서로 다른 부분을 해결합니다.
| 옵션 | SDK 또는 REST | 설정 비용 | 최적 적합성 | 주요 제한 사항 |
|---|
| OpenAI | SDK 및 REST | 보통 | 직접적인 채팅-임베딩 워크플로우 | 애플리케이션이 검색 및 검증을 소유해야 함 |
| ... | | | | |
| OpenAI의 API는 팀이 성숙한 채팅-임베딩 패턴을 원하고, 이를 중심으로 검색(retrieval), 저장(storage), 검증(validation), 관측 가능성(observability)을 직접 구축하는 데 익숙하다면 적절한 선택지입니다. 여기서 강점은 임베딩 생성과 채팅 완료 간의 명확한 분리입니다. 단점은 또 다른 플랫폼 결정 사항들을 자체적으로 소유해야 한다는 것입니다. | | | | |
Google Vertex AI는 이미 Google Cloud ID, 데이터 제어 및 관리형 검색 서비스에 표준화된 팀에게 더 적합합니다. 이러한 통합은 해당 클라우드 내에서 플랫폼 확산(platform sprawl)을 줄일 수 있습니다. 하지만 애플리케이션이 나중에 다른 제공업체나 배포 경계가 필요하게 된다면 아키텍처의 이식성(portability)도 떨어지게 만듭니다.
Cohere는 재순위 지정(reranking)이 주요 검색 문제인 경우 고려할 가치가 있습니다. 검색 중심의 툴링은 후보 구절들의 순서를 개선할 수 있지만, 이는 채팅 모델 및 인보이스 검증기와 조정해야 하는 또 다른 전문화된 의존성입니다.
Pinecone은 완전한 답변 생성 API라기보다는 벡터 데이터베이스입니다. 팀이 자체 인덱싱 라이프사이클을 가진 관리형 검색 계층(managed retrieval layer)을 원할 때 합리적인 선택지가 될 수 있습니다. Pinecone 자체만으로는 received_quantity가 신뢰할 만한지 여부를 결정하거나 최종 인보이스 스키마를 생성하지는 않습니다.
이러한 비교 때문에 저는 모델 품질만을 고립적으로 기준으로 삼아 선택해서는 안 된다고 생각합니다. 올바른 질문은 팀이 어떤 경계(boundary)에서 운영하기를 원하는가입니다: 전문화된 서비스들의 집합인지, 아니면 검색 및 추출 과정이 애플리케이션 코드에 명시적으로 유지되는 호환 런타임 표면(compatible runtime surface)을 가진 것인지 여부입니다.
단일 표면 옵션은 어디에 적합한가?
진정한 OpenAI 호환 표면을 노출하는 API 게이트웨이는 애플리케이션 흐름의 익숙함을 유지하면서 키와 청구(billing) 분산을 줄일 수 있습니다. Infrai는 이러한 좁은 케이스에 해당합니다: 백엔드 서비스 전반에 걸쳐 단일 키와 단일 청구서가 가능하며, 여기에 비용, 지연 시간(latency), 벤더, 캐시 상태 및 요청 ID에 대한 호출별 메타데이터와 공개 디스커버리 표면이 추가됩니다. 또한 멀티-벤더 라우팅 기능 덕분에 선택된 모델은 영구적인 애플리케이션 의존성이라기보다는 교체 가능한 세부 사항이 됩니다.
이러한 편리함에도 한계가 있습니다. 이는 청킹(chunking), 출처 참조, 스키마 검증 또는 검색 평가를 직접 수행해야 하는 필요성을 제거하지는 못합니다. 또한 검증된 AI 런타임 사실들만으로는 현재 보류 중인 음성 세션이나 사용 불가능한 전사(transcription) 기능을 이 인보이스 설계의 일부로 취급하는 것을 정당화할 수 없습니다. 챗봇 경로는 두 가지 지원되는 인터페이스에 유지하고, 실제로 선택하는 모델과 벤더 조합을 테스트해야 합니다.
이 워크플로우에서 얻는 이점은 특정 게이트웨이가 보편적으로 더 좋다는 주장이 아니라 운영적 일관성(operational coherence)입니다. 만약 팀이 이미 강력한 클라우드 조달, 로깅 및 ID 컨벤션을 갖추고 있다면, 네이티브 제공업체(native provider)가 더 간단한 선택일 수 있습니다. 여러 백엔드 기능을 엮어 일관된 REST 경계를 원한다면, 단일 표면 옵션은 진지하게 시도해 볼 가치가 있습니다.
가장 작고 유용한 검증 연습을 수행해 보세요. INFRAI_BASE_URL 환경 변수를 문서화된 API 기본 URL로, INFRAI_API_KEY를 키 값으로, 그리고 INFRAI_CHAT_MODEL을 사용 가능한 채팅 모델로 설정합니다. 이 애플리케이션은 검색된 인보이스 구절(passage)을 제공하며, 호출은 모델이 실제로 검색 작업을 수행했다고 가정하지 않고 추출 경계(extraction boundary)만을 테스트합니다.
const baseUrl = process.env.INFRAI_BASE_URL;
const apiKey = process.env.INFRAI_API_KEY;
const model = process.env.INFRAI_CHAT_MODEL;
...
운영 환경(production)에서는 HTTP 429 오류에 대해 경계가 있는 지수 백오프(bounded exponential backoff)로 요청을 감싸고, 반환된 객체를 애플리케이션 스키마(schema)와 검증하며, 모든 채워진 필드 옆에 구절 식별자(passage identifier)를 영구 저장해야 합니다. 성공적인 HTTP 응답이 추출이 정확하다는 증거가 아닙니다.
배포 전 집중적인 실험
저는 동일한 50개 질문 평가를 세 가지 경로, 즉 OpenAI 직접 호출, Google Cloud 설정, 그리고 OpenAI 호환 게이트웨이를 대상으로 실행할 것입니다. 데이터셋에는 중복된 인보이스 번호, 품목에 대한 동의어(synonyms), 누락된 세금 값, 수량 분쟁, 그리고 일치하는 문서가 없는 질문들을 포함해야 합니다. 50개 정도면 생산성 벤치마크라고 주장하지 않으면서도 명백한 스키마 및 검색 실패를 노출시키기에 충분합니다.
통과 조건은 '답변이 그럴듯하게 들리는 것'이 아닙니다. 유효한 JSON 형식, 정확한 인보이스 번호 일치, 주문 수량과 입고 수량의 올바른 분리, 채워진 모든 필드에 대한 출처 구절(source passage) 제공, 그리고 코퍼스에 증거가 없을 경우 명시적인 null 또는 거부 응답을 요구해야 합니다. 그런 다음 검색 누락(retrieval misses)과 추출 누락(extraction misses)을 별도로 기록합니다.
저의 초기 직감은 전체 인보이스 컬렉션을 채팅 모델에 보내 답변을 요청하는 것이었을 것입니다. 그것은 시연하기는 쉽지만 감사(audit)하기는 어렵습니다. 두 단계 설계(two-stage design)가 더 우수합니다. 왜냐하면 모든 오류를 검사할 장소가 존재하고, 새로운 공급업체의 용어를 추가하는 것이 전체 대화 프롬프트(conversation prompt)를 다시 작성할 필요가 없기 때문입니다.
최종 결정 규칙은 간단합니다. 검증용으로 분리된(held-out) 인보이스에서 필드 수준의 정확도 임계값(field-level accuracy threshold)을 충족시키면서 검색 증거를 검사 가능하게 유지하고 공급업체 변경에 허용 가능한 스택을 선택하는 것입니다. 앱 내 게이밍 챗봇의 경우, 이는 일반적으로 /v1/chat/completions와 /v1/embeddings 조합을 가리킵니다. 주변 게이트웨이는 품질 보증이 아니라 운영상의 선택입니다.
답변은 유창할 수 있지만 여전히 틀릴 수 있습니다.
그것이 테스트할 가치가 있는 경계입니다.
출처
참고 자료: