[번역] LangChain.js: Conceptual Guide: Structured outputs
LangChain.js 의 주요 구성요소 및 개념(concept)들이 LangChain.js conceptual guide 페이지에 나열되어 있습니다. 이 포스트는 LangChain.js 의 concept 중 하나를 번역했습니다.
구조화된 출력 (Structured output)
개요
챗봇과 같은 많은 애플리케이션에서는 모델이 사용자에게 자연어로 직접 응답해야 합니다. 하지만 때로는 모델이 구조화된 형식으로 출력해야 하는 경우가 있습니다. 예를 들어, 모델 출력을 데이터베이스에 저장하고 데이터베이스 스키마에 맞출 필요가 있을 때입니다. 이런 요구사항에서 구조화된 출력 개념이 등장하며, 모델이 특정 출력 구조를 따르도록 지시할 수 있습니다.
구조화된 출력
주요 개념
- 스키마 정의: 출력 구조를 스키마로 표현하며 여러 방식으로 정의할 수 있습니다.
- 구조화된 출력 반환: 모델에 이 스키마를 제공하고 이를 준수하는 출력을 반환하도록 지시합니다.
권장 사용법
다음 의사 코드(pseudo-code)는 구조화된 출력 사용 시 권장 워크플로를 보여줍니다. LangChain은 withStructuredOutput()
메서드를 통해 스키마를 모델에 바인딩하고 출력을 파싱하는 과정을 자동화합니다. 이 헬퍼 함수는 구조화된 출력을 지원하는 모든 모델 제공자에서 사용 가능합니다.
// 스키마 정의 const schema = { foo: "bar" }; // 모델에 스키마 바인딩 const modelWithStructure = model.withStructuredOutput(schema); // 스키마에 맞는 구조화된 출력 생성 const structuredOutput = await modelWithStructure.invoke(userInput);
스키마 정의
출력 구조를 표현하는 핵심 개념입니다. TypeScript에서 일반적으로 허용되는 객체 유형은 모델에 따라 다르지만, Zod 스키마 정의가 가장 간단하고 일반적인 형식입니다:
import { z } from "zod"; const ResponseFormatter = z.object({ answer: z.string().describe("사용자 질문에 대한 답변"), followup_question: z .string() .describe("사용자가 추가로 질문할 수 있는 후속 질문"), });
Zod 스키마는 내부적으로 모델 제공자에게 전송되기 전 JSONSchema로 변환됩니다:
{ "$schema": "https://json-schema.org/draft/2020-12/schema", "title": "ResponseFormatter", "type": "object", "properties": { "answer": { "description": "사용자 질문에 대한 답변", "type": "string" }, "followup_question": { "description": "사용자가 추가로 질문할 수 있는 후속 질문", "type": "string" } }, "required": ["answer", "followup_question"] }
구조화된 출력 반환
스키마를 정의한 후 모델이 이를 사용하도록 지시해야 합니다. 모델 제공자의 API 기능을 활용하는 더 강력한 방법들이 있습니다.
툴 호출(Tool Calling) 사용
많은 모델 제공자가 툴 호출을 지원합니다. 간단히 말해, 스키마를 가진 툴을 생성하고 모델에 바인딩하면 모델이 이 툴을 호출하며 스키마를 준수합니다:
import { ChatOpenAI } from "@langchain/openai"; const model = new ChatOpenAI({ modelName: "gpt-4", temperature: 0, }); // ResponseFormatter 스키마로 툴 생성 const responseFormatterTool = tool(async () => {}, { name: "responseFormatter", schema: ResponseFormatter, }); // 모델에 툴 바인딩 const modelWithTools = model.bindTools([responseFormatterTool]); // 모델 호출 const aiMsg = await modelWithTools.invoke( "세포의 동력실은 무엇인가요?" );
JSON 모드
일부 모델 제공자는 JSON 스키마 정의를 입력으로 받고 JSON 출력을 강제하는 JSON 모드를 지원합니다 (지원 모델 목록):
import { ChatOpenAI } from "@langchain/openai"; const model = new ChatOpenAI({ model: "gpt-4", }).bind({ response_format: { type: "json_object" }, }); const aiMsg = await model.invoke( "'random_nums' 키와 0-99 사이 10개 난수를 값으로 하는 JSON 객체 반환" ); console.log(aiMsg.content); // 출력: { // "random_nums": [23, 47, 89, 15, 34, 76, 58, 3, 62, 91] // }
출력은 여전히 문자열이므로 JSON 객체로 파싱해야 합니다:
const jsonObject = JSON.parse(aiMsg.content); // {'random_ints': [23, 47, 89, 15, 34, 76, 58, 3, 62, 91]}
구조화된 출력 메서드
위 방법들의 문제점을 해결하기 위해 LangChain은 withStructuredOutput()
헬퍼 함수를 제공합니다:
// 스키마 바인딩 const modelWithStructure = model.withStructuredOutput(ResponseFormatter); // 모델 호출 const structuredOutput = await modelWithStructure.invoke( "세포의 동력실은 무엇인가요?" ); // 객체 반환 console.log(structuredOutput); /* 출력: { answer: "세포의 동력실은 미토콘드리아입니다...", followup_question: "세포 내 ATP의 기능은 무엇인가요?" } */
이 메서드는 스키마를 툴로 바인딩하고 출력을 지정된 스키마로 파싱합니다.
관련 자료
- 사용법 상세 정보는 가이드 문서를 참고