3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

StructuredOutputParserの使い方

Last updated at Posted at 2025-04-22

StructuredOutputParserについてまとめておく

2025.4時点でStructuredOutputParserについての記述があまりないので、その一助のために記載しておく
pydamic function callの内藤とかとまじってしまっていて、AIさまも正しい内容をだしてくれてない感じしたので

コード

from duckduckgo_search import DDGS
from langchain_openai import ChatOpenAI, OpenAIEmbeddings
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain.vectorstores import Chroma
from langchain_community.document_loaders import UnstructuredURLLoader
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.runnables import RunnablePassthrough
from langchain.output_parsers import StructuredOutputParser, ResponseSchema

# OutputParserの準備
response_schemas = [
    ResponseSchema(name="address", description="会場の住所"),
    ResponseSchema(name="access", description="アクセス方法"),
    ResponseSchema(name="features", description="会場の特徴"),
    ResponseSchema(name="manager", description="会場の担当者"),
    ResponseSchema(name="tel", description="会場の電話番号"),
    ResponseSchema(name="email", description="メールアドレス"),
    ResponseSchema(name="url", description="URL"),
    ResponseSchema(name="open", type="boolean", description="営業しているかどうか"),
    ResponseSchema(name="venues", type="list", description="会場内の施設のリスト"),
]
# parserを生成
parser = StructuredOutputParser.from_response_schemas(response_schemas)

def register_chroma(word:str):
    # Chromaの初期化
    results = DDGS().text(word, max_results=20, region="jp-jp")
    urls = list(map(lambda x: x['href'], results))
    splitter = RecursiveCharacterTextSplitter(chunk_size=500, chunk_overlap=50)
    loader = UnstructuredURLLoader(urls=urls)
    documents = loader.load()
    docs = splitter.split_documents(documents)
    embeddings = OpenAIEmbeddings()
    chroma = Chroma.from_documents(docs, embeddings, persist_directory="./chromadb")
#    chroma.persist()
    return chroma

word = 'Bunkamura'
chroma = register_chroma(word)
retriever = chroma.as_retriever()
llm = ChatOpenAI(model_name="gpt-4o-mini", temperature=0)
parser = StructuredOutputParser.from_response_schemas(response_schemas)

template = """\
指定された会場の情報を教えてください。
文脈:{context}
{format_instructions}

会場:{input}
"""
# Promptを生成し、内容を部分適用する
prompt = ChatPromptTemplate.from_template(template=template)
prompt_with_parser = prompt.partial(format_instructions=parser.get_format_instructions())

# クエリを投げる
chain = {"context": retriever, "input": RunnablePassthrough()} | prompt_with_parser | llm | parser
result = chain.invoke(word)
print(result)

流れとしては

  • chromadbからのretrieverの読みだし
  • lChatPromptTemlateからpartialを設定して部分適用されたpromptを生成
  • それをLCELで流す
  • ResponseSchemaの型はデフォルトだが、型情報をわたすと、それにしたがって生成する
  • 最終的にはjsonがかえってくる

langchain関連のインポートなりduckduckgoなりのインタフェイスについてはいくらでも情報があるので調べてください

注意

ResponseSchemaのnameのところは問いあわせに使われたりもするので、ミススペルなどするとinvalid jsonで落ちる罠とかある
LLMならではという感じがしますね
(capasityとかいれてたら落ちたよ)

まとめ

ResponseSchemaの使いかたとPromptの流れがわかれば大丈夫だと思います
ではenjoy

3
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?