mirror of
https://github.com/hwchase17/langchain.git
synced 2025-05-30 03:28:40 +00:00
langchain[patch]: structured output chain nits (#17291)
This commit is contained in:
parent
8a3b74fe1f
commit
50de7a31f0
@ -82,6 +82,7 @@ from langchain.chains.router import (
|
||||
)
|
||||
from langchain.chains.sequential import SequentialChain, SimpleSequentialChain
|
||||
from langchain.chains.sql_database.query import create_sql_query_chain
|
||||
from langchain.chains.structured_output import create_structured_output_runnable
|
||||
from langchain.chains.summarize import load_summarize_chain
|
||||
from langchain.chains.transform import TransformChain
|
||||
|
||||
@ -145,5 +146,6 @@ __all__ = [
|
||||
"create_sql_query_chain",
|
||||
"create_retrieval_chain",
|
||||
"create_history_aware_retriever",
|
||||
"create_structured_output_runnable",
|
||||
"load_summarize_chain",
|
||||
]
|
||||
|
@ -22,7 +22,7 @@ from langchain.output_parsers.openai_functions import (
|
||||
def create_openai_fn_runnable(
|
||||
functions: Sequence[Union[Dict[str, Any], Type[BaseModel], Callable]],
|
||||
llm: Runnable,
|
||||
prompt: BasePromptTemplate,
|
||||
prompt: Optional[BasePromptTemplate] = None,
|
||||
*,
|
||||
enforce_single_function_usage: bool = True,
|
||||
output_parser: Optional[Union[BaseOutputParser, BaseGenerationOutputParser]] = None,
|
||||
@ -64,7 +64,6 @@ def create_openai_fn_runnable(
|
||||
|
||||
from langchain.chains.structured_output import create_openai_fn_runnable
|
||||
from langchain_openai import ChatOpenAI
|
||||
from langchain_core.prompts import ChatPromptTemplate
|
||||
from langchain_core.pydantic_v1 import BaseModel, Field
|
||||
|
||||
|
||||
@ -85,15 +84,8 @@ def create_openai_fn_runnable(
|
||||
|
||||
|
||||
llm = ChatOpenAI(model="gpt-4", temperature=0)
|
||||
prompt = ChatPromptTemplate.from_messages(
|
||||
[
|
||||
("system", "You are a world class algorithm for recording entities."),
|
||||
("human", "Make calls to the relevant function to record the entities in the following input: {input}"),
|
||||
("human", "Tip: Make sure to answer in the correct format"),
|
||||
]
|
||||
)
|
||||
chain = create_openai_fn_runnable([RecordPerson, RecordDog], llm, prompt)
|
||||
chain.invoke({"input": "Harry was a chubby brown beagle who loved chicken"})
|
||||
structured_llm = create_openai_fn_runnable([RecordPerson, RecordDog], llm)
|
||||
structured_llm.invoke("Harry was a chubby brown beagle who loved chicken)
|
||||
# -> RecordDog(name="Harry", color="brown", fav_food="chicken")
|
||||
""" # noqa: E501
|
||||
if not functions:
|
||||
@ -103,14 +95,17 @@ def create_openai_fn_runnable(
|
||||
if len(openai_functions) == 1 and enforce_single_function_usage:
|
||||
llm_kwargs["function_call"] = {"name": openai_functions[0]["name"]}
|
||||
output_parser = output_parser or get_openai_output_parser(functions)
|
||||
return prompt | llm.bind(**llm_kwargs) | output_parser
|
||||
if prompt:
|
||||
return prompt | llm.bind(**llm_kwargs) | output_parser
|
||||
else:
|
||||
return llm.bind(**llm_kwargs) | output_parser
|
||||
|
||||
|
||||
# TODO: implement mode='openai-tools'.
|
||||
def create_structured_output_runnable(
|
||||
output_schema: Union[Dict[str, Any], Type[BaseModel]],
|
||||
llm: Runnable,
|
||||
prompt: BasePromptTemplate,
|
||||
prompt: Optional[BasePromptTemplate] = None,
|
||||
*,
|
||||
output_parser: Optional[Union[BaseOutputParser, BaseGenerationOutputParser]] = None,
|
||||
mode: Literal["openai-functions", "openai-json"] = "openai-functions",
|
||||
@ -152,7 +147,28 @@ def create_structured_output_runnable(
|
||||
|
||||
from typing import Optional
|
||||
|
||||
from langchain.chains.structured_output import create_structured_output_runnable
|
||||
from langchain.chains import create_structured_output_runnable
|
||||
from langchain_openai import ChatOpenAI
|
||||
from langchain_core.pydantic_v1 import BaseModel, Field
|
||||
|
||||
class Dog(BaseModel):
|
||||
'''Identifying information about a dog.'''
|
||||
|
||||
name: str = Field(..., description="The dog's name")
|
||||
color: str = Field(..., description="The dog's color")
|
||||
fav_food: Optional[str] = Field(None, description="The dog's favorite food")
|
||||
|
||||
llm = ChatOpenAI(model="gpt-3.5-turbo-0125", temperature=0)
|
||||
structured_llm = create_structured_output_runnable(Dog, llm, mode="openai-functions")
|
||||
structured_llm.invoke("Harry was a chubby brown beagle who loved chicken")
|
||||
# -> Dog(name="Harry", color="brown", fav_food="chicken")
|
||||
|
||||
OpenAI functions with prompt example:
|
||||
.. code-block:: python
|
||||
|
||||
from typing import Optional
|
||||
|
||||
from langchain.chains import create_structured_output_runnable
|
||||
from langchain_openai import ChatOpenAI
|
||||
from langchain_core.prompts import ChatPromptTemplate
|
||||
from langchain_core.pydantic_v1 import BaseModel, Field
|
||||
@ -165,23 +181,20 @@ def create_structured_output_runnable(
|
||||
fav_food: Optional[str] = Field(None, description="The dog's favorite food")
|
||||
|
||||
llm = ChatOpenAI(model="gpt-3.5-turbo-0125", temperature=0)
|
||||
structured_llm = create_structured_output_runnable(Dog, llm, mode="openai-functions")
|
||||
system = '''Extract information about any dogs mentioned in the user input.'''
|
||||
prompt = ChatPromptTemplate.from_messages(
|
||||
[
|
||||
("system", "You are a world class algorithm for extracting information in structured formats."),
|
||||
("human", "Use the given format to extract information from the following input: {input}"),
|
||||
("human", "Tip: Make sure to answer in the correct format"),
|
||||
]
|
||||
[("system", system), ("human", "{input}"),]
|
||||
)
|
||||
chain = create_structured_output_runnable(Dog, llm, prompt, mode="openai-functions")
|
||||
chain = prompt | structured_llm
|
||||
chain.invoke({"input": "Harry was a chubby brown beagle who loved chicken"})
|
||||
# -> Dog(name="Harry", color="brown", fav_food="chicken")
|
||||
|
||||
OpenAI json response format example:
|
||||
.. code-block:: python
|
||||
|
||||
from typing import Optional
|
||||
|
||||
from langchain.chains.structured_output import create_structured_output_runnable
|
||||
from langchain.chains import create_structured_output_runnable
|
||||
from langchain_openai import ChatOpenAI
|
||||
from langchain_core.prompts import ChatPromptTemplate
|
||||
from langchain_core.pydantic_v1 import BaseModel, Field
|
||||
@ -194,32 +207,30 @@ def create_structured_output_runnable(
|
||||
fav_food: Optional[str] = Field(None, description="The dog's favorite food")
|
||||
|
||||
llm = ChatOpenAI(model="gpt-3.5-turbo-0125", temperature=0)
|
||||
structured_llm = create_structured_output_runnable(Dog, llm, mode="openai-json")
|
||||
system = '''You are a world class assistant for extracting information in structured JSON formats. \
|
||||
|
||||
Extract a valid JSON blob from the user input that matches the following JSON Schema:
|
||||
|
||||
{output_schema}'''
|
||||
prompt = ChatPromptTemplate.from_messages(
|
||||
[
|
||||
("system", system),
|
||||
("human", "{input}"),
|
||||
]
|
||||
[("system", system), ("human", "{input}"),]
|
||||
)
|
||||
chain = create_structured_output_runnable(Dog, llm, prompt, mode="openai-json")
|
||||
chain = prompt | structured_llm
|
||||
chain.invoke({"input": "Harry was a chubby brown beagle who loved chicken"})
|
||||
""" # noqa: E501
|
||||
if mode == "openai-functions":
|
||||
return _create_openai_functions_structured_output_runnable(
|
||||
output_schema,
|
||||
llm,
|
||||
prompt,
|
||||
prompt=prompt,
|
||||
output_parser=output_parser,
|
||||
enforce_single_function_usage=enforce_single_function_usage,
|
||||
**kwargs,
|
||||
)
|
||||
elif mode == "openai-json":
|
||||
return _create_openai_json_runnable(
|
||||
output_schema, llm, prompt, output_parser=output_parser, **kwargs
|
||||
output_schema, llm, prompt=prompt, output_parser=output_parser, **kwargs
|
||||
)
|
||||
else:
|
||||
raise ValueError(
|
||||
@ -263,7 +274,7 @@ def get_openai_output_parser(
|
||||
def _create_openai_json_runnable(
|
||||
output_schema: Union[Dict[str, Any], Type[BaseModel]],
|
||||
llm: Runnable,
|
||||
prompt: BasePromptTemplate,
|
||||
prompt: Optional[BasePromptTemplate] = None,
|
||||
*,
|
||||
output_parser: Optional[Union[BaseOutputParser, BaseGenerationOutputParser]] = None,
|
||||
) -> Runnable:
|
||||
@ -277,17 +288,20 @@ def _create_openai_json_runnable(
|
||||
output_parser = output_parser or JsonOutputParser()
|
||||
schema_as_dict = output_schema
|
||||
|
||||
if "output_schema" in prompt.input_variables:
|
||||
prompt = prompt.partial(output_schema=json.dumps(schema_as_dict, indent=2))
|
||||
|
||||
llm = llm.bind(response_format={"type": "json_object"})
|
||||
return prompt | llm | output_parser
|
||||
if prompt:
|
||||
if "output_schema" in prompt.input_variables:
|
||||
prompt = prompt.partial(output_schema=json.dumps(schema_as_dict, indent=2))
|
||||
|
||||
return prompt | llm | output_parser
|
||||
else:
|
||||
return llm | output_parser
|
||||
|
||||
|
||||
def _create_openai_functions_structured_output_runnable(
|
||||
output_schema: Union[Dict[str, Any], Type[BaseModel]],
|
||||
llm: Runnable,
|
||||
prompt: BasePromptTemplate,
|
||||
prompt: Optional[BasePromptTemplate] = None,
|
||||
*,
|
||||
output_parser: Optional[Union[BaseOutputParser, BaseGenerationOutputParser]] = None,
|
||||
**kwargs: Any,
|
||||
@ -315,7 +329,7 @@ def _create_openai_functions_structured_output_runnable(
|
||||
return create_openai_fn_runnable(
|
||||
[function],
|
||||
llm,
|
||||
prompt,
|
||||
prompt=prompt,
|
||||
output_parser=output_parser,
|
||||
**kwargs,
|
||||
)
|
||||
|
@ -62,6 +62,7 @@ EXPECTED_ALL = [
|
||||
"create_history_aware_retriever",
|
||||
"create_retrieval_chain",
|
||||
"load_summarize_chain",
|
||||
"create_structured_output_runnable",
|
||||
]
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user