LangChain 에이전트로부터 텍스트가 아닌 객체를 얻으려면, run() 함수에 Zod 스키마를 output으로 전달하면 됩니다. 이 튜토리얼은 단 몇 줄의 코드로 고객 메시지를 애플리케이션에서 사용할 수 있는 주문(order) 객체로 변환하는 방법을 보여줍니다.
이 내용은 'NestJS와 AI 에이전트' 시리즈의 세 번째 파트입니다. Part 2에서는 여기서 사용된 카탈로그 도구(catalog tools)를 에이전트에 제공합니다.
테스트 환경: NestJS 12, LangChain 1.x, Zod 4, nestjs-langchain 2.1 및 Node 22.
구조화된 출력이 바꾸는 것은 무엇인가요?
Difference between with structured output and without structured output
동일한 메시지, 동일한 모델입니다. 스키마가 없으면 에이전트는 텍스트로 응답하며, 코드는 문장에서 SKU를 추출해야 합니다. 하지만 스키마가 있으면, 이는 스키마에 의해 검증되고 타입 지정된 객체로 응답합니다.
모델 자체가 결정론적(deterministic)이지는 않습니다. 어떤 필드에 무엇이 들어갈지 스스로 결정하기 때문입니다. 그러나 그 답변의 형태(shape)는 고정되어 있으며, 이것이 백엔드가 의존하는 부분입니다.
답변을 어떻게 설명하나요?
orders/order-draft.schema.ts에서 Zod 객체를 사용합니다:
import { z } from 'zod';
export const OrderDraft = z.object({
...
모델은 이 스키마와 포함된 설명을 받아서 각 필드를 채웁니다. .transform()과 .refine()도 작동합니다: docs/structured-output.md 문서를 참조하세요.
run()에서 어떻게 가져오나요?
새로운 orders/orders.controller.ts 파일에서 스키마를 output으로 전달합니다:
import { Body, Controller, Post } from '@nestjs/common';
import { Agent } from 'nestjs-langchain';
import { OrderDraft } from './order-draft.schema.js';
...
그런 다음 AppModule의 controllers에 OrdersController를 추가합니다.
output은 OrderDraft 형식입니다: output.sku는 컴파일되지만, 오타는 그렇지 않습니다.
- 입력에서 파트 2의 카탈로그 검색을 요청해야 합니다: 그렇지 않으면 모델이 메모리에서 SKU를 작성할 수 있습니다.
POST /ask는 여전히 텍스트로 응답합니다: 스키마는 에이전트에 속하는 것이 아니라 실행(run)에 속합니다.
사용해 보기 (Try it)
npm run start:dev
curl -X POST http://localhost:3000/orders/draft \
...
{ "sku": "KB-101", "quantity": 2 }
모델은 파트 2의 searchProducts 도구를 사용하여 SKU를 찾은 다음, 스키마를 통해 응답했습니다.
다음 단계: API 키 없이 테스트하기 (Next: test it without an API key)
이제 에이전트는 코드가 신뢰할 수 있는 형태로 응답합니다. 파트 4에서는 LangChain의 fakeModel()을 사용하여 모든 것을 테스트하는데, 이는 도구 호출과 큐에 넣은 답변(카탈로그 도구, 이 엔드포인트, 재시도 및 422 오류)을 제공자나 네트워크 없이 재생합니다. 테스트는 이미 저장소(repo)의 orders/orders.controller.spec.ts에 있습니다.