mirror of
https://github.com/hwchase17/langchain.git
synced 2025-09-22 19:09:57 +00:00
docs: tool-use use case (#15783)
Co-authored-by: Harrison Chase <hw.chase.17@gmail.com>
This commit is contained in:
@@ -9,6 +9,7 @@ from typing import (
|
||||
Union,
|
||||
)
|
||||
|
||||
from langchain_core._api import deprecated
|
||||
from langchain_core.output_parsers import (
|
||||
BaseGenerationOutputParser,
|
||||
BaseLLMOutputParser,
|
||||
@@ -106,7 +107,7 @@ def create_openai_fn_runnable(
|
||||
|
||||
from typing import Optional
|
||||
|
||||
from langchain.chains.openai_functions import create_openai_fn_chain
|
||||
from langchain.chains.openai_functions import create_openai_fn_runnable
|
||||
from langchain_community.chat_models import ChatOpenAI
|
||||
from langchain_core.prompts import ChatPromptTemplate
|
||||
from langchain_core.pydantic_v1 import BaseModel, Field
|
||||
@@ -180,7 +181,7 @@ def create_structured_output_runnable(
|
||||
|
||||
from typing import Optional
|
||||
|
||||
from langchain.chains.openai_functions import create_structured_output_chain
|
||||
from langchain.chains.openai_functions import create_structured_output_runnable
|
||||
from langchain_community.chat_models import ChatOpenAI
|
||||
from langchain_core.prompts import ChatPromptTemplate
|
||||
from langchain_core.pydantic_v1 import BaseModel, Field
|
||||
@@ -200,7 +201,7 @@ def create_structured_output_runnable(
|
||||
("human", "Tip: Make sure to answer in the correct format"),
|
||||
]
|
||||
)
|
||||
chain = create_structured_output_chain(Dog, llm, prompt)
|
||||
chain = create_structured_output_runnable(Dog, llm, prompt)
|
||||
chain.invoke({"input": "Harry was a chubby brown beagle who loved chicken"})
|
||||
# -> Dog(name="Harry", color="brown", fav_food="chicken")
|
||||
""" # noqa: E501
|
||||
@@ -236,6 +237,7 @@ def create_structured_output_runnable(
|
||||
""" --- Legacy --- """
|
||||
|
||||
|
||||
@deprecated(since="0.1.1", removal="0.2.0", alternative="create_openai_fn_runnable")
|
||||
def create_openai_fn_chain(
|
||||
functions: Sequence[Union[Dict[str, Any], Type[BaseModel], Callable]],
|
||||
llm: BaseLanguageModel,
|
||||
@@ -336,6 +338,9 @@ def create_openai_fn_chain(
|
||||
return llm_chain
|
||||
|
||||
|
||||
@deprecated(
|
||||
since="0.1.1", removal="0.2.0", alternative="create_structured_output_runnable"
|
||||
)
|
||||
def create_structured_output_chain(
|
||||
output_schema: Union[Dict[str, Any], Type[BaseModel]],
|
||||
llm: BaseLanguageModel,
|
||||
|
@@ -1,5 +1,6 @@
|
||||
import copy
|
||||
import json
|
||||
from json import JSONDecodeError
|
||||
from typing import Any, List, Type
|
||||
|
||||
from langchain_core.exceptions import OutputParserException
|
||||
@@ -13,6 +14,16 @@ from langchain_core.pydantic_v1 import BaseModel
|
||||
class JsonOutputToolsParser(BaseGenerationOutputParser[Any]):
|
||||
"""Parse tools from OpenAI response."""
|
||||
|
||||
strict: bool = False
|
||||
"""Whether to allow non-JSON-compliant strings.
|
||||
|
||||
See: https://docs.python.org/3/library/json.html#encoders-and-decoders
|
||||
|
||||
Useful when the parsed output may include unicode characters or new lines.
|
||||
"""
|
||||
return_id: bool = False
|
||||
"""Whether to return the tool call id."""
|
||||
|
||||
def parse_result(self, result: List[Generation], *, partial: bool = False) -> Any:
|
||||
generation = result[0]
|
||||
if not isinstance(generation, ChatGeneration):
|
||||
@@ -26,16 +37,30 @@ class JsonOutputToolsParser(BaseGenerationOutputParser[Any]):
|
||||
return []
|
||||
|
||||
final_tools = []
|
||||
exceptions = []
|
||||
for tool_call in tool_calls:
|
||||
if "function" not in tool_call:
|
||||
pass
|
||||
function_args = tool_call["function"]["arguments"]
|
||||
final_tools.append(
|
||||
{
|
||||
"type": tool_call["function"]["name"],
|
||||
"args": json.loads(function_args),
|
||||
}
|
||||
)
|
||||
continue
|
||||
try:
|
||||
function_args = json.loads(
|
||||
tool_call["function"]["arguments"], strict=self.strict
|
||||
)
|
||||
except JSONDecodeError as e:
|
||||
exceptions.append(
|
||||
f"Function {tool_call['function']['name']} arguments:\n\n"
|
||||
f"{tool_call['function']['arguments']}\n\nare not valid JSON. "
|
||||
f"Received JSONDecodeError {e}"
|
||||
)
|
||||
continue
|
||||
parsed = {
|
||||
"type": tool_call["function"]["name"],
|
||||
"args": function_args,
|
||||
}
|
||||
if self.return_id:
|
||||
parsed["id"] = tool_call["id"]
|
||||
final_tools.append(parsed)
|
||||
if exceptions:
|
||||
raise OutputParserException("\n\n".join(exceptions))
|
||||
return final_tools
|
||||
|
||||
|
||||
@@ -44,10 +69,17 @@ class JsonOutputKeyToolsParser(JsonOutputToolsParser):
|
||||
|
||||
key_name: str
|
||||
"""The type of tools to return."""
|
||||
return_single: bool = False
|
||||
"""Whether to return only the first tool call."""
|
||||
|
||||
def parse_result(self, result: List[Generation], *, partial: bool = False) -> Any:
|
||||
results = super().parse_result(result)
|
||||
return [res["args"] for res in results if results["type"] == self.key_name]
|
||||
results = [res for res in results if res["type"] == self.key_name]
|
||||
if not self.return_id:
|
||||
results = [res["args"] for res in results]
|
||||
if self.return_single:
|
||||
return results[0] if results else None
|
||||
return results
|
||||
|
||||
|
||||
class PydanticToolsParser(JsonOutputToolsParser):
|
||||
|
Reference in New Issue
Block a user