langchain 0.2.13__py3-none-any.whl → 0.2.15__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- langchain/_api/module_import.py +2 -2
- langchain/agents/__init__.py +4 -3
- langchain/agents/agent.py +40 -23
- langchain/agents/agent_iterator.py +2 -2
- langchain/agents/agent_toolkits/__init__.py +1 -1
- langchain/agents/agent_toolkits/vectorstore/toolkit.py +2 -1
- langchain/agents/agent_types.py +2 -2
- langchain/agents/chat/base.py +1 -1
- langchain/agents/conversational/base.py +1 -1
- langchain/agents/conversational_chat/base.py +1 -1
- langchain/agents/initialize.py +1 -1
- langchain/agents/json_chat/base.py +1 -1
- langchain/agents/loading.py +2 -2
- langchain/agents/mrkl/base.py +3 -3
- langchain/agents/openai_assistant/base.py +11 -15
- langchain/agents/openai_functions_agent/base.py +1 -1
- langchain/agents/openai_functions_multi_agent/base.py +1 -1
- langchain/agents/react/agent.py +1 -1
- langchain/agents/react/base.py +4 -4
- langchain/agents/self_ask_with_search/base.py +2 -2
- langchain/agents/structured_chat/base.py +3 -2
- langchain/agents/tools.py +2 -2
- langchain/agents/xml/base.py +2 -2
- langchain/chains/base.py +5 -5
- langchain/chains/combine_documents/base.py +4 -4
- langchain/chains/combine_documents/stuff.py +1 -1
- langchain/chains/constitutional_ai/base.py +144 -1
- langchain/chains/conversation/base.py +1 -1
- langchain/chains/conversational_retrieval/base.py +1 -1
- langchain/chains/flare/base.py +42 -69
- langchain/chains/hyde/base.py +18 -8
- langchain/chains/llm_math/base.py +118 -1
- langchain/chains/natbot/base.py +24 -10
- langchain/chains/openai_functions/base.py +2 -2
- langchain/chains/openai_functions/extraction.py +2 -2
- langchain/chains/openai_tools/extraction.py +1 -1
- langchain/chains/query_constructor/parser.py +23 -0
- langchain/chains/structured_output/base.py +2 -2
- langchain/retrievers/document_compressors/chain_extract.py +19 -10
- langchain/retrievers/document_compressors/chain_filter.py +27 -10
- langchain/retrievers/document_compressors/cohere_rerank.py +1 -1
- langchain/retrievers/re_phraser.py +7 -7
- langchain/tools/__init__.py +14 -5
- langchain/tools/render.py +0 -2
- langchain/tools/retriever.py +0 -4
- {langchain-0.2.13.dist-info → langchain-0.2.15.dist-info}/METADATA +2 -2
- {langchain-0.2.13.dist-info → langchain-0.2.15.dist-info}/RECORD +50 -50
- {langchain-0.2.13.dist-info → langchain-0.2.15.dist-info}/LICENSE +0 -0
- {langchain-0.2.13.dist-info → langchain-0.2.15.dist-info}/WHEEL +0 -0
- {langchain-0.2.13.dist-info → langchain-0.2.15.dist-info}/entry_points.txt +0 -0
|
@@ -7,6 +7,7 @@ import re
|
|
|
7
7
|
import warnings
|
|
8
8
|
from typing import Any, Dict, List, Optional
|
|
9
9
|
|
|
10
|
+
from langchain_core._api import deprecated
|
|
10
11
|
from langchain_core.callbacks import (
|
|
11
12
|
AsyncCallbackManagerForChainRun,
|
|
12
13
|
CallbackManagerForChainRun,
|
|
@@ -20,16 +21,132 @@ from langchain.chains.llm import LLMChain
|
|
|
20
21
|
from langchain.chains.llm_math.prompt import PROMPT
|
|
21
22
|
|
|
22
23
|
|
|
24
|
+
@deprecated(
|
|
25
|
+
since="0.2.13",
|
|
26
|
+
message=(
|
|
27
|
+
"This class is deprecated and will be removed in langchain 1.0. "
|
|
28
|
+
"See API reference for replacement: "
|
|
29
|
+
"https://api.python.langchain.com/en/latest/chains/langchain.chains.llm_math.base.LLMMathChain.html" # noqa: E501
|
|
30
|
+
),
|
|
31
|
+
removal="1.0",
|
|
32
|
+
)
|
|
23
33
|
class LLMMathChain(Chain):
|
|
24
34
|
"""Chain that interprets a prompt and executes python code to do math.
|
|
25
35
|
|
|
36
|
+
Note: this class is deprecated. See below for a replacement implementation
|
|
37
|
+
using LangGraph. The benefits of this implementation are:
|
|
38
|
+
|
|
39
|
+
- Uses LLM tool calling features;
|
|
40
|
+
- Support for both token-by-token and step-by-step streaming;
|
|
41
|
+
- Support for checkpointing and memory of chat history;
|
|
42
|
+
- Easier to modify or extend (e.g., with additional tools, structured responses, etc.)
|
|
43
|
+
|
|
44
|
+
Install LangGraph with:
|
|
45
|
+
|
|
46
|
+
.. code-block:: bash
|
|
47
|
+
|
|
48
|
+
pip install -U langgraph
|
|
49
|
+
|
|
50
|
+
.. code-block:: python
|
|
51
|
+
|
|
52
|
+
import math
|
|
53
|
+
from typing import Annotated, Sequence
|
|
54
|
+
|
|
55
|
+
from langchain_core.messages import BaseMessage
|
|
56
|
+
from langchain_core.runnables import RunnableConfig
|
|
57
|
+
from langchain_core.tools import tool
|
|
58
|
+
from langchain_openai import ChatOpenAI
|
|
59
|
+
from langgraph.graph import END, StateGraph
|
|
60
|
+
from langgraph.graph.message import add_messages
|
|
61
|
+
from langgraph.prebuilt.tool_node import ToolNode
|
|
62
|
+
import numexpr
|
|
63
|
+
from typing_extensions import TypedDict
|
|
64
|
+
|
|
65
|
+
@tool
|
|
66
|
+
def calculator(expression: str) -> str:
|
|
67
|
+
\"\"\"Calculate expression using Python's numexpr library.
|
|
68
|
+
|
|
69
|
+
Expression should be a single line mathematical expression
|
|
70
|
+
that solves the problem.
|
|
71
|
+
|
|
72
|
+
Examples:
|
|
73
|
+
"37593 * 67" for "37593 times 67"
|
|
74
|
+
"37593**(1/5)" for "37593^(1/5)"
|
|
75
|
+
\"\"\"
|
|
76
|
+
local_dict = {"pi": math.pi, "e": math.e}
|
|
77
|
+
return str(
|
|
78
|
+
numexpr.evaluate(
|
|
79
|
+
expression.strip(),
|
|
80
|
+
global_dict={}, # restrict access to globals
|
|
81
|
+
local_dict=local_dict, # add common mathematical functions
|
|
82
|
+
)
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
llm = ChatOpenAI(model="gpt-4o-mini", temperature=0)
|
|
86
|
+
tools = [calculator]
|
|
87
|
+
llm_with_tools = llm.bind_tools(tools, tool_choice="any")
|
|
88
|
+
|
|
89
|
+
class ChainState(TypedDict):
|
|
90
|
+
\"\"\"LangGraph state.\"\"\"
|
|
91
|
+
|
|
92
|
+
messages: Annotated[Sequence[BaseMessage], add_messages]
|
|
93
|
+
|
|
94
|
+
async def acall_chain(state: ChainState, config: RunnableConfig):
|
|
95
|
+
last_message = state["messages"][-1]
|
|
96
|
+
response = await llm_with_tools.ainvoke(state["messages"], config)
|
|
97
|
+
return {"messages": [response]}
|
|
98
|
+
|
|
99
|
+
async def acall_model(state: ChainState, config: RunnableConfig):
|
|
100
|
+
response = await llm.ainvoke(state["messages"], config)
|
|
101
|
+
return {"messages": [response]}
|
|
102
|
+
|
|
103
|
+
graph_builder = StateGraph(ChainState)
|
|
104
|
+
graph_builder.add_node("call_tool", acall_chain)
|
|
105
|
+
graph_builder.add_node("execute_tool", ToolNode(tools))
|
|
106
|
+
graph_builder.add_node("call_model", acall_model)
|
|
107
|
+
graph_builder.set_entry_point("call_tool")
|
|
108
|
+
graph_builder.add_edge("call_tool", "execute_tool")
|
|
109
|
+
graph_builder.add_edge("execute_tool", "call_model")
|
|
110
|
+
graph_builder.add_edge("call_model", END)
|
|
111
|
+
chain = graph_builder.compile()
|
|
112
|
+
|
|
113
|
+
.. code-block:: python
|
|
114
|
+
|
|
115
|
+
example_query = "What is 551368 divided by 82"
|
|
116
|
+
|
|
117
|
+
events = chain.astream(
|
|
118
|
+
{"messages": [("user", example_query)]},
|
|
119
|
+
stream_mode="values",
|
|
120
|
+
)
|
|
121
|
+
async for event in events:
|
|
122
|
+
event["messages"][-1].pretty_print()
|
|
123
|
+
|
|
124
|
+
.. code-block:: none
|
|
125
|
+
|
|
126
|
+
================================ Human Message =================================
|
|
127
|
+
|
|
128
|
+
What is 551368 divided by 82
|
|
129
|
+
================================== Ai Message ==================================
|
|
130
|
+
Tool Calls:
|
|
131
|
+
calculator (call_MEiGXuJjJ7wGU4aOT86QuGJS)
|
|
132
|
+
Call ID: call_MEiGXuJjJ7wGU4aOT86QuGJS
|
|
133
|
+
Args:
|
|
134
|
+
expression: 551368 / 82
|
|
135
|
+
================================= Tool Message =================================
|
|
136
|
+
Name: calculator
|
|
137
|
+
|
|
138
|
+
6724.0
|
|
139
|
+
================================== Ai Message ==================================
|
|
140
|
+
|
|
141
|
+
551368 divided by 82 equals 6724.
|
|
142
|
+
|
|
26
143
|
Example:
|
|
27
144
|
.. code-block:: python
|
|
28
145
|
|
|
29
146
|
from langchain.chains import LLMMathChain
|
|
30
147
|
from langchain_community.llms import OpenAI
|
|
31
148
|
llm_math = LLMMathChain.from_llm(OpenAI())
|
|
32
|
-
"""
|
|
149
|
+
""" # noqa: E501
|
|
33
150
|
|
|
34
151
|
llm_chain: LLMChain
|
|
35
152
|
llm: Optional[BaseLanguageModel] = None
|
langchain/chains/natbot/base.py
CHANGED
|
@@ -5,15 +5,27 @@ from __future__ import annotations
|
|
|
5
5
|
import warnings
|
|
6
6
|
from typing import Any, Dict, List, Optional
|
|
7
7
|
|
|
8
|
+
from langchain_core._api import deprecated
|
|
8
9
|
from langchain_core.callbacks import CallbackManagerForChainRun
|
|
9
10
|
from langchain_core.language_models import BaseLanguageModel
|
|
11
|
+
from langchain_core.output_parsers import StrOutputParser
|
|
10
12
|
from langchain_core.pydantic_v1 import root_validator
|
|
13
|
+
from langchain_core.runnables import Runnable
|
|
11
14
|
|
|
12
15
|
from langchain.chains.base import Chain
|
|
13
|
-
from langchain.chains.llm import LLMChain
|
|
14
16
|
from langchain.chains.natbot.prompt import PROMPT
|
|
15
17
|
|
|
16
18
|
|
|
19
|
+
@deprecated(
|
|
20
|
+
since="0.2.13",
|
|
21
|
+
message=(
|
|
22
|
+
"Importing NatBotChain from langchain is deprecated and will be removed in "
|
|
23
|
+
"langchain 1.0. Please import from langchain_community instead: "
|
|
24
|
+
"from langchain_community.chains.natbot import NatBotChain. "
|
|
25
|
+
"You may need to pip install -U langchain-community."
|
|
26
|
+
),
|
|
27
|
+
removal="1.0",
|
|
28
|
+
)
|
|
17
29
|
class NatBotChain(Chain):
|
|
18
30
|
"""Implement an LLM driven browser.
|
|
19
31
|
|
|
@@ -37,7 +49,7 @@ class NatBotChain(Chain):
|
|
|
37
49
|
natbot = NatBotChain.from_default("Buy me a new hat.")
|
|
38
50
|
"""
|
|
39
51
|
|
|
40
|
-
llm_chain:
|
|
52
|
+
llm_chain: Runnable
|
|
41
53
|
objective: str
|
|
42
54
|
"""Objective that NatBot is tasked with completing."""
|
|
43
55
|
llm: Optional[BaseLanguageModel] = None
|
|
@@ -60,7 +72,7 @@ class NatBotChain(Chain):
|
|
|
60
72
|
"class method."
|
|
61
73
|
)
|
|
62
74
|
if "llm_chain" not in values and values["llm"] is not None:
|
|
63
|
-
values["llm_chain"] =
|
|
75
|
+
values["llm_chain"] = PROMPT | values["llm"] | StrOutputParser()
|
|
64
76
|
return values
|
|
65
77
|
|
|
66
78
|
@classmethod
|
|
@@ -77,7 +89,7 @@ class NatBotChain(Chain):
|
|
|
77
89
|
cls, llm: BaseLanguageModel, objective: str, **kwargs: Any
|
|
78
90
|
) -> NatBotChain:
|
|
79
91
|
"""Load from LLM."""
|
|
80
|
-
llm_chain =
|
|
92
|
+
llm_chain = PROMPT | llm | StrOutputParser()
|
|
81
93
|
return cls(llm_chain=llm_chain, objective=objective, **kwargs)
|
|
82
94
|
|
|
83
95
|
@property
|
|
@@ -104,12 +116,14 @@ class NatBotChain(Chain):
|
|
|
104
116
|
_run_manager = run_manager or CallbackManagerForChainRun.get_noop_manager()
|
|
105
117
|
url = inputs[self.input_url_key]
|
|
106
118
|
browser_content = inputs[self.input_browser_content_key]
|
|
107
|
-
llm_cmd = self.llm_chain.
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
119
|
+
llm_cmd = self.llm_chain.invoke(
|
|
120
|
+
{
|
|
121
|
+
"objective": self.objective,
|
|
122
|
+
"url": url[:100],
|
|
123
|
+
"previous_command": self.previous_command,
|
|
124
|
+
"browser_content": browser_content[:4500],
|
|
125
|
+
},
|
|
126
|
+
config={"callbacks": _run_manager.get_child()},
|
|
113
127
|
)
|
|
114
128
|
llm_cmd = llm_cmd.strip()
|
|
115
129
|
self.previous_command = llm_cmd
|
|
@@ -43,7 +43,7 @@ __all__ = [
|
|
|
43
43
|
]
|
|
44
44
|
|
|
45
45
|
|
|
46
|
-
@deprecated(since="0.1.1", removal="
|
|
46
|
+
@deprecated(since="0.1.1", removal="1.0", alternative="create_openai_fn_runnable")
|
|
47
47
|
def create_openai_fn_chain(
|
|
48
48
|
functions: Sequence[Union[Dict[str, Any], Type[BaseModel], Callable]],
|
|
49
49
|
llm: BaseLanguageModel,
|
|
@@ -145,7 +145,7 @@ def create_openai_fn_chain(
|
|
|
145
145
|
|
|
146
146
|
|
|
147
147
|
@deprecated(
|
|
148
|
-
since="0.1.1", removal="
|
|
148
|
+
since="0.1.1", removal="1.0", alternative="ChatOpenAI.with_structured_output"
|
|
149
149
|
)
|
|
150
150
|
def create_structured_output_chain(
|
|
151
151
|
output_schema: Union[Dict[str, Any], Type[BaseModel]],
|
|
@@ -58,7 +58,7 @@ Passage:
|
|
|
58
58
|
"feedback here:"
|
|
59
59
|
"<https://github.com/langchain-ai/langchain/discussions/18154>"
|
|
60
60
|
),
|
|
61
|
-
removal="
|
|
61
|
+
removal="1.0",
|
|
62
62
|
alternative=(
|
|
63
63
|
"""
|
|
64
64
|
from langchain_core.pydantic_v1 import BaseModel, Field
|
|
@@ -128,7 +128,7 @@ def create_extraction_chain(
|
|
|
128
128
|
"feedback here:"
|
|
129
129
|
"<https://github.com/langchain-ai/langchain/discussions/18154>"
|
|
130
130
|
),
|
|
131
|
-
removal="
|
|
131
|
+
removal="1.0",
|
|
132
132
|
alternative=(
|
|
133
133
|
"""
|
|
134
134
|
from langchain_core.pydantic_v1 import BaseModel, Field
|
|
@@ -29,7 +29,7 @@ If a property is not present and is not required in the function parameters, do
|
|
|
29
29
|
"feedback here:"
|
|
30
30
|
"<https://github.com/langchain-ai/langchain/discussions/18154>"
|
|
31
31
|
),
|
|
32
|
-
removal="
|
|
32
|
+
removal="1.0",
|
|
33
33
|
alternative=(
|
|
34
34
|
"""
|
|
35
35
|
from langchain_core.pydantic_v1 import BaseModel, Field
|
|
@@ -35,6 +35,7 @@ GRAMMAR = r"""
|
|
|
35
35
|
?value: SIGNED_INT -> int
|
|
36
36
|
| SIGNED_FLOAT -> float
|
|
37
37
|
| DATE -> date
|
|
38
|
+
| DATETIME -> datetime
|
|
38
39
|
| list
|
|
39
40
|
| string
|
|
40
41
|
| ("false" | "False" | "FALSE") -> false
|
|
@@ -42,6 +43,7 @@ GRAMMAR = r"""
|
|
|
42
43
|
|
|
43
44
|
args: expr ("," expr)*
|
|
44
45
|
DATE.2: /["']?(\d{4}-[01]\d-[0-3]\d)["']?/
|
|
46
|
+
DATETIME.2: /["']?\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d[Zz]?["']?/
|
|
45
47
|
string: /'[^']*'/ | ESCAPED_STRING
|
|
46
48
|
list: "[" [args] "]"
|
|
47
49
|
|
|
@@ -61,6 +63,13 @@ class ISO8601Date(TypedDict):
|
|
|
61
63
|
type: Literal["date"]
|
|
62
64
|
|
|
63
65
|
|
|
66
|
+
class ISO8601DateTime(TypedDict):
|
|
67
|
+
"""A datetime in ISO 8601 format (YYYY-MM-DDTHH:MM:SS)."""
|
|
68
|
+
|
|
69
|
+
datetime: str
|
|
70
|
+
type: Literal["datetime"]
|
|
71
|
+
|
|
72
|
+
|
|
64
73
|
@v_args(inline=True)
|
|
65
74
|
class QueryTransformer(Transformer):
|
|
66
75
|
"""Transform a query string into an intermediate representation."""
|
|
@@ -149,6 +158,20 @@ class QueryTransformer(Transformer):
|
|
|
149
158
|
)
|
|
150
159
|
return {"date": item, "type": "date"}
|
|
151
160
|
|
|
161
|
+
def datetime(self, item: Any) -> ISO8601DateTime:
|
|
162
|
+
item = str(item).strip("\"'")
|
|
163
|
+
try:
|
|
164
|
+
# Parse full ISO 8601 datetime format
|
|
165
|
+
datetime.datetime.strptime(item, "%Y-%m-%dT%H:%M:%S%z")
|
|
166
|
+
except ValueError:
|
|
167
|
+
try:
|
|
168
|
+
datetime.datetime.strptime(item, "%Y-%m-%dT%H:%M:%S")
|
|
169
|
+
except ValueError:
|
|
170
|
+
raise ValueError(
|
|
171
|
+
"Datetime values are expected to be in ISO 8601 format."
|
|
172
|
+
)
|
|
173
|
+
return {"datetime": item, "type": "datetime"}
|
|
174
|
+
|
|
152
175
|
def string(self, item: Any) -> str:
|
|
153
176
|
# Remove escaped quotes
|
|
154
177
|
return str(item).strip("\"'")
|
|
@@ -41,7 +41,7 @@ from langchain_core.utils.pydantic import is_basemodel_subclass
|
|
|
41
41
|
"feedback here: "
|
|
42
42
|
"<https://github.com/langchain-ai/langchain/discussions/18154>"
|
|
43
43
|
),
|
|
44
|
-
removal="
|
|
44
|
+
removal="1.0",
|
|
45
45
|
alternative=(
|
|
46
46
|
"""
|
|
47
47
|
from langchain_core.pydantic_v1 import BaseModel, Field
|
|
@@ -159,7 +159,7 @@ def create_openai_fn_runnable(
|
|
|
159
159
|
"feedback here: "
|
|
160
160
|
"<https://github.com/langchain-ai/langchain/discussions/18154>"
|
|
161
161
|
),
|
|
162
|
-
removal="
|
|
162
|
+
removal="1.0",
|
|
163
163
|
alternative=(
|
|
164
164
|
"""
|
|
165
165
|
from langchain_core.pydantic_v1 import BaseModel, Field
|
|
@@ -8,8 +8,9 @@ from typing import Any, Callable, Dict, Optional, Sequence, cast
|
|
|
8
8
|
from langchain_core.callbacks.manager import Callbacks
|
|
9
9
|
from langchain_core.documents import Document
|
|
10
10
|
from langchain_core.language_models import BaseLanguageModel
|
|
11
|
-
from langchain_core.output_parsers import BaseOutputParser
|
|
11
|
+
from langchain_core.output_parsers import BaseOutputParser, StrOutputParser
|
|
12
12
|
from langchain_core.prompts import PromptTemplate
|
|
13
|
+
from langchain_core.runnables import Runnable
|
|
13
14
|
|
|
14
15
|
from langchain.chains.llm import LLMChain
|
|
15
16
|
from langchain.retrievers.document_compressors.base import BaseDocumentCompressor
|
|
@@ -49,12 +50,15 @@ class LLMChainExtractor(BaseDocumentCompressor):
|
|
|
49
50
|
"""Document compressor that uses an LLM chain to extract
|
|
50
51
|
the relevant parts of documents."""
|
|
51
52
|
|
|
52
|
-
llm_chain:
|
|
53
|
+
llm_chain: Runnable
|
|
53
54
|
"""LLM wrapper to use for compressing documents."""
|
|
54
55
|
|
|
55
56
|
get_input: Callable[[str, Document], dict] = default_get_input
|
|
56
57
|
"""Callable for constructing the chain input from the query and a Document."""
|
|
57
58
|
|
|
59
|
+
class Config:
|
|
60
|
+
arbitrary_types_allowed = True
|
|
61
|
+
|
|
58
62
|
def compress_documents(
|
|
59
63
|
self,
|
|
60
64
|
documents: Sequence[Document],
|
|
@@ -65,10 +69,13 @@ class LLMChainExtractor(BaseDocumentCompressor):
|
|
|
65
69
|
compressed_docs = []
|
|
66
70
|
for doc in documents:
|
|
67
71
|
_input = self.get_input(query, doc)
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
+
output_ = self.llm_chain.invoke(_input, config={"callbacks": callbacks})
|
|
73
|
+
if isinstance(self.llm_chain, LLMChain):
|
|
74
|
+
output = output_[self.llm_chain.output_key]
|
|
75
|
+
if self.llm_chain.prompt.output_parser is not None:
|
|
76
|
+
output = self.llm_chain.prompt.output_parser.parse(output)
|
|
77
|
+
else:
|
|
78
|
+
output = output_
|
|
72
79
|
if len(output) == 0:
|
|
73
80
|
continue
|
|
74
81
|
compressed_docs.append(
|
|
@@ -85,9 +92,7 @@ class LLMChainExtractor(BaseDocumentCompressor):
|
|
|
85
92
|
"""Compress page content of raw documents asynchronously."""
|
|
86
93
|
outputs = await asyncio.gather(
|
|
87
94
|
*[
|
|
88
|
-
self.llm_chain.
|
|
89
|
-
**self.get_input(query, doc), callbacks=callbacks
|
|
90
|
-
)
|
|
95
|
+
self.llm_chain.ainvoke(self.get_input(query, doc), callbacks=callbacks)
|
|
91
96
|
for doc in documents
|
|
92
97
|
]
|
|
93
98
|
)
|
|
@@ -111,5 +116,9 @@ class LLMChainExtractor(BaseDocumentCompressor):
|
|
|
111
116
|
"""Initialize from LLM."""
|
|
112
117
|
_prompt = prompt if prompt is not None else _get_default_chain_prompt()
|
|
113
118
|
_get_input = get_input if get_input is not None else default_get_input
|
|
114
|
-
|
|
119
|
+
if _prompt.output_parser is not None:
|
|
120
|
+
parser = _prompt.output_parser
|
|
121
|
+
else:
|
|
122
|
+
parser = StrOutputParser()
|
|
123
|
+
llm_chain = _prompt | llm | parser
|
|
115
124
|
return cls(llm_chain=llm_chain, get_input=_get_input) # type: ignore[arg-type]
|
|
@@ -5,7 +5,9 @@ from typing import Any, Callable, Dict, Optional, Sequence
|
|
|
5
5
|
from langchain_core.callbacks.manager import Callbacks
|
|
6
6
|
from langchain_core.documents import Document
|
|
7
7
|
from langchain_core.language_models import BaseLanguageModel
|
|
8
|
+
from langchain_core.output_parsers import StrOutputParser
|
|
8
9
|
from langchain_core.prompts import BasePromptTemplate, PromptTemplate
|
|
10
|
+
from langchain_core.runnables import Runnable
|
|
9
11
|
from langchain_core.runnables.config import RunnableConfig
|
|
10
12
|
|
|
11
13
|
from langchain.chains import LLMChain
|
|
@@ -32,13 +34,16 @@ def default_get_input(query: str, doc: Document) -> Dict[str, Any]:
|
|
|
32
34
|
class LLMChainFilter(BaseDocumentCompressor):
|
|
33
35
|
"""Filter that drops documents that aren't relevant to the query."""
|
|
34
36
|
|
|
35
|
-
llm_chain:
|
|
37
|
+
llm_chain: Runnable
|
|
36
38
|
"""LLM wrapper to use for filtering documents.
|
|
37
39
|
The chain prompt is expected to have a BooleanOutputParser."""
|
|
38
40
|
|
|
39
41
|
get_input: Callable[[str, Document], dict] = default_get_input
|
|
40
42
|
"""Callable for constructing the chain input from the query and a Document."""
|
|
41
43
|
|
|
44
|
+
class Config:
|
|
45
|
+
arbitrary_types_allowed = True
|
|
46
|
+
|
|
42
47
|
def compress_documents(
|
|
43
48
|
self,
|
|
44
49
|
documents: Sequence[Document],
|
|
@@ -56,11 +61,15 @@ class LLMChainFilter(BaseDocumentCompressor):
|
|
|
56
61
|
documents,
|
|
57
62
|
)
|
|
58
63
|
|
|
59
|
-
for
|
|
64
|
+
for output_, doc in outputs:
|
|
60
65
|
include_doc = None
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
66
|
+
if isinstance(self.llm_chain, LLMChain):
|
|
67
|
+
output = output_[self.llm_chain.output_key]
|
|
68
|
+
if self.llm_chain.prompt.output_parser is not None:
|
|
69
|
+
include_doc = self.llm_chain.prompt.output_parser.parse(output)
|
|
70
|
+
else:
|
|
71
|
+
if isinstance(output_, bool):
|
|
72
|
+
include_doc = output_
|
|
64
73
|
if include_doc:
|
|
65
74
|
filtered_docs.append(doc)
|
|
66
75
|
|
|
@@ -82,11 +91,15 @@ class LLMChainFilter(BaseDocumentCompressor):
|
|
|
82
91
|
),
|
|
83
92
|
documents,
|
|
84
93
|
)
|
|
85
|
-
for
|
|
94
|
+
for output_, doc in outputs:
|
|
86
95
|
include_doc = None
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
96
|
+
if isinstance(self.llm_chain, LLMChain):
|
|
97
|
+
output = output_[self.llm_chain.output_key]
|
|
98
|
+
if self.llm_chain.prompt.output_parser is not None:
|
|
99
|
+
include_doc = self.llm_chain.prompt.output_parser.parse(output)
|
|
100
|
+
else:
|
|
101
|
+
if isinstance(output_, bool):
|
|
102
|
+
include_doc = output_
|
|
90
103
|
if include_doc:
|
|
91
104
|
filtered_docs.append(doc)
|
|
92
105
|
|
|
@@ -110,5 +123,9 @@ class LLMChainFilter(BaseDocumentCompressor):
|
|
|
110
123
|
A LLMChainFilter that uses the given language model.
|
|
111
124
|
"""
|
|
112
125
|
_prompt = prompt if prompt is not None else _get_default_chain_prompt()
|
|
113
|
-
|
|
126
|
+
if _prompt.output_parser is not None:
|
|
127
|
+
parser = _prompt.output_parser
|
|
128
|
+
else:
|
|
129
|
+
parser = StrOutputParser()
|
|
130
|
+
llm_chain = _prompt | llm | parser
|
|
114
131
|
return cls(llm_chain=llm_chain, **kwargs)
|
|
@@ -13,7 +13,7 @@ from langchain.retrievers.document_compressors.base import BaseDocumentCompresso
|
|
|
13
13
|
|
|
14
14
|
|
|
15
15
|
@deprecated(
|
|
16
|
-
since="0.0.30", removal="
|
|
16
|
+
since="0.0.30", removal="1.0", alternative_import="langchain_cohere.CohereRerank"
|
|
17
17
|
)
|
|
18
18
|
class CohereRerank(BaseDocumentCompressor):
|
|
19
19
|
"""Document compressor that uses `Cohere Rerank API`."""
|
|
@@ -7,11 +7,11 @@ from langchain_core.callbacks import (
|
|
|
7
7
|
)
|
|
8
8
|
from langchain_core.documents import Document
|
|
9
9
|
from langchain_core.language_models import BaseLLM
|
|
10
|
+
from langchain_core.output_parsers import StrOutputParser
|
|
10
11
|
from langchain_core.prompts import BasePromptTemplate
|
|
11
12
|
from langchain_core.prompts.prompt import PromptTemplate
|
|
12
13
|
from langchain_core.retrievers import BaseRetriever
|
|
13
|
-
|
|
14
|
-
from langchain.chains.llm import LLMChain
|
|
14
|
+
from langchain_core.runnables import Runnable
|
|
15
15
|
|
|
16
16
|
logger = logging.getLogger(__name__)
|
|
17
17
|
|
|
@@ -30,7 +30,7 @@ class RePhraseQueryRetriever(BaseRetriever):
|
|
|
30
30
|
Then, retrieve docs for the re-phrased query."""
|
|
31
31
|
|
|
32
32
|
retriever: BaseRetriever
|
|
33
|
-
llm_chain:
|
|
33
|
+
llm_chain: Runnable
|
|
34
34
|
|
|
35
35
|
@classmethod
|
|
36
36
|
def from_llm(
|
|
@@ -51,8 +51,7 @@ class RePhraseQueryRetriever(BaseRetriever):
|
|
|
51
51
|
Returns:
|
|
52
52
|
RePhraseQueryRetriever
|
|
53
53
|
"""
|
|
54
|
-
|
|
55
|
-
llm_chain = LLMChain(llm=llm, prompt=prompt)
|
|
54
|
+
llm_chain = prompt | llm | StrOutputParser()
|
|
56
55
|
return cls(
|
|
57
56
|
retriever=retriever,
|
|
58
57
|
llm_chain=llm_chain,
|
|
@@ -72,8 +71,9 @@ class RePhraseQueryRetriever(BaseRetriever):
|
|
|
72
71
|
Returns:
|
|
73
72
|
Relevant documents for re-phrased question
|
|
74
73
|
"""
|
|
75
|
-
|
|
76
|
-
|
|
74
|
+
re_phrased_question = self.llm_chain.invoke(
|
|
75
|
+
query, {"callbacks": run_manager.get_child()}
|
|
76
|
+
)
|
|
77
77
|
logger.info(f"Re-phrased question: {re_phrased_question}")
|
|
78
78
|
docs = self.retriever.invoke(
|
|
79
79
|
re_phrased_question, config={"callbacks": run_manager.get_child()}
|
langchain/tools/__init__.py
CHANGED
|
@@ -21,7 +21,16 @@ import warnings
|
|
|
21
21
|
from typing import Any
|
|
22
22
|
|
|
23
23
|
from langchain_core._api import LangChainDeprecationWarning
|
|
24
|
-
from langchain_core.tools import
|
|
24
|
+
from langchain_core.tools import (
|
|
25
|
+
BaseTool as BaseTool,
|
|
26
|
+
)
|
|
27
|
+
from langchain_core.tools import (
|
|
28
|
+
StructuredTool as StructuredTool,
|
|
29
|
+
)
|
|
30
|
+
from langchain_core.tools import (
|
|
31
|
+
Tool as Tool,
|
|
32
|
+
)
|
|
33
|
+
from langchain_core.tools.convert import tool as tool
|
|
25
34
|
|
|
26
35
|
from langchain._api.interactive_env import is_interactive_env
|
|
27
36
|
|
|
@@ -75,6 +84,10 @@ def __getattr__(name: str) -> Any:
|
|
|
75
84
|
|
|
76
85
|
|
|
77
86
|
__all__ = [
|
|
87
|
+
"StructuredTool",
|
|
88
|
+
"BaseTool",
|
|
89
|
+
"tool",
|
|
90
|
+
"Tool",
|
|
78
91
|
"AINAppOps",
|
|
79
92
|
"AINOwnerOps",
|
|
80
93
|
"AINRuleOps",
|
|
@@ -92,7 +105,6 @@ __all__ = [
|
|
|
92
105
|
"BaseRequestsTool",
|
|
93
106
|
"BaseSQLDatabaseTool",
|
|
94
107
|
"BaseSparkSQLTool",
|
|
95
|
-
"BaseTool",
|
|
96
108
|
"BearlyInterpreterTool",
|
|
97
109
|
"BingSearchResults",
|
|
98
110
|
"BingSearchRun",
|
|
@@ -181,8 +193,6 @@ __all__ = [
|
|
|
181
193
|
"StdInInquireTool",
|
|
182
194
|
"StackExchangeTool",
|
|
183
195
|
"SteamshipImageGenerationTool",
|
|
184
|
-
"StructuredTool",
|
|
185
|
-
"Tool",
|
|
186
196
|
"VectorStoreQATool",
|
|
187
197
|
"VectorStoreQAWithSourcesTool",
|
|
188
198
|
"WikipediaQueryRun",
|
|
@@ -193,5 +203,4 @@ __all__ = [
|
|
|
193
203
|
"ZapierNLAListActions",
|
|
194
204
|
"ZapierNLARunAction",
|
|
195
205
|
"format_tool_to_openai_function",
|
|
196
|
-
"tool",
|
|
197
206
|
]
|
langchain/tools/render.py
CHANGED
|
@@ -7,7 +7,6 @@ This module contains various ways to render tools.
|
|
|
7
7
|
|
|
8
8
|
# For backwards compatibility
|
|
9
9
|
from langchain_core.tools import (
|
|
10
|
-
ToolsRenderer,
|
|
11
10
|
render_text_description,
|
|
12
11
|
render_text_description_and_args,
|
|
13
12
|
)
|
|
@@ -17,7 +16,6 @@ from langchain_core.utils.function_calling import (
|
|
|
17
16
|
)
|
|
18
17
|
|
|
19
18
|
__all__ = [
|
|
20
|
-
"ToolsRenderer",
|
|
21
19
|
"render_text_description",
|
|
22
20
|
"render_text_description_and_args",
|
|
23
21
|
"format_tool_to_openai_tool",
|
langchain/tools/retriever.py
CHANGED
|
@@ -1,14 +1,10 @@
|
|
|
1
1
|
from langchain_core.tools import (
|
|
2
|
-
RetrieverInput,
|
|
3
|
-
ToolsRenderer,
|
|
4
2
|
create_retriever_tool,
|
|
5
3
|
render_text_description,
|
|
6
4
|
render_text_description_and_args,
|
|
7
5
|
)
|
|
8
6
|
|
|
9
7
|
__all__ = [
|
|
10
|
-
"RetrieverInput",
|
|
11
|
-
"ToolsRenderer",
|
|
12
8
|
"create_retriever_tool",
|
|
13
9
|
"render_text_description",
|
|
14
10
|
"render_text_description_and_args",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: langchain
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.15
|
|
4
4
|
Summary: Building applications with LLMs through composability
|
|
5
5
|
Home-page: https://github.com/langchain-ai/langchain
|
|
6
6
|
License: MIT
|
|
@@ -15,7 +15,7 @@ Requires-Dist: PyYAML (>=5.3)
|
|
|
15
15
|
Requires-Dist: SQLAlchemy (>=1.4,<3)
|
|
16
16
|
Requires-Dist: aiohttp (>=3.8.3,<4.0.0)
|
|
17
17
|
Requires-Dist: async-timeout (>=4.0.0,<5.0.0) ; python_version < "3.11"
|
|
18
|
-
Requires-Dist: langchain-core (>=0.2.
|
|
18
|
+
Requires-Dist: langchain-core (>=0.2.35,<0.3.0)
|
|
19
19
|
Requires-Dist: langchain-text-splitters (>=0.2.0,<0.3.0)
|
|
20
20
|
Requires-Dist: langsmith (>=0.1.17,<0.2.0)
|
|
21
21
|
Requires-Dist: numpy (>=1,<2) ; python_version < "3.12"
|