파싱

잘 지시를 따르는 LLMs(Large Language Models)는 주어진 형식으로 정보를 출력하는 것을 처리할 수 있습니다.

이 접근 방식은 좋은 프롬프트를 설계한 다음 LLMs의 출력을 구문 분석하여 정보를 추출하는 데 의존합니다.

여기서는 Claude를 사용할 것입니다. Claude는 지시를 잘 따르는 능력이 뛰어나죠! 앤트로픽 모델.

from langchain_anthropic.chat_models import ChatAnthropic

model = ChatAnthropic(model_name="claude-3-sonnet-20240229", temperature=0)

팁: 파싱 접근 방식에 대해 추출 품질에 대한 동일한 고려사항이 모두 적용됩니다. 추출 품질 지침을 검토하세요.

이 튜토리얼은 간단하게 유지되어야 하지만 일반적으로 성능을 극대화하기 위해 참조 예제를 포함해야 합니다!

PydanticOutputParser 사용

다음 예제는 내장된 PydanticOutputParser를 사용하여 채팅 모델의 출력을 구문 분석하는 방법을 보여줍니다.

from typing import List, Optional

from langchain.output_parsers import PydanticOutputParser
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.pydantic_v1 import BaseModel, Field, validator


class Person(BaseModel):
    """사람에 관한 정보."""

    name: str = Field(..., description="사람의 이름")
    height_in_meters: float = Field(
        ..., description="미터로 표시된 사람의 키입니다."
    )


class People(BaseModel):
    """텍스트에서 모든 사람에 대한 식별 정보."""

    people: List[Person]


parser = PydanticOutputParser(pydantic_object=People)

prompt = ChatPromptTemplate.from_messages(
    [
        (
            "system",
            "사용자 쿼리에 응답하세요. 출력을 `json` 태그로 둘러십시오\n{format_instructions}",
        ),
        ("human", "{query}"),
    ]
).partial(format_instructions=parser.get_format_instructions())

이제 모델에게 보내는 정보를 살펴봅시다

query = "안나는 23살이고 키가 6피트입니다"
print(prompt.format_prompt(query=query).to_string())
System: 사용자 쿼리에 응답하세요. 출력을 `json` 태그로 둘러십시오
출력은 아래의 JSON 스키마를 준수하는 JSON 인스턴스로 형식화되어야 합니다.

예를 들어 스키마 {"properties": {"foo": {"title": "Foo", "description": "문자열의 목록", "type": "array", "items": {"type": "string"}}}, "required": ["foo"]}에 대해 객체 {"foo": ["bar", "baz"]}는 스키마의 잘 형식화된 인스턴스입니다. 객체 {"properties": {"foo": ["bar", "baz"]}}는 잘 형식화된 것이 아닙니다.

여기 출력 스키마입니다:
{"description": "텍스트에서 모든 사람에 대한 식별 정보.", "properties": {"people": {"title": "People", "type": "array", "items": {"$ref": "#/definitions/Person"}}}, "required": ["people"], "definitions": {"Person": {"title": "Person", "description": "사람에 관한 정보.", "type": "object", "properties": {"name": {"title": "Name", "description": "사람의 이름", "type": "string"}, "height_in_meters": {"title": "Height In Meters", "description": "미터로 표시된 사람의 키입니다.", "type": "number"}}, "required": ["name", "height_in_meters"]}}}

Human: 안나는 23살이고 키가 6피트입니다
chain = prompt | model | parser
chain.invoke({"query": query})
People(people=[Person(name='안나', height_in_meters=1.83)])

사용자 정의 구문 분석

LangChainLCEL을 사용하여 사용자 정의 프롬프트와 구문 분석기를 만드는 것은 쉽습니다.

모델에서 출력을 구문 분석하는 간단한 함수를 사용할 수 있습니다!

import json
import re
from typing import List, Optional

from langchain_anthropic.chat_models import ChatAnthropic
from langchain_core.messages import AIMessage
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.pydantic_v1 import BaseModel, Field, validator


class Person(BaseModel):
    """개인에 대한 정보."""

    name: str = Field(..., description="개인의 이름")
    height_in_meters: float = Field(
        ..., description="미터 단위로 표현된 개인의 키."
    )


class People(BaseModel):
    """텍스트에 있는 모든 사람에 대한 식별 정보."""

    people: List[Person]


prompt = ChatPromptTemplate.from_messages(
    [
        (
            "system",
            "사용자 질의에 답변하십시오. 주어진 스키마와 일치하는 JSON 형식으로 답변을 출력하십시오: ```json\n{schema}\n```. "
            "답변을 반드시 ```json 및 ``` 태그로 감싸야 합니다.",
        ),
        ("human", "{query}"),
    ]
).partial(schema=People.schema())


def extract_json(message: AIMessage) -> List[dict]:
    """JSON이 ```json 및 ``` 태그 사이에 포함된 문자열에서 JSON 콘텐츠를 추출합니다.

    매개변수:
        text (str): JSON 콘텐츠가 포함된 텍스트입니다.

    반환:
        list: 추출된 JSON 문자열의 리스트입니다.
    """
    text = message.content
    pattern = r"```json(.*?)```"

    matches = re.findall(pattern, text, re.DOTALL)

    try:
        return [json.loads(match.strip()) for match in matches]
    except Exception:
        raise ValueError(f"구문 분석 실패: {message}")
query = "안나는 23살이고 키가 6피트입니다"
print(prompt.format_prompt(query=query).to_string())
System: 사용자 질의에 답변하십시오. 주어진 스키마와 일치하는 JSON 형식으로 답변을 출력하십시오: \`\`\`json
{'title': 'People', 'description': '텍스트에 있는 모든 사람에 대한 식별 정보.', 'type': 'object', 'properties': {'people': {'title': 'People', 'type': 'array', 'items': {'$ref': '#/definitions/Person'}}}, 'required': ['people'], 'definitions': {'Person': {'title': 'Person', 'description': '개인에 대한 정보.', 'type': 'object', 'properties': {'name': {'title': 'Name', 'description': '개인의 이름', 'type': 'string'}, 'height_in_meters': {'title': 'Height In Meters', 'description': '미터 단위로 표현된 개인의 키.', 'type': 'number'}}, 'required': ['name', 'height_in_meters']}}}
\`\`\`. 답변을 반드시 \`\`\`json 및 \`\`\` 태그로 감싸야 합니다
Human: 안나는 23살이고 키가 6피트입니다
chain = prompt | model | extract_json
chain.invoke({"query": query})
[{'people': [{'name': '안나', 'height_in_meters': 1.83}]}]

다른 라이브러리

만약 구문 분석 접근 방식으로 추출해야 한다면 Kor 라이브러리를 확인해보세요. 이 라이브러리는 LangChain 유지 보수자 중 한 명이 작성한 것으로 예제를 고려하여 프롬프트를 작성하고, 형식(예: JSON 또는 CSV)을 제어할 수 있으며 TypeScript로 스키마를 표현할 수 있도록 도와줍니다. 매우 효과적으로 작동하는 것으로 보입니다!