From 48f318b7a141fd54a0ea42ea7dd70b661fb17885 Mon Sep 17 00:00:00 2001 From: Chester Curme Date: Mon, 25 Nov 2024 15:02:44 -0500 Subject: [PATCH] update citations guide --- docs/docs/how_to/qa_citations.ipynb | 699 +++++++++++++++------------- 1 file changed, 379 insertions(+), 320 deletions(-) diff --git a/docs/docs/how_to/qa_citations.ipynb b/docs/docs/how_to/qa_citations.ipynb index d2b61428771dd..13d230315b801 100644 --- a/docs/docs/how_to/qa_citations.ipynb +++ b/docs/docs/how_to/qa_citations.ipynb @@ -19,7 +19,7 @@ "\n", "We generally suggest using the first item of the list that works for your use-case. That is, if your model supports tool-calling, try methods 1 or 2; otherwise, or if those fail, advance down the list.\n", "\n", - "Let's first create a simple [RAG](/docs/concepts/rag/) chain. To start we'll just retrieve from Wikipedia using the [WikipediaRetriever](https://python.langchain.com/api_reference/community/retrievers/langchain_community.retrievers.wikipedia.WikipediaRetriever.html)." + "Let's first create a simple [RAG](/docs/concepts/rag/) chain. To start we'll just retrieve from Wikipedia using the [WikipediaRetriever](https://python.langchain.com/api_reference/community/retrievers/langchain_community.retrievers.wikipedia.WikipediaRetriever.html). We will use the same [LangGraph](/docs/concepts/architecture/#langgraph) implementation from the [RAG Tutorial](/docs/tutorials/rag)." ] }, { @@ -29,7 +29,7 @@ "source": [ "## Setup\n", "\n", - "First we'll need to install some dependencies and set environment vars for the models we'll be using." + "First we'll need to install some dependencies:" ] }, { @@ -39,28 +39,7 @@ "metadata": {}, "outputs": [], "source": [ - "%pip install -qU langchain langchain-openai langchain-anthropic langchain-community wikipedia" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "id": "8732a85a-dd1a-483c-8da7-a81251276aa1", - "metadata": {}, - "outputs": [], - "source": [ - "import getpass\n", - "import os\n", - "\n", - "if not os.environ.get(\"OPENAI_API_KEY\"):\n", - " os.environ[\"OPENAI_API_KEY\"] = getpass.getpass()\n", - "\n", - "if not os.environ.get(\"ANTHROPIC_API_KEY\"):\n", - " os.environ[\"ANTHROPIC_API_KEY\"] = getpass.getpass()\n", - "\n", - "# Uncomment if you want to log to LangSmith\n", - "# os.environ[\"LANGCHAIN_TRACING_V2\"] = \"true\n", - "# os.environ[\"LANGCHAIN_API_KEY\"] = getpass.getpass()" + "%pip install -qU langchain-community wikipedia" ] }, { @@ -87,12 +66,20 @@ "\n", "from langchain_openai import ChatOpenAI\n", "\n", - "llm = ChatOpenAI()" + "llm = ChatOpenAI(model=\"gpt-4o-mini\")" + ] + }, + { + "cell_type": "markdown", + "id": "916f7524-51cf-4afc-90b9-faccd2b44ef3", + "metadata": {}, + "source": [ + "We can now load a [retriever](/docs/concepts/retrievers/) and construct our [prompt](/docs/concepts/prompt_templates/):" ] }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 7, "id": "4e17c3f6-8ce6-4767-b615-50a57c84c7b0", "metadata": {}, "outputs": [ @@ -108,7 +95,7 @@ "\n", "================================\u001b[1m Human Message \u001b[0m=================================\n", "\n", - "\u001b[33;1m\u001b[1;3m{input}\u001b[0m\n" + "\u001b[33;1m\u001b[1;3m{question}\u001b[0m\n" ] } ], @@ -129,7 +116,7 @@ "prompt = ChatPromptTemplate.from_messages(\n", " [\n", " (\"system\", system_prompt),\n", - " (\"human\", \"{input}\"),\n", + " (\"human\", \"{question}\"),\n", " ]\n", ")\n", "prompt.pretty_print()" @@ -140,121 +127,111 @@ "id": "c89e2045-9244-43e6-bf3f-59af22658529", "metadata": {}, "source": [ - "Now that we've got a [model](/docs/concepts/chat_models/), [retriver](/docs/concepts/retrievers/) and [prompt](/docs/concepts/prompt_templates/), let's chain them all together. We'll need to add some logic for formatting our retrieved Documents to a string that can be passed to our prompt. Following the how-to guide on [adding citations](/docs/how_to/qa_citations) to a RAG application, we'll make it so our chain returns both the answer and the retrieved Documents." + "Now that we've got a [model](/docs/concepts/chat_models/), [retriver](/docs/concepts/retrievers/) and [prompt](/docs/concepts/prompt_templates/), let's chain them all together. Following the how-to guide on [adding citations](/docs/how_to/qa_citations) to a RAG application, we'll make it so our chain returns both the answer and the retrieved Documents. This uses the same [LangGraph](/docs/concepts/architecture/#langgraph) implementation as in the [RAG Tutorial](/docs/tutorials/rag)." ] }, { "cell_type": "code", "execution_count": 4, - "id": "4cd55e1c-a6b7-44b7-9dde-5f42abe714ea", + "id": "e69a4698-9258-41bd-a9d2-0d2a03cd8872", "metadata": {}, "outputs": [], "source": [ - "from typing import List\n", - "\n", "from langchain_core.documents import Document\n", - "from langchain_core.output_parsers import StrOutputParser\n", - "from langchain_core.runnables import RunnablePassthrough\n", + "from langgraph.graph import START, StateGraph\n", + "from typing_extensions import List, TypedDict\n", "\n", "\n", - "def format_docs(docs: List[Document]):\n", - " return \"\\n\\n\".join(doc.page_content for doc in docs)\n", + "# Define state for application\n", + "class State(TypedDict):\n", + " question: str\n", + " context: List[Document]\n", + " answer: str\n", "\n", "\n", - "rag_chain_from_docs = (\n", - " RunnablePassthrough.assign(context=(lambda x: format_docs(x[\"context\"])))\n", - " | prompt\n", - " | llm\n", - " | StrOutputParser()\n", - ")\n", + "# Define application steps\n", + "def retrieve(state: State):\n", + " retrieved_docs = retriever.invoke(state[\"question\"])\n", + " return {\"context\": retrieved_docs}\n", "\n", - "retrieve_docs = (lambda x: x[\"input\"]) | retriever\n", "\n", - "chain = RunnablePassthrough.assign(context=retrieve_docs).assign(\n", - " answer=rag_chain_from_docs\n", - ")" + "def generate(state: State):\n", + " docs_content = \"\\n\\n\".join(doc.page_content for doc in state[\"context\"])\n", + " messages = prompt.invoke({\"question\": state[\"question\"], \"context\": docs_content})\n", + " response = llm.invoke(messages)\n", + " return {\"answer\": response.content}\n", + "\n", + "\n", + "# Compile application and test\n", + "graph_builder = StateGraph(State).add_sequence([retrieve, generate])\n", + "graph_builder.add_edge(START, \"retrieve\")\n", + "graph = graph_builder.compile()" ] }, { "cell_type": "code", "execution_count": 5, - "id": "42b28717-d34c-42de-b923-155ac60529a2", - "metadata": {}, - "outputs": [], - "source": [ - "result = chain.invoke({\"input\": \"How fast are cheetahs?\"})" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "id": "8b20cf8e-dccd-45d1-aef0-25f1ad1aca6d", + "id": "37eaab79-74cd-4806-bdbd-7340652c425a", "metadata": {}, "outputs": [ { - "name": "stdout", - "output_type": "stream", - "text": [ - "dict_keys(['input', 'context', 'answer'])\n" - ] - } - ], - "source": [ - "print(result.keys())" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "id": "ae5ed9a7-c72a-480d-80c6-0a6bd38b9941", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "page_content='The cheetah (Acinonyx jubatus) is a large cat and the fastest land animal. It has a tawny to creamy white or pale buff fur that is marked with evenly spaced, solid black spots. The head is small and rounded, with a short snout and black tear-like facial streaks. It reaches 67–94 cm (26–37 in) at the shoulder, and the head-and-body length is between 1.1 and 1.5 m (3 ft 7 in and 4 ft 11 in). Adults weigh between 21 and 72 kg (46 and 159 lb). The cheetah is capable of running at 93 to 104 km/h (58 to 65 mph); it has evolved specialized adaptations for speed, including a light build, long thin legs and a long tail.\\nThe cheetah was first described in the late 18th century. Four subspecies are recognised today that are native to Africa and central Iran. An African subspecies was introduced to India in 2022. It is now distributed mainly in small, fragmented populations in northwestern, eastern and southern Africa and central Iran. It lives in a variety of habitats such as savannahs in the Serengeti, arid mountain ranges in the Sahara, and hilly desert terrain.\\nThe cheetah lives in three main social groups: females and their cubs, male \"coalitions\", and solitary males. While females lead a nomadic life searching for prey in large home ranges, males are more sedentary and instead establish much smaller territories in areas with plentiful prey and access to females. The cheetah is active during the day, with peaks during dawn and dusk. It feeds on small- to medium-sized prey, mostly weighing under 40 kg (88 lb), and prefers medium-sized ungulates such as impala, springbok and Thomson\\'s gazelles. The cheetah typically stalks its prey within 60–100 m (200–330 ft) before charging towards it, trips it during the chase and bites its throat to suffocate it to death. It breeds throughout the year. After a gestation of nearly three months, females give birth to a litter of three or four cubs. Cheetah cubs are highly vulnerable to predation by other large carnivores. They are weaned a' metadata={'title': 'Cheetah', 'summary': 'The cheetah (Acinonyx jubatus) is a large cat and the fastest land animal. It has a tawny to creamy white or pale buff fur that is marked with evenly spaced, solid black spots. The head is small and rounded, with a short snout and black tear-like facial streaks. It reaches 67–94 cm (26–37 in) at the shoulder, and the head-and-body length is between 1.1 and 1.5 m (3 ft 7 in and 4 ft 11 in). Adults weigh between 21 and 72 kg (46 and 159 lb). The cheetah is capable of running at 93 to 104 km/h (58 to 65 mph); it has evolved specialized adaptations for speed, including a light build, long thin legs and a long tail.\\nThe cheetah was first described in the late 18th century. Four subspecies are recognised today that are native to Africa and central Iran. An African subspecies was introduced to India in 2022. It is now distributed mainly in small, fragmented populations in northwestern, eastern and southern Africa and central Iran. It lives in a variety of habitats such as savannahs in the Serengeti, arid mountain ranges in the Sahara, and hilly desert terrain.\\nThe cheetah lives in three main social groups: females and their cubs, male \"coalitions\", and solitary males. While females lead a nomadic life searching for prey in large home ranges, males are more sedentary and instead establish much smaller territories in areas with plentiful prey and access to females. The cheetah is active during the day, with peaks during dawn and dusk. It feeds on small- to medium-sized prey, mostly weighing under 40 kg (88 lb), and prefers medium-sized ungulates such as impala, springbok and Thomson\\'s gazelles. The cheetah typically stalks its prey within 60–100 m (200–330 ft) before charging towards it, trips it during the chase and bites its throat to suffocate it to death. It breeds throughout the year. After a gestation of nearly three months, females give birth to a litter of three or four cubs. Cheetah cubs are highly vulnerable to predation by other large carnivores. They are weaned at around four months and are independent by around 20 months of age.\\nThe cheetah is threatened by habitat loss, conflict with humans, poaching and high susceptibility to diseases. In 2016, the global cheetah population was estimated at 7,100 individuals in the wild; it is listed as Vulnerable on the IUCN Red List. It has been widely depicted in art, literature, advertising, and animation. It was tamed in ancient Egypt and trained for hunting ungulates in the Arabian Peninsula and India. It has been kept in zoos since the early 19th century.', 'source': 'https://en.wikipedia.org/wiki/Cheetah'}\n" - ] + "data": { + "image/png": "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", + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" } ], "source": [ - "print(result[\"context\"][0])" + "from IPython.display import Image, display\n", + "\n", + "display(Image(graph.get_graph().draw_mermaid_png()))" ] }, { "cell_type": "code", - "execution_count": 8, - "id": "31f20897-0a7a-44e8-aeac-75d54f6e3789", + "execution_count": 10, + "id": "aef87758-c785-4484-ba59-9a784e5e1252", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "Cheetahs are capable of running at speeds of 93 to 104 km/h (58 to 65 mph). They have evolved specialized adaptations for speed, including a light build, long thin legs, and a long tail.\n" + "Sources: ['https://en.wikipedia.org/wiki/Cheetah', 'https://en.wikipedia.org/wiki/Southeast_African_cheetah', 'https://en.wikipedia.org/wiki/Footspeed', 'https://en.wikipedia.org/wiki/Fastest_animals', 'https://en.wikipedia.org/wiki/Pursuit_predation', 'https://en.wikipedia.org/wiki/Gepard-class_fast_attack_craft']\n", + "\n", + "\n", + "Answer: Cheetahs are capable of running at speeds between 93 to 104 km/h (58 to 65 mph).\n" ] } ], "source": [ - "print(result[\"answer\"])" + "result = graph.invoke({\"question\": \"How fast are cheetahs?\"})\n", + "\n", + "sources = [doc.metadata[\"source\"] for doc in result[\"context\"]]\n", + "print(f\"Sources: {sources}\\n\\n\")\n", + "print(f'Answer: {result[\"answer\"]}')" ] }, { "cell_type": "markdown", - "id": "0f1f9a49-8f3f-44dd-98df-0218b5fb93a6", + "id": "b64cdff1-724e-460e-9795-23fb666002c6", "metadata": {}, "source": [ - "LangSmith trace: https://smith.langchain.com/public/0472c5d1-49dc-4c1c-8100-61910067d7ed/r" + "Check out the [LangSmith trace](https://smith.langchain.com/public/ed043789-8599-44de-b88e-ba463ea454a3/r)." ] }, { "cell_type": "markdown", - "id": "a7619ba1-33bd-48bf-8637-be409c94037f", + "id": "765ecc32-accc-4dcc-89b6-f5bfca633efb", "metadata": {}, "source": [ - "## Function-calling\n", + "## Tool-calling\n", "\n", - "If your LLM of choice implements a [tool-calling](/docs/concepts/tool_calling) feature, you can use it to make the model specify which of the provided documents it's referencing when generating its answer. LangChain tool-calling models implement a `.with_structured_output` method which will force generation adhering to a desired schema (see for example [here](https://python.langchain.com/api_reference/openai/chat_models/langchain_openai.chat_models.base.ChatOpenAI.html#langchain_openai.chat_models.base.ChatOpenAI.with_structured_output)).\n", + "If your LLM of choice implements a [tool-calling](/docs/concepts/tool_calling) feature, you can use it to make the model specify which of the provided documents it's referencing when generating its answer. LangChain tool-calling models implement a `.with_structured_output` method which will force generation adhering to a desired schema (see details [here](/docs/how_to/structured_output/)).\n", "\n", "### Cite documents\n", "\n", @@ -265,8 +242,8 @@ }, { "cell_type": "code", - "execution_count": 9, - "id": "0af2c3a1-870c-428e-95da-0c2fd04d5616", + "execution_count": 11, + "id": "2088e137-2afe-45cc-a5dd-c54d63713c14", "metadata": {}, "outputs": [], "source": [ @@ -288,7 +265,7 @@ }, { "cell_type": "markdown", - "id": "68b95186-faf5-46f1-8715-ebbc38207d5d", + "id": "60c958e5-896b-4737-a5f8-353b6bdd907d", "metadata": {}, "source": [ "Let's see what the model output is like when we pass in our functions and a user input:" @@ -296,17 +273,17 @@ }, { "cell_type": "code", - "execution_count": 10, - "id": "2e2b7a87-3642-4ed8-9445-684daa93b0d7", + "execution_count": 12, + "id": "daad793f-f08d-4b56-90e8-3f015a79a88e", "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "CitedAnswer(answer='Brian\\'s height is 5\\'11\".', citations=[1, 3])" + "CitedAnswer(answer='Brian is 5\\'11\".', citations=[1, 3])" ] }, - "execution_count": 10, + "execution_count": 12, "metadata": {}, "output_type": "execute_result" } @@ -331,7 +308,7 @@ }, { "cell_type": "markdown", - "id": "7b847b53-987e-4d3a-9621-77e613d49cfd", + "id": "7085ffd9-15d6-4c14-a485-420a5952d335", "metadata": {}, "source": [ "Or as a dict:" @@ -339,17 +316,17 @@ }, { "cell_type": "code", - "execution_count": 11, - "id": "3ee49bbd-567f-41cc-8798-d5aad0fe1cea", + "execution_count": 13, + "id": "855b1d4d-5519-47a5-9cc3-4a6f8dafd451", "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "{'answer': 'Brian\\'s height is 5\\'11\".', 'citations': [1, 3]}" + "{'answer': 'Brian is 5\\'11\".', 'citations': [1, 3]}" ] }, - "execution_count": 11, + "execution_count": 13, "metadata": {}, "output_type": "execute_result" } @@ -360,20 +337,20 @@ }, { "cell_type": "markdown", - "id": "bb8bbbb5-2afc-401f-a140-648c3d2c4522", + "id": "f9c86861-4b66-478a-8451-47bbdcaa292e", "metadata": {}, "source": [ "Now we structure the source identifiers into the prompt to replicate with our chain. We will make three changes:\n", "\n", "1. Update the prompt to include source identifiers;\n", - "2. Use the `structured_llm` (i.e., `llm.with_structured_output(CitedAnswer));\n", - "3. Remove the `StrOutputParser`, to retain the Pydantic object in the output." + "2. Use the `structured_llm` (i.e., `llm.with_structured_output(CitedAnswer)`);\n", + "3. Return the Pydantic object in the output." ] }, { "cell_type": "code", - "execution_count": 12, - "id": "3cb835f3-3cf5-4144-bf6b-24558b9faf31", + "execution_count": 26, + "id": "e93107ec-33ec-4507-9c80-45a2b13f0d05", "metadata": {}, "outputs": [], "source": [ @@ -385,50 +362,55 @@ " return \"\\n\\n\" + \"\\n\\n\".join(formatted)\n", "\n", "\n", - "rag_chain_from_docs = (\n", - " RunnablePassthrough.assign(context=(lambda x: format_docs_with_id(x[\"context\"])))\n", - " | prompt\n", - " | structured_llm\n", - ")\n", + "class State(TypedDict):\n", + " question: str\n", + " context: List[Document]\n", + " # highlight-next-line\n", + " answer: CitedAnswer\n", "\n", - "retrieve_docs = (lambda x: x[\"input\"]) | retriever\n", "\n", - "chain = RunnablePassthrough.assign(context=retrieve_docs).assign(\n", - " answer=rag_chain_from_docs\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "id": "3e259b2f-5147-4c3c-9c26-b4eb8143e5f0", - "metadata": {}, - "outputs": [], - "source": [ - "result = chain.invoke({\"input\": \"How fast are cheetahs?\"})" + "def generate(state: State):\n", + " # highlight-next-line\n", + " formatted_docs = format_docs_with_id(state[\"context\"])\n", + " messages = prompt.invoke({\"question\": state[\"question\"], \"context\": formatted_docs})\n", + " # highlight-start\n", + " structured_llm = llm.with_structured_output(CitedAnswer)\n", + " response = structured_llm.invoke(messages)\n", + " # highlight-end\n", + " return {\"answer\": response}\n", + "\n", + "\n", + "graph_builder = StateGraph(State).add_sequence([retrieve, generate])\n", + "graph_builder.add_edge(START, \"retrieve\")\n", + "graph = graph_builder.compile()" ] }, { "cell_type": "code", - "execution_count": 14, - "id": "2d8d2a01-608d-479f-85f1-eb8d14b11bc2", + "execution_count": 27, + "id": "182362b0-075a-4d45-ad05-c4f39d410624", "metadata": {}, "outputs": [ { - "name": "stdout", - "output_type": "stream", - "text": [ - "answer='Cheetahs can run at speeds of 93 to 104 km/h (58 to 65 mph). They are known as the fastest land animals.' citations=[0]\n" - ] + "data": { + "text/plain": [ + "CitedAnswer(answer='Cheetahs are capable of running at speeds between 93 to 104 km/h (58 to 65 mph).', citations=[0, 3])" + ] + }, + "execution_count": 27, + "metadata": {}, + "output_type": "execute_result" } ], "source": [ - "print(result[\"answer\"])" + "result = graph.invoke({\"question\": \"How fast are cheetahs?\"})\n", + "\n", + "result[\"answer\"]" ] }, { "cell_type": "markdown", - "id": "da8341f5-a48a-4c07-8445-a313e20c36a2", + "id": "c2b8258c-0c1e-41df-bfce-819bc1892382", "metadata": {}, "source": [ "We can inspect the document at index 0, which the model cited:" @@ -436,15 +418,17 @@ }, { "cell_type": "code", - "execution_count": 15, - "id": "02d19f2b-2e15-492f-b44b-577990d15a86", + "execution_count": 21, + "id": "8cc4254b-525b-4286-b119-87c8dbbbeb7c", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "page_content='The cheetah (Acinonyx jubatus) is a large cat and the fastest land animal. It has a tawny to creamy white or pale buff fur that is marked with evenly spaced, solid black spots. The head is small and rounded, with a short snout and black tear-like facial streaks. It reaches 67–94 cm (26–37 in) at the shoulder, and the head-and-body length is between 1.1 and 1.5 m (3 ft 7 in and 4 ft 11 in). Adults weigh between 21 and 72 kg (46 and 159 lb). The cheetah is capable of running at 93 to 104 km/h (58 to 65 mph); it has evolved specialized adaptations for speed, including a light build, long thin legs and a long tail.\\nThe cheetah was first described in the late 18th century. Four subspecies are recognised today that are native to Africa and central Iran. An African subspecies was introduced to India in 2022. It is now distributed mainly in small, fragmented populations in northwestern, eastern and southern Africa and central Iran. It lives in a variety of habitats such as savannahs in the Serengeti, arid mountain ranges in the Sahara, and hilly desert terrain.\\nThe cheetah lives in three main social groups: females and their cubs, male \"coalitions\", and solitary males. While females lead a nomadic life searching for prey in large home ranges, males are more sedentary and instead establish much smaller territories in areas with plentiful prey and access to females. The cheetah is active during the day, with peaks during dawn and dusk. It feeds on small- to medium-sized prey, mostly weighing under 40 kg (88 lb), and prefers medium-sized ungulates such as impala, springbok and Thomson\\'s gazelles. The cheetah typically stalks its prey within 60–100 m (200–330 ft) before charging towards it, trips it during the chase and bites its throat to suffocate it to death. It breeds throughout the year. After a gestation of nearly three months, females give birth to a litter of three or four cubs. Cheetah cubs are highly vulnerable to predation by other large carnivores. They are weaned a' metadata={'title': 'Cheetah', 'summary': 'The cheetah (Acinonyx jubatus) is a large cat and the fastest land animal. It has a tawny to creamy white or pale buff fur that is marked with evenly spaced, solid black spots. The head is small and rounded, with a short snout and black tear-like facial streaks. It reaches 67–94 cm (26–37 in) at the shoulder, and the head-and-body length is between 1.1 and 1.5 m (3 ft 7 in and 4 ft 11 in). Adults weigh between 21 and 72 kg (46 and 159 lb). The cheetah is capable of running at 93 to 104 km/h (58 to 65 mph); it has evolved specialized adaptations for speed, including a light build, long thin legs and a long tail.\\nThe cheetah was first described in the late 18th century. Four subspecies are recognised today that are native to Africa and central Iran. An African subspecies was introduced to India in 2022. It is now distributed mainly in small, fragmented populations in northwestern, eastern and southern Africa and central Iran. It lives in a variety of habitats such as savannahs in the Serengeti, arid mountain ranges in the Sahara, and hilly desert terrain.\\nThe cheetah lives in three main social groups: females and their cubs, male \"coalitions\", and solitary males. While females lead a nomadic life searching for prey in large home ranges, males are more sedentary and instead establish much smaller territories in areas with plentiful prey and access to females. The cheetah is active during the day, with peaks during dawn and dusk. It feeds on small- to medium-sized prey, mostly weighing under 40 kg (88 lb), and prefers medium-sized ungulates such as impala, springbok and Thomson\\'s gazelles. The cheetah typically stalks its prey within 60–100 m (200–330 ft) before charging towards it, trips it during the chase and bites its throat to suffocate it to death. It breeds throughout the year. After a gestation of nearly three months, females give birth to a litter of three or four cubs. Cheetah cubs are highly vulnerable to predation by other large carnivores. They are weaned at around four months and are independent by around 20 months of age.\\nThe cheetah is threatened by habitat loss, conflict with humans, poaching and high susceptibility to diseases. In 2016, the global cheetah population was estimated at 7,100 individuals in the wild; it is listed as Vulnerable on the IUCN Red List. It has been widely depicted in art, literature, advertising, and animation. It was tamed in ancient Egypt and trained for hunting ungulates in the Arabian Peninsula and India. It has been kept in zoos since the early 19th century.', 'source': 'https://en.wikipedia.org/wiki/Cheetah'}\n" + "page_content='The cheetah (Acinonyx jubatus) is a large cat and the fastest land animal. It has a tawny to creamy white or pale buff fur that is marked with evenly spaced, solid black spots. The head is small and rounded, with a short snout and black tear-like facial streaks. It reaches 67–94 cm (26–37 in) at the shoulder, and the head-and-body length is between 1.1 and 1.5 m (3 ft 7 in and 4 ft 11 in). Adults weigh between 21 and 72 kg (46 and 159 lb). The cheetah is capable of running at 93 to 104 km/h (58 to 65 mph); it has evolved specialized adaptations for speed, including a light build, long thin legs and a long tail.\n", + "The cheetah was first described in the late 18th century. Four subspecies are recognised today that are native to Africa and central Iran. An African subspecies was introduced to India in 2022. It is now distributed mainly in small, fragmented populations in northwestern, eastern and southern Africa and central Iran. It lives in a variety of habitats such as savannahs in the Serengeti, arid mountain ranges in the Sahara, and hilly desert terrain.\n", + "The cheetah lives in three main social groups: females and their cubs, male \"coalitions\", and solitary males. While females lead a nomadic life searching for prey in large home ranges, males are more sedentary and instead establish much smaller territories in areas with plentiful prey and access to females. The cheetah is active during the day, with peaks during dawn and dusk. It feeds on small- to medium-sized prey, mostly weighing under 40 kg (88 lb), and prefers medium-sized ungulates such as impala, springbok and Thomson's gazelles. The cheetah typically stalks its prey within 60–100 m (200–330 ft) before charging towards it, trips it during the chase and bites its throat to suffocate it to death. It breeds throughout the year. After a gestation of nearly three months, females give birth to a litter of three or four cubs. Cheetah cubs are highly vulnerable to predation by other large carnivores. They are weaned a' metadata={'title': 'Cheetah', 'summary': 'The cheetah (Acinonyx jubatus) is a large cat and the fastest land animal. It has a tawny to creamy white or pale buff fur that is marked with evenly spaced, solid black spots. The head is small and rounded, with a short snout and black tear-like facial streaks. It reaches 67–94 cm (26–37 in) at the shoulder, and the head-and-body length is between 1.1 and 1.5 m (3 ft 7 in and 4 ft 11 in). Adults weigh between 21 and 72 kg (46 and 159 lb). The cheetah is capable of running at 93 to 104 km/h (58 to 65 mph); it has evolved specialized adaptations for speed, including a light build, long thin legs and a long tail.\\nThe cheetah was first described in the late 18th century. Four subspecies are recognised today that are native to Africa and central Iran. An African subspecies was introduced to India in 2022. It is now distributed mainly in small, fragmented populations in northwestern, eastern and southern Africa and central Iran. It lives in a variety of habitats such as savannahs in the Serengeti, arid mountain ranges in the Sahara, and hilly desert terrain.\\nThe cheetah lives in three main social groups: females and their cubs, male \"coalitions\", and solitary males. While females lead a nomadic life searching for prey in large home ranges, males are more sedentary and instead establish much smaller territories in areas with plentiful prey and access to females. The cheetah is active during the day, with peaks during dawn and dusk. It feeds on small- to medium-sized prey, mostly weighing under 40 kg (88 lb), and prefers medium-sized ungulates such as impala, springbok and Thomson\\'s gazelles. The cheetah typically stalks its prey within 60–100 m (200–330 ft) before charging towards it, trips it during the chase and bites its throat to suffocate it to death. It breeds throughout the year. After a gestation of nearly three months, females give birth to a litter of three or four cubs. Cheetah cubs are highly vulnerable to predation by other large carnivores. They are weaned at around four months and are independent by around 20 months of age.\\nThe cheetah is threatened by habitat loss, conflict with humans, poaching and high susceptibility to diseases. The global cheetah population was estimated in 2021 at 6,517; it is listed as Vulnerable on the IUCN Red List. It has been widely depicted in art, literature, advertising, and animation. It was tamed in ancient Egypt and trained for hunting ungulates in the Arabian Peninsula and India. It has been kept in zoos since the early 19th century.', 'source': 'https://en.wikipedia.org/wiki/Cheetah'}\n" ] } ], @@ -454,15 +438,15 @@ }, { "cell_type": "markdown", - "id": "94f2898a-ef4d-423a-b002-910fef7a65c9", + "id": "5f5c8187-93ba-40a8-a006-2f17491cd48d", "metadata": {}, "source": [ - "LangSmith trace: https://smith.langchain.com/public/aff39dc7-3e09-4d64-8083-87026d975534/r" + "LangSmith trace: https://smith.langchain.com/public/6f34d136-451d-4625-90c8-2d8decebc21a/r" ] }, { "cell_type": "markdown", - "id": "fdbd1407-8a5b-4c35-aa2b-9d26424edb93", + "id": "8b965cbc-f5a4-465a-9220-c30dbd437c34", "metadata": {}, "source": [ "### Cite snippets\n", @@ -474,8 +458,8 @@ }, { "cell_type": "code", - "execution_count": 16, - "id": "fbf708aa-e8ac-4dea-bb57-82229597e2e0", + "execution_count": 28, + "id": "89794b32-f84d-46fb-9a8c-9a6df908b383", "metadata": {}, "outputs": [], "source": [ @@ -504,37 +488,35 @@ }, { "cell_type": "code", - "execution_count": 17, - "id": "beabab7b-7b6b-4eef-b874-e92d1ed8707c", + "execution_count": 32, + "id": "5adb77c4-e185-4ed3-8be0-d380ad50f649", "metadata": {}, "outputs": [], "source": [ - "rag_chain_from_docs = (\n", - " RunnablePassthrough.assign(context=(lambda x: format_docs_with_id(x[\"context\"])))\n", - " | prompt\n", - " | llm.with_structured_output(QuotedAnswer)\n", - ")\n", + "class State(TypedDict):\n", + " question: str\n", + " context: List[Document]\n", + " # highlight-next-line\n", + " answer: QuotedAnswer\n", "\n", - "retrieve_docs = (lambda x: x[\"input\"]) | retriever\n", "\n", - "chain = RunnablePassthrough.assign(context=retrieve_docs).assign(\n", - " answer=rag_chain_from_docs\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": 18, - "id": "9709ee6d-416f-4bd3-89c6-23667b9f3cca", - "metadata": {}, - "outputs": [], - "source": [ - "result = chain.invoke({\"input\": \"How fast are cheetahs?\"})" + "def generate(state: State):\n", + " formatted_docs = format_docs_with_id(state[\"context\"])\n", + " messages = prompt.invoke({\"question\": state[\"question\"], \"context\": formatted_docs})\n", + " # highlight-next-line\n", + " structured_llm = llm.with_structured_output(QuotedAnswer)\n", + " response = structured_llm.invoke(messages)\n", + " return {\"answer\": response}\n", + "\n", + "\n", + "graph_builder = StateGraph(State).add_sequence([retrieve, generate])\n", + "graph_builder.add_edge(START, \"retrieve\")\n", + "graph = graph_builder.compile()" ] }, { "cell_type": "markdown", - "id": "b42ba8c6-4214-49f5-b920-f0e028f301c2", + "id": "0f23cbe0-3d71-4f9b-903d-07801682f05a", "metadata": {}, "source": [ "Here we see that the model has extracted a relevant snippet of text from source 0:" @@ -542,47 +524,49 @@ }, { "cell_type": "code", - "execution_count": 19, - "id": "56b01963-8680-4782-9c3f-384c197f0c2d", + "execution_count": 33, + "id": "3376deae-9fea-4aaa-861a-d37d9121926c", "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "QuotedAnswer(answer='Cheetahs can run at speeds of 93 to 104 km/h (58 to 65 mph).', citations=[Citation(source_id=0, quote='The cheetah is capable of running at 93 to 104 km/h (58 to 65 mph); it has evolved specialized adaptations for speed, including a light build, long thin legs and a long tail.')])" + "QuotedAnswer(answer='Cheetahs are capable of running at speeds of 93 to 104 km/h (58 to 65 mph).', citations=[Citation(source_id=0, quote='The cheetah is capable of running at 93 to 104 km/h (58 to 65 mph); it has evolved specialized adaptations for speed.')])" ] }, - "execution_count": 19, + "execution_count": 33, "metadata": {}, "output_type": "execute_result" } ], "source": [ + "result = graph.invoke({\"question\": \"How fast are cheetahs?\"})\n", + "\n", "result[\"answer\"]" ] }, { "cell_type": "markdown", - "id": "28676cf1-4a2e-44d2-8b2f-36303a12a371", + "id": "740eff91-9ccd-44c3-a707-978a560f412a", "metadata": {}, "source": [ - "LangSmith trace: https://smith.langchain.com/public/0f638cc9-8409-4a53-9010-86ac28144129/r" + "LangSmith trace: https://smith.langchain.com/public/e16dc72f-4261-4f25-a9a7-906238737283/r" ] }, { "cell_type": "markdown", - "id": "fb2d90a4-0370-4598-9f4b-e8e9a554346e", + "id": "ab0e894f-5c85-4120-995c-8348c129d736", "metadata": {}, "source": [ "## Direct prompting\n", "\n", - "Many models don't support function-calling. We can achieve similar results with direct prompting. Let's try instructing a model to generate structured XML for its output:" + "Some models don't support function-calling. We can achieve similar results with direct prompting. Let's try instructing a model to generate structured XML for its output:" ] }, { "cell_type": "code", - "execution_count": 20, - "id": "4e95bd8a-2f15-4e20-a1d9-225974b8d598", + "execution_count": 38, + "id": "2ec10eb1-da72-4393-b639-489c0a4f3d4d", "metadata": {}, "outputs": [], "source": [ @@ -604,26 +588,26 @@ "\n", "Here are the Wikipedia articles:{context}\"\"\"\n", "xml_prompt = ChatPromptTemplate.from_messages(\n", - " [(\"system\", xml_system), (\"human\", \"{input}\")]\n", + " [(\"system\", xml_system), (\"human\", \"{question}\")]\n", ")" ] }, { "cell_type": "markdown", - "id": "2d3bd0f7-e249-4bc6-bd46-6fb74ebf0118", + "id": "74cae200-0a88-4264-a5ad-a115b4a7d35c", "metadata": {}, "source": [ "We now make similar small updates to our chain:\n", "\n", "1. We update the formatting function to wrap the retrieved context in XML tags;\n", "2. We do not use `.with_structured_output` (e.g., because it does not exist for a model);\n", - "3. We use [XMLOutputParser](https://python.langchain.com/api_reference/core/output_parsers/langchain_core.output_parsers.xml.XMLOutputParser.html) in place of `StrOutputParser` to parse the answer into a dict." + "3. We use [XMLOutputParser](https://python.langchain.com/api_reference/core/output_parsers/langchain_core.output_parsers.xml.XMLOutputParser.html) to parse the answer into a dict." ] }, { "cell_type": "code", - "execution_count": 21, - "id": "5861ca8c-63b7-4918-bdc6-fe4e53fe03ca", + "execution_count": 41, + "id": "1426de65-f247-455d-bf15-b58e08e0189d", "metadata": {}, "outputs": [], "source": [ @@ -642,33 +626,33 @@ " return \"\\n\\n\" + \"\\n\".join(formatted) + \"\"\n", "\n", "\n", - "rag_chain_from_docs = (\n", - " RunnablePassthrough.assign(context=(lambda x: format_docs_xml(x[\"context\"])))\n", - " | xml_prompt\n", - " | llm\n", - " | XMLOutputParser()\n", - ")\n", + "class State(TypedDict):\n", + " question: str\n", + " context: List[Document]\n", + " # highlight-next-line\n", + " answer: dict\n", "\n", - "retrieve_docs = (lambda x: x[\"input\"]) | retriever\n", "\n", - "chain = RunnablePassthrough.assign(context=retrieve_docs).assign(\n", - " answer=rag_chain_from_docs\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": 22, - "id": "f1edb401-6027-4112-82ec-25736e8ebabd", - "metadata": {}, - "outputs": [], - "source": [ - "result = chain.invoke({\"input\": \"How fast are cheetahs?\"})" + "def generate(state: State):\n", + " # highlight-start\n", + " formatted_docs = format_docs_xml(state[\"context\"])\n", + " messages = xml_prompt.invoke(\n", + " {\"question\": state[\"question\"], \"context\": formatted_docs}\n", + " )\n", + " response = llm.invoke(messages)\n", + " parsed_response = XMLOutputParser().invoke(response)\n", + " # highlight-end\n", + " return {\"answer\": parsed_response}\n", + "\n", + "\n", + "graph_builder = StateGraph(State).add_sequence([retrieve, generate])\n", + "graph_builder.add_edge(START, \"retrieve\")\n", + "graph = graph_builder.compile()" ] }, { "cell_type": "markdown", - "id": "e5264571-48c2-492d-a750-640f9fff3e71", + "id": "54b74634-a90f-4b96-90fb-2b1bdd3e24eb", "metadata": {}, "source": [ "Note that citations are again structured into the answer:" @@ -676,51 +660,125 @@ }, { "cell_type": "code", - "execution_count": 23, - "id": "a2b4bdc9-92dd-434c-b61c-11ec44c92905", + "execution_count": 42, + "id": "56f4b74f-36b6-4df5-ac95-f9e856401251", "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "{'cited_answer': [{'answer': 'Cheetahs are capable of running at 93 to 104 km/h (58 to 65 mph).'},\n", + "{'cited_answer': [{'answer': 'Cheetahs can run at speeds of 93 to 104 km/h (58 to 65 mph).'},\n", " {'citations': [{'citation': [{'source_id': '0'},\n", - " {'quote': 'The cheetah is capable of running at 93 to 104 km/h (58 to 65 mph); it has evolved specialized adaptations for speed, including a light build, long thin legs and a long tail.'}]}]}]}" + " {'quote': 'The cheetah is capable of running at 93 to 104 km/h (58 to 65 mph);'}]},\n", + " {'citation': [{'source_id': '3'},\n", + " {'quote': 'The fastest land animal is the cheetah.'}]}]}]}" ] }, - "execution_count": 23, + "execution_count": 42, "metadata": {}, "output_type": "execute_result" } ], "source": [ + "result = graph.invoke({\"question\": \"How fast are cheetahs?\"})\n", + "\n", "result[\"answer\"]" ] }, { "cell_type": "markdown", - "id": "940db8d5-8f43-44dd-9738-04fc7464baac", + "id": "0285feff-1d57-4aea-bd41-390224cd02e3", "metadata": {}, "source": [ - "LangSmith trace: https://smith.langchain.com/public/a3636c70-39c6-4c8f-bc83-1c7a174c237e/r" + "LangSmith trace: https://smith.langchain.com/public/0c45f847-c640-4b9a-a5fa-63559e413527/r" ] }, { "cell_type": "markdown", - "id": "9d4180b0-5d29-4bfa-85be-2a6161a872c4", + "id": "ab06819d-09fa-4f5c-8838-c22f5e32af17", "metadata": {}, "source": [ "## Retrieval post-processing\n", "\n", - "Another approach is to post-process our retrieved documents to compress the content, so that the source content is already minimal enough that we don't need the model to cite specific sources or spans. For example, we could break up each document into a sentence or two, embed those and keep only the most relevant ones. LangChain has some built-in components for this. Here we'll use a [RecursiveCharacterTextSplitter](https://python.langchain.com/api_reference/text_splitters/text_splitter/langchain_text_splitters.RecursiveCharacterTextSplitter.html#langchain_text_splitters.RecursiveCharacterTextSplitter), which creates chunks of a sepacified size by splitting on separator substrings, and an [EmbeddingsFilter](https://python.langchain.com/api_reference/langchain/retrievers/langchain.retrievers.document_compressors.embeddings_filter.EmbeddingsFilter.html#langchain.retrievers.document_compressors.embeddings_filter.EmbeddingsFilter), which keeps only the texts with the most relevant embeddings.\n", + "Another approach is to post-process our retrieved documents to compress the content, so that the source content is already minimal enough that we don't need the model to cite specific sources or spans. For example, we could break up each document into a sentence or two, embed those and keep only the most relevant ones. LangChain has some built-in components for this. Here we'll use a [RecursiveCharacterTextSplitter](https://python.langchain.com/api_reference/text_splitters/text_splitter/langchain_text_splitters.RecursiveCharacterTextSplitter.html#langchain_text_splitters.RecursiveCharacterTextSplitter), which creates chunks of a specified size by splitting on separator substrings, and an [EmbeddingsFilter](https://python.langchain.com/api_reference/langchain/retrievers/langchain.retrievers.document_compressors.embeddings_filter.EmbeddingsFilter.html#langchain.retrievers.document_compressors.embeddings_filter.EmbeddingsFilter), which keeps only the texts with the most relevant embeddings.\n", + "\n", + "This approach effectively updates our `retrieve` step to compress the documents. Let's first select an [embedding model](/docs/integrations/text_embedding/):\n", + "\n", + "import EmbeddingTabs from \"@theme/EmbeddingTabs\";\n", + "\n", + "" + ] + }, + { + "cell_type": "code", + "execution_count": 43, + "id": "d2814d13-49c1-4368-b6b7-d61865ba0849", + "metadata": {}, + "outputs": [], + "source": [ + "# | output: false\n", + "# | echo: false\n", + "\n", + "from langchain_openai import OpenAIEmbeddings\n", "\n", - "This approach effectively swaps our original retriever with an updated one that compresses the documents. To start, we build the retriever:" + "embeddings = OpenAIEmbeddings()" + ] + }, + { + "cell_type": "markdown", + "id": "db6d8f11-9a6d-446e-b311-1e3ca8c85371", + "metadata": {}, + "source": [ + "We can now rewrite the `retrieve` step:" ] }, { "cell_type": "code", - "execution_count": 24, - "id": "9b14f817-4454-47b2-9eb0-2b8783a8c252", + "execution_count": 44, + "id": "932e6e39-ca75-4763-9b0c-fa6bb7351414", + "metadata": {}, + "outputs": [], + "source": [ + "from langchain.retrievers.document_compressors import EmbeddingsFilter\n", + "from langchain_core.runnables import RunnableParallel\n", + "from langchain_text_splitters import RecursiveCharacterTextSplitter\n", + "\n", + "splitter = RecursiveCharacterTextSplitter(\n", + " chunk_size=400,\n", + " chunk_overlap=0,\n", + " separators=[\"\\n\\n\", \"\\n\", \".\", \" \"],\n", + " keep_separator=False,\n", + ")\n", + "compressor = EmbeddingsFilter(embeddings=embeddings, k=10)\n", + "\n", + "\n", + "class State(TypedDict):\n", + " question: str\n", + " context: List[Document]\n", + " answer: str\n", + "\n", + "\n", + "def retrieve(state: State):\n", + " retrieved_docs = retriever.invoke(state[\"question\"])\n", + " # highlight-start\n", + " split_docs = splitter.split_documents(retrieved_docs)\n", + " stateful_docs = compressor.compress_documents(split_docs, state[\"question\"])\n", + " # highlight-end\n", + " return {\"context\": stateful_docs}" + ] + }, + { + "cell_type": "markdown", + "id": "73ee7ba2-20e0-4099-a6fd-d02fa77ac58a", + "metadata": {}, + "source": [ + "Let's test this out:" + ] + }, + { + "cell_type": "code", + "execution_count": 60, + "id": "315df7b2-bf7e-4d1c-9363-be753a6d590f", "metadata": {}, "outputs": [ { @@ -730,82 +788,47 @@ "Adults weigh between 21 and 72 kg (46 and 159 lb). The cheetah is capable of running at 93 to 104 km/h (58 to 65 mph); it has evolved specialized adaptations for speed, including a light build, long thin legs and a long tail\n", "\n", "\n", - "\n", "The cheetah (Acinonyx jubatus) is a large cat and the fastest land animal. It has a tawny to creamy white or pale buff fur that is marked with evenly spaced, solid black spots. The head is small and rounded, with a short snout and black tear-like facial streaks. It reaches 67–94 cm (26–37 in) at the shoulder, and the head-and-body length is between 1.1 and 1.5 m (3 ft 7 in and 4 ft 11 in)\n", "\n", "\n", - "\n", - "2 mph), or 171 body lengths per second. The cheetah, the fastest land mammal, scores at only 16 body lengths per second, while Anna's hummingbird has the highest known length-specific velocity attained by any vertebrate\n", - "\n", + "2 mph), or 171 body lengths per second. The cheetah, the fastest land mammal, scores at only 16 body lengths per second\n", "\n", "\n", "It feeds on small- to medium-sized prey, mostly weighing under 40 kg (88 lb), and prefers medium-sized ungulates such as impala, springbok and Thomson's gazelles. The cheetah typically stalks its prey within 60–100 m (200–330 ft) before charging towards it, trips it during the chase and bites its throat to suffocate it to death. It breeds throughout the year\n", "\n", "\n", - "\n", "The cheetah was first described in the late 18th century. Four subspecies are recognised today that are native to Africa and central Iran. An African subspecies was introduced to India in 2022. It is now distributed mainly in small, fragmented populations in northwestern, eastern and southern Africa and central Iran\n", "\n", "\n", - "\n", "The cheetah lives in three main social groups: females and their cubs, male \"coalitions\", and solitary males. While females lead a nomadic life searching for prey in large home ranges, males are more sedentary and instead establish much smaller territories in areas with plentiful prey and access to females. The cheetah is active during the day, with peaks during dawn and dusk\n", "\n", "\n", - "\n", "The Southeast African cheetah (Acinonyx jubatus jubatus) is the nominate cheetah subspecies native to East and Southern Africa. The Southern African cheetah lives mainly in the lowland areas and deserts of the Kalahari, the savannahs of Okavango Delta, and the grasslands of the Transvaal region in South Africa. In Namibia, cheetahs are mostly found in farmlands\n", "\n", "\n", - "\n", "Subpopulations have been called \"South African cheetah\" and \"Namibian cheetah.\"\n", "\n", "\n", - "\n", "In India, four cheetahs of the subspecies are living in Kuno National Park in Madhya Pradesh after having been introduced there\n", "\n", "\n", - "\n", "Acinonyx jubatus velox proposed in 1913 by Edmund Heller on basis of a cheetah that was shot by Kermit Roosevelt in June 1909 in the Kenyan highlands.\n", "Acinonyx rex proposed in 1927 by Reginald Innes Pocock on basis of a specimen from the Umvukwe Range in Rhodesia.\n", "\n", - "\n", "\n" ] } ], "source": [ - "from langchain.retrievers.document_compressors import EmbeddingsFilter\n", - "from langchain_core.runnables import RunnableParallel\n", - "from langchain_openai import OpenAIEmbeddings\n", - "from langchain_text_splitters import RecursiveCharacterTextSplitter\n", + "retrieval_result = retrieve({\"question\": \"How fast are cheetahs?\"})\n", "\n", - "splitter = RecursiveCharacterTextSplitter(\n", - " chunk_size=400,\n", - " chunk_overlap=0,\n", - " separators=[\"\\n\\n\", \"\\n\", \".\", \" \"],\n", - " keep_separator=False,\n", - ")\n", - "compressor = EmbeddingsFilter(embeddings=OpenAIEmbeddings(), k=10)\n", - "\n", - "\n", - "def split_and_filter(input) -> List[Document]:\n", - " docs = input[\"docs\"]\n", - " question = input[\"question\"]\n", - " split_docs = splitter.split_documents(docs)\n", - " stateful_docs = compressor.compress_documents(split_docs, question)\n", - " return [stateful_doc for stateful_doc in stateful_docs]\n", - "\n", - "\n", - "new_retriever = (\n", - " RunnableParallel(question=RunnablePassthrough(), docs=retriever) | split_and_filter\n", - ")\n", - "docs = new_retriever.invoke(\"How fast are cheetahs?\")\n", - "for doc in docs:\n", - " print(doc.page_content)\n", - " print(\"\\n\\n\")" + "for doc in retrieval_result[\"context\"]:\n", + " print(f\"{doc.page_content}\\n\\n\")" ] }, { "cell_type": "markdown", - "id": "984bc1e1-76fb-4d84-baa9-5fa5abca9da4", + "id": "4095cb9a-71e6-4ffc-8ed4-1ec9c7bdb748", "metadata": {}, "source": [ "Next, we assemble it into our chain as before:" @@ -813,46 +836,47 @@ }, { "cell_type": "code", - "execution_count": 25, - "id": "fa2adb01-5d8f-484c-8216-bae35717db0d", + "execution_count": 63, + "id": "08088f0f-209c-48ce-9b94-23e1bd3d465b", "metadata": {}, "outputs": [], "source": [ - "rag_chain_from_docs = (\n", - " RunnablePassthrough.assign(context=(lambda x: format_docs(x[\"context\"])))\n", - " | prompt\n", - " | llm\n", - " | StrOutputParser()\n", - ")\n", + "# This step is unchanged from our original RAG implementation\n", + "def generate(state: State):\n", + " docs_content = \"\\n\\n\".join(doc.page_content for doc in state[\"context\"])\n", + " messages = prompt.invoke({\"question\": state[\"question\"], \"context\": docs_content})\n", + " response = llm.invoke(messages)\n", + " return {\"answer\": response.content}\n", "\n", - "chain = RunnablePassthrough.assign(\n", - " context=(lambda x: x[\"input\"]) | new_retriever\n", - ").assign(answer=rag_chain_from_docs)" + "\n", + "graph_builder = StateGraph(State).add_sequence([retrieve, generate])\n", + "graph_builder.add_edge(START, \"retrieve\")\n", + "graph = graph_builder.compile()" ] }, { "cell_type": "code", - "execution_count": 26, - "id": "1a5b72f8-135b-4604-8777-59f2ef682323", + "execution_count": 64, + "id": "2903c47d-aae1-4662-bc1e-ee73ff774e88", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "Cheetahs are capable of running at speeds between 93 to 104 km/h (58 to 65 mph), making them the fastest land animals.\n" + "Cheetahs are capable of running at speeds between 93 to 104 km/h (58 to 65 mph). They are known as the fastest land animals.\n" ] } ], "source": [ - "result = chain.invoke({\"input\": \"How fast are cheetahs?\"})\n", + "result = graph.invoke({\"question\": \"How fast are cheetahs?\"})\n", "\n", "print(result[\"answer\"])" ] }, { "cell_type": "markdown", - "id": "d9ac43ab-db4f-458a-9b5a-fd3e116229bd", + "id": "a86b6b89-dab3-4533-96e7-93c7f4a18346", "metadata": {}, "source": [ "Note that the document content is now compressed, although the document objects retain the original content in a \"summary\" key in their metadata. These summaries are not passed to the model; only the condensed content is." @@ -860,8 +884,8 @@ }, { "cell_type": "code", - "execution_count": 27, - "id": "80625506-8764-4adf-a467-33f465d0f51f", + "execution_count": 65, + "id": "9cd14ad3-de62-4092-9021-1af6dee8f263", "metadata": {}, "outputs": [ { @@ -870,7 +894,7 @@ "'Adults weigh between 21 and 72 kg (46 and 159 lb). The cheetah is capable of running at 93 to 104 km/h (58 to 65 mph); it has evolved specialized adaptations for speed, including a light build, long thin legs and a long tail'" ] }, - "execution_count": 27, + "execution_count": 65, "metadata": {}, "output_type": "execute_result" } @@ -881,31 +905,31 @@ }, { "cell_type": "code", - "execution_count": 28, - "id": "672c5691-5d54-4271-9d97-93571eebda91", + "execution_count": 66, + "id": "9067f521-4ac8-42eb-a730-2d335803c9b2", "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "'The cheetah (Acinonyx jubatus) is a large cat and the fastest land animal. It has a tawny to creamy white or pale buff fur that is marked with evenly spaced, solid black spots. The head is small and rounded, with a short snout and black tear-like facial streaks. It reaches 67–94 cm (26–37 in) at the shoulder, and the head-and-body length is between 1.1 and 1.5 m (3 ft 7 in and 4 ft 11 in). Adults weigh between 21 and 72 kg (46 and 159 lb). The cheetah is capable of running at 93 to 104 km/h (58 to 65 mph); it has evolved specialized adaptations for speed, including a light build, long thin legs and a long tail.\\nThe cheetah was first described in the late 18th century. Four subspecies are recognised today that are native to Africa and central Iran. An African subspecies was introduced to India in 2022. It is now distributed mainly in small, fragmented populations in northwestern, eastern and southern Africa and central Iran. It lives in a variety of habitats such as savannahs in the Serengeti, arid mountain ranges in the Sahara, and hilly desert terrain.\\nThe cheetah lives in three main social groups: females and their cubs, male \"coalitions\", and solitary males. While females lead a nomadic life searching for prey in large home ranges, males are more sedentary and instead establish much smaller territories in areas with plentiful prey and access to females. The cheetah is active during the day, with peaks during dawn and dusk. It feeds on small- to medium-sized prey, mostly weighing under 40 kg (88 lb), and prefers medium-sized ungulates such as impala, springbok and Thomson\\'s gazelles. The cheetah typically stalks its prey within 60–100 m (200–330 ft) before charging towards it, trips it during the chase and bites its throat to suffocate it to death. It breeds throughout the year. After a gestation of nearly three months, females give birth to a litter of three or four cubs. Cheetah cubs are highly vulnerable to predation by other large carnivores. They are weaned at around four months and are independent by around 20 months of age.\\nThe cheetah is threatened by habitat loss, conflict with humans, poaching and high susceptibility to diseases. In 2016, the global cheetah population was estimated at 7,100 individuals in the wild; it is listed as Vulnerable on the IUCN Red List. It has been widely depicted in art, literature, advertising, and animation. It was tamed in ancient Egypt and trained for hunting ungulates in the Arabian Peninsula and India. It has been kept in zoos since the early 19th century.'" + "'The cheetah (Acinonyx jubatus) is a large cat and the fastest land animal. It has a tawny to creamy white or pale buff fur that is marked with evenly spaced, solid black spots. The head is small and rounded, with a short snout and black tear-like facial streaks. It reaches 67–94 cm (26–37 in) at the shoulder, and the head-and-body length is between 1.1 and 1.5 m (3 ft 7 in and 4 ft 11 in). Adults weigh between 21 and 72 kg (46 and 159 lb). The cheetah is capable of running at 93 to 104 km/h (58 to 65 mph); it has evolved specialized adaptations for speed, including a light build, long thin legs and a long tail.\\nThe cheetah was first described in the late 18th century. Four subspecies are recognised today that are native to Africa and central Iran. An African subspecies was introduced to India in 2022. It is now distributed mainly in small, fragmented populations in northwestern, eastern and southern Africa and central Iran. It lives in a variety of habitats such as savannahs in the Serengeti, arid mountain ranges in the Sahara, and hilly desert terrain.\\nThe cheetah lives in three main social groups: females and their cubs, male \"coalitions\", and solitary males. While females lead a nomadic life searching for prey in large home ranges, males are more sedentary and instead establish much smaller territories in areas with plentiful prey and access to females. The cheetah is active during the day, with peaks during dawn and dusk. It feeds on small- to medium-sized prey, mostly weighing under 40 kg (88 lb), and prefers medium-sized ungulates such as impala, springbok and Thomson\\'s gazelles. The cheetah typically stalks its prey within 60–100 m (200–330 ft) before charging towards it, trips it during the chase and bites its throat to suffocate it to death. It breeds throughout the year. After a gestation of nearly three months, females give birth to a litter of three or four cubs. Cheetah cubs are highly vulnerable to predation by other large carnivores. They are weaned at around four months and are independent by around 20 months of age.\\nThe cheetah is threatened by habitat loss, conflict with humans, poaching and high susceptibility to diseases. The global cheetah population was estimated in 2021 at 6,517; it is listed as Vulnerable on the IUCN Red List. It has been widely depicted in art, literature, advertising, and animation. It was tamed in ancient Egypt and trained for hunting ungulates in the Arabian Peninsula and India. It has been kept in zoos since the early 19th century.'" ] }, - "execution_count": 28, + "execution_count": 66, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "result[\"context\"][0].metadata[\"summary\"] # original document" + "result[\"context\"][0].metadata[\"summary\"] # original document # original document" ] }, { "cell_type": "markdown", - "id": "88ab8fd6-f6b4-4ba5-b022-f10cca983490", + "id": "c4325c9c-c09a-42ed-98d8-9111d387d517", "metadata": {}, "source": [ - "LangSmith trace: https://smith.langchain.com/public/a61304fa-e5a5-4c64-a268-b0aef1130d53/r" + "LangSmith trace: https://smith.langchain.com/public/21b0dc15-d70a-4293-9402-9c70f9178e66/r" ] }, { @@ -917,13 +941,13 @@ "\n", "Another approach is to post-process our model generation. In this example we'll first generate just an answer, and then we'll ask the model to annotate it's own answer with citations. The downside of this approach is of course that it is slower and more expensive, because two model calls need to be made.\n", "\n", - "Let's apply this to our initial chain." + "Let's apply this to our initial chain. If desired, we can implement this via a third step in our application." ] }, { "cell_type": "code", - "execution_count": 29, - "id": "daff5cb9-7639-4d30-b6e7-d795736a2b58", + "execution_count": 67, + "id": "9b8f73b9-2365-40fb-90c5-458bc056c1d8", "metadata": {}, "outputs": [], "source": [ @@ -951,79 +975,106 @@ }, { "cell_type": "code", - "execution_count": 30, - "id": "6f505eb9-db02-4c49-add3-1e469844d7ca", + "execution_count": 80, + "id": "80344f87-0e51-4202-ab6a-35dc36548ecf", "metadata": {}, "outputs": [], "source": [ - "from langchain_core.prompts import MessagesPlaceholder\n", - "\n", - "prompt = ChatPromptTemplate.from_messages(\n", - " [\n", - " (\"system\", system_prompt),\n", - " (\"human\", \"{question}\"),\n", - " MessagesPlaceholder(\"chat_history\", optional=True),\n", + "class State(TypedDict):\n", + " question: str\n", + " context: List[Document]\n", + " answer: str\n", + " # highlight-next-line\n", + " annotations: AnnotatedAnswer\n", + "\n", + "\n", + "def retrieve(state: State):\n", + " retrieved_docs = retriever.invoke(state[\"question\"])\n", + " return {\"context\": retrieved_docs}\n", + "\n", + "\n", + "def generate(state: State):\n", + " docs_content = \"\\n\\n\".join(doc.page_content for doc in state[\"context\"])\n", + " messages = prompt.invoke({\"question\": state[\"question\"], \"context\": docs_content})\n", + " response = llm.invoke(messages)\n", + " return {\"answer\": response.content}\n", + "\n", + "\n", + "# highlight-start\n", + "def annotate(state: State):\n", + " formatted_docs = format_docs_with_id(state[\"context\"])\n", + " messages = [\n", + " (\"system\", system_prompt.format(context=formatted_docs)),\n", + " (\"human\", state[\"question\"]),\n", + " (\"ai\", state[\"answer\"]),\n", + " (\"human\", \"Annotate your answer with citations.\"),\n", " ]\n", - ")\n", - "answer = prompt | llm\n", - "annotation_chain = prompt | structured_llm\n", + " response = structured_llm.invoke(messages)\n", + " # highlight-end\n", + " # highlight-next-line\n", + " return {\"annotations\": response}\n", "\n", - "chain = (\n", - " RunnableParallel(\n", - " question=RunnablePassthrough(), docs=(lambda x: x[\"input\"]) | retriever\n", - " )\n", - " .assign(context=format)\n", - " .assign(ai_message=answer)\n", - " .assign(\n", - " chat_history=(lambda x: [x[\"ai_message\"]]),\n", - " answer=(lambda x: x[\"ai_message\"].content),\n", - " )\n", - " .assign(annotations=annotation_chain)\n", - " .pick([\"answer\", \"docs\", \"annotations\"])\n", - ")" + "\n", + "# highlight-next-line\n", + "graph_builder = StateGraph(State).add_sequence([retrieve, generate, annotate])\n", + "graph_builder.add_edge(START, \"retrieve\")\n", + "graph = graph_builder.compile()" ] }, { "cell_type": "code", - "execution_count": 31, - "id": "eb11c422-09b3-4d5a-87eb-3bad2e73cf6c", + "execution_count": 81, + "id": "688b43cc-2766-4216-a9b5-245c18eb5675", "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "image/png": "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", + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ - "result = chain.invoke({\"input\": \"How fast are cheetahs?\"})" + "display(Image(graph.get_graph().draw_mermaid_png()))" ] }, { "cell_type": "code", - "execution_count": 32, - "id": "5b8bbc02-f753-4abc-87ec-211aac3dc3d0", + "execution_count": 82, + "id": "a02d494e-2ba4-4626-b982-3fac8e65d0af", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "Cheetahs are capable of running at speeds between 93 to 104 km/h (58 to 65 mph). Their specialized adaptations for speed, such as a light build, long thin legs, and a long tail, allow them to be the fastest land animals.\n" + "Cheetahs are capable of running at speeds between 93 to 104 km/h (58 to 65 mph).\n" ] } ], "source": [ + "result = graph.invoke({\"question\": \"How fast are cheetahs?\"})\n", + "\n", "print(result[\"answer\"])" ] }, { "cell_type": "code", - "execution_count": 33, - "id": "c7882b76-db21-40ee-bb31-ff438880adf6", + "execution_count": 83, + "id": "a8a02c3f-12dd-4e79-adc9-87a31b210abd", "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "AnnotatedAnswer(citations=[Citation(source_id=0, quote='The cheetah is capable of running at 93 to 104 km/h (58 to 65 mph); it has evolved specialized adaptations for speed, including a light build, long thin legs and a long tail.')])" + "AnnotatedAnswer(citations=[Citation(source_id=0, quote='The cheetah is capable of running at 93 to 104 km/h (58 to 65 mph)')])" ] }, - "execution_count": 33, + "execution_count": 83, "metadata": {}, "output_type": "execute_result" } @@ -1034,11 +1085,19 @@ }, { "cell_type": "markdown", - "id": "803c6155-48af-40db-b4b0-1ecc5328e99b", + "id": "54e65f9b-5a80-46ad-91ac-3a946184fc8f", "metadata": {}, "source": [ - "LangSmith trace: https://smith.langchain.com/public/bf5e8856-193b-4ff2-af8d-c0f4fbd1d9cb/r" + "LangSmith trace: https://smith.langchain.com/public/b8257417-573b-47c4-a750-74e542035f19/r" ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b4eca9be-14ae-4e6c-9693-fea8bdbf7372", + "metadata": {}, + "outputs": [], + "source": [] } ], "metadata": {