mirror of
https://github.com/langchain-ai/langgraph.git
synced 2026-08-21 07:02:25 +02:00
625 lines
23 KiB
Plaintext
625 lines
23 KiB
Plaintext
{
|
|
"cells": [
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "54abe00a-0132-493a-bee0-5dcb3044c412",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"! pip install langchain_community tiktoken langchain-openai langchainhub chromadb langchain langgraph faiss-cpu"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "c02e806b-5169-4572-b007-3302df9801e0",
|
|
"metadata": {},
|
|
"source": [
|
|
"Optionally, use [LangSmith](https://docs.smith.langchain.com/) for tracing: \n",
|
|
"\n",
|
|
"```\n",
|
|
"export LANGCHAIN_TRACING_V2=true\n",
|
|
"export LANGCHAIN_ENDPOINT=https://api.smith.langchain.com\n",
|
|
"export LANGCHAIN_API_KEY=<your-api-key>\n",
|
|
"```"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "15bb14a1-4640-461d-9385-401ce346da75",
|
|
"metadata": {},
|
|
"source": [
|
|
"## Docs"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 14,
|
|
"id": "e471e650-97c2-4524-82c4-9bffaa8e6447",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"from bs4 import BeautifulSoup as Soup\n",
|
|
"from langchain_community.document_loaders.recursive_url_loader import RecursiveUrlLoader\n",
|
|
"\n",
|
|
"# LCEL docs \n",
|
|
"url = \"https://python.langchain.com/docs/expression_language/\"\n",
|
|
"loader = RecursiveUrlLoader(\n",
|
|
" url=url, max_depth=20, extractor=lambda x: Soup(x, \"html.parser\").text\n",
|
|
")\n",
|
|
"docs = loader.load()\n",
|
|
"\n",
|
|
"# Sort the list based on the URLs in 'metadata' -> 'source'\n",
|
|
"d_sorted = sorted(docs, key=lambda x: x.metadata[\"source\"])\n",
|
|
"d_reversed = list(reversed(d_sorted))\n",
|
|
"\n",
|
|
"# Concatenate the 'page_content' of each sorted dictionary\n",
|
|
"concatenated_content = \"\\n\\n\\n --- \\n\\n\\n\".join(\n",
|
|
" [doc.page_content for doc in d_reversed]\n",
|
|
")"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "5ccf1981-54b6-4667-b56e-a43dbfec35c7",
|
|
"metadata": {},
|
|
"source": [
|
|
"## Tool Use"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 17,
|
|
"id": "133889df-277a-4641-93cb-5dafa942b47a",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"from operator import itemgetter\n",
|
|
"from langchain_openai import ChatOpenAI\n",
|
|
"from langchain.prompts import PromptTemplate\n",
|
|
"from langchain_core.pydantic_v1 import BaseModel, Field\n",
|
|
"from langchain.output_parsers.openai_tools import PydanticToolsParser\n",
|
|
"from langchain_core.utils.function_calling import convert_to_openai_tool\n",
|
|
" \n",
|
|
"## Data model\n",
|
|
"class code(BaseModel):\n",
|
|
" \"\"\"Code output\"\"\"\n",
|
|
" prefix: str = Field(description=\"Description of the problem and approach\")\n",
|
|
" imports: str = Field(description=\"Code block import statements\")\n",
|
|
" code: str = Field(description=\"Code block not including import statements\")\n",
|
|
"\n",
|
|
"## LLM\n",
|
|
"model = ChatOpenAI(temperature=0, model=\"gpt-4-0125-preview\", streaming=True)\n",
|
|
"\n",
|
|
"# Tool\n",
|
|
"code_tool_oai = convert_to_openai_tool(code)\n",
|
|
"\n",
|
|
"# LLM with tool and enforce invocation\n",
|
|
"llm_with_tool = model.bind(\n",
|
|
" tools=[code_tool_oai],\n",
|
|
" tool_choice={\"type\": \"function\", \"function\": {\"name\": \"code\"}},\n",
|
|
")\n",
|
|
"\n",
|
|
"# Parser\n",
|
|
"parser_tool = PydanticToolsParser(tools=[code])\n",
|
|
"\n",
|
|
"## Prompt\n",
|
|
"template = \"\"\"You are a coding assistant with expertise in LCEL, LangChain expression language. \\n \n",
|
|
" Here is a full set of LCEL documentation: \n",
|
|
" \\n ------- \\n\n",
|
|
" {context} \n",
|
|
" \\n ------- \\n\n",
|
|
" Answer the user question based on the above provided documentation. \\n\n",
|
|
" Ensure any code you provide can be executed with all required imports and variables defined. \\n\n",
|
|
" Structure your answer with a description of the code solution. \\n\n",
|
|
" Then list the imports. And finally list the functioning code block. \\n\n",
|
|
" Here is the user question: \\n --- --- --- \\n {question}\"\"\"\n",
|
|
"\n",
|
|
"# Prompt \n",
|
|
"prompt = PromptTemplate(\n",
|
|
" template=template,\n",
|
|
" input_variables=[\"context\", \"question\"],\n",
|
|
")\n",
|
|
"\n",
|
|
"# Chain\n",
|
|
"chain = (\n",
|
|
" {\n",
|
|
" # \"context\": lambda x: docs,\n",
|
|
" \"context\": lambda x: concatenated_content,\n",
|
|
" \"question\": itemgetter(\"question\"),\n",
|
|
" }\n",
|
|
" | prompt\n",
|
|
" | llm_with_tool \n",
|
|
" | parser_tool\n",
|
|
")"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 19,
|
|
"id": "450cfac7-8a2a-43ed-a431-b38fb4d0de66",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"data": {
|
|
"text/plain": [
|
|
"[code(prefix=\"To create a Retrieval-Augmented Generation (RAG) chain in LangChain Expression Language (LCEL), you need to follow a structured approach. This involves setting up a retriever to fetch relevant documents based on the user's query, and then using those documents to generate a response with a language model. Here's a step-by-step guide to creating a RAG chain in LCEL:\\n\\n\", imports='from operator import itemgetter\\nfrom langchain_community.vectorstores import FAISS\\nfrom langchain_core.output_parsers import StrOutputParser\\nfrom langchain_core.prompts import ChatPromptTemplate\\nfrom langchain_core.runnables import RunnablePassthrough\\nfrom langchain_openai import ChatOpenAI, OpenAIEmbeddings', code='# Initialize the vector store with sample texts and embeddings\\nvectorstore = FAISS.from_texts(\\n [\"harrison worked at kensho\"], embedding=OpenAIEmbeddings())\\n\\n# Create a retriever from the vector store\\nretriever = vectorstore.as_retriever()\\n\\n# Define the prompt template\\ntemplate = \"\"\"Answer the question based only on the following context:{context}Question: {question}\"\"\"\\nprompt = ChatPromptTemplate.from_template(template)\\n\\n# Initialize the model\\nmodel = ChatOpenAI()\\n\\n# Create the RAG chain\\nchain = (\\n {\"context\": retriever, \"question\": RunnablePassthrough()} | prompt | model | StrOutputParser()\\n)\\n\\n# Invoke the chain with a query\\nresponse = chain.invoke(\"where did harrison work?\")\\nprint(response)')]"
|
|
]
|
|
},
|
|
"execution_count": 19,
|
|
"metadata": {},
|
|
"output_type": "execute_result"
|
|
}
|
|
],
|
|
"source": [
|
|
"chain.invoke({\"question\":\"How to create a RAG chain in LCEL?\"})"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "32a6686d-48d9-4b4c-becf-0d496384eed9",
|
|
"metadata": {},
|
|
"source": [
|
|
"## State"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 20,
|
|
"id": "95be35d1-b90c-4559-a6bf-2cd79e68ae4a",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"from typing import Dict, TypedDict\n",
|
|
"\n",
|
|
"from langchain_core.messages import BaseMessage\n",
|
|
"\n",
|
|
"\n",
|
|
"class GraphState(TypedDict):\n",
|
|
" \"\"\"\n",
|
|
" Represents the state of our graph.\n",
|
|
"\n",
|
|
" Attributes:\n",
|
|
" keys: A dictionary where each key is a string.\n",
|
|
" \"\"\"\n",
|
|
"\n",
|
|
" keys: Dict[str, any]"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 21,
|
|
"id": "396bee5b-9cc3-44d2-bc6a-955af0e0a847",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"from operator import itemgetter\n",
|
|
"from bs4 import BeautifulSoup as Soup\n",
|
|
"from langchain_community.document_loaders.recursive_url_loader import RecursiveUrlLoader\n",
|
|
"from langchain_openai import ChatOpenAI\n",
|
|
"from langchain.prompts import PromptTemplate\n",
|
|
"from langchain_core.output_parsers import StrOutputParser\n",
|
|
"from langchain_core.runnables import RunnablePassthrough\n",
|
|
"from langchain_core.pydantic_v1 import BaseModel, Field\n",
|
|
"from langchain.output_parsers import PydanticOutputParser\n",
|
|
"from langchain.output_parsers.openai_tools import PydanticToolsParser\n",
|
|
"from langchain_core.utils.function_calling import convert_to_openai_tool\n",
|
|
"\n",
|
|
"def generate(state):\n",
|
|
" \"\"\"\n",
|
|
" Generate a code solution based on LCEL docs and the input question \n",
|
|
" with optional feedback from code execution tests \n",
|
|
"\n",
|
|
" Args:\n",
|
|
" state (dict): The current graph state\n",
|
|
"\n",
|
|
" Returns:\n",
|
|
" state (dict): New key added to state, documents, that contains retrieved documents\n",
|
|
" \"\"\"\n",
|
|
" \n",
|
|
" ## State\n",
|
|
" state_dict = state[\"keys\"]\n",
|
|
" question = state_dict[\"question\"]\n",
|
|
" iter = state_dict[\"iterations\"]\n",
|
|
" \n",
|
|
" ## Data model\n",
|
|
" class code(BaseModel):\n",
|
|
" \"\"\"Code output\"\"\"\n",
|
|
" prefix: str = Field(description=\"Description of the problem and approach\")\n",
|
|
" imports: str = Field(description=\"Code block import statements\")\n",
|
|
" code: str = Field(description=\"Code block not including import statements\")\n",
|
|
" \n",
|
|
" ## LLM\n",
|
|
" model = ChatOpenAI(temperature=0, model=\"gpt-4-0125-preview\", streaming=True)\n",
|
|
" \n",
|
|
" # Tool\n",
|
|
" code_tool_oai = convert_to_openai_tool(code)\n",
|
|
" \n",
|
|
" # LLM with tool and enforce invocation\n",
|
|
" llm_with_tool = model.bind(\n",
|
|
" tools=[convert_to_openai_tool(code_tool_oai)],\n",
|
|
" tool_choice={\"type\": \"function\", \"function\": {\"name\": \"code\"}},\n",
|
|
" )\n",
|
|
" \n",
|
|
" # Parser\n",
|
|
" parser_tool = PydanticToolsParser(tools=[code])\n",
|
|
" \n",
|
|
" ## Prompt\n",
|
|
" template = \"\"\"You are a coding assistant with expertise in LCEL, LangChain expression language. \\n \n",
|
|
" Here is a full set of LCEL documentation: \n",
|
|
" \\n ------- \\n\n",
|
|
" {context} \n",
|
|
" \\n ------- \\n\n",
|
|
" Answer the user question based on the above provided documentation. \\n\n",
|
|
" Ensure any code you provide can be executed with all required imports and variables defined. \\n\n",
|
|
" Structure your answer with a description of the code solution. \\n\n",
|
|
" Then list the imports. And finally list the functioning code block. \\n\n",
|
|
" Here is the user question: \\n --- --- --- \\n {question}\"\"\"\n",
|
|
"\n",
|
|
" ## Generation\n",
|
|
" if \"error\" in state_dict:\n",
|
|
" print(\"---RE-GENERATE SOLUTION w/ ERROR FEEDBACK---\")\n",
|
|
" \n",
|
|
" error = state_dict[\"error\"]\n",
|
|
" code_solution = state_dict[\"generation\"]\n",
|
|
" \n",
|
|
" # Udpate prompt \n",
|
|
" addendum = \"\"\" \\n --- --- --- \\n You previously tried to solve this problem. \\n Here is your solution: \n",
|
|
" \\n --- --- --- \\n {generation} \\n --- --- --- \\n Here is the resulting error from code \n",
|
|
" execution: \\n --- --- --- \\n {error} \\n --- --- --- \\n Please re-try to answer this. \n",
|
|
" Structure your answer with a description of the code solution. \\n Then list the imports. \n",
|
|
" And finally list the functioning code block. Structure your answer with a description of \n",
|
|
" the code solution. \\n Then list the imports. And finally list the functioning code block. \n",
|
|
" \\n Here is the user question: \\n --- --- --- \\n {question}\"\"\"\n",
|
|
" template = template + addendum\n",
|
|
"\n",
|
|
" # Prompt \n",
|
|
" prompt = PromptTemplate(\n",
|
|
" template=template,\n",
|
|
" input_variables=[\"context\", \"question\", \"generation\", \"error\"],\n",
|
|
" )\n",
|
|
" \n",
|
|
" # Chain\n",
|
|
" chain = (\n",
|
|
" {\n",
|
|
" \"context\": lambda x: concatenated_content,\n",
|
|
" \"question\": itemgetter(\"question\"),\n",
|
|
" \"generation\": itemgetter(\"generation\"),\n",
|
|
" \"error\": itemgetter(\"error\"),\n",
|
|
" }\n",
|
|
" | prompt\n",
|
|
" | llm_with_tool \n",
|
|
" | parser_tool\n",
|
|
" )\n",
|
|
"\n",
|
|
" code_solution = chain.invoke({\"question\":question,\n",
|
|
" \"generation\":str(code_solution[0]),\n",
|
|
" \"error\":error})\n",
|
|
" \n",
|
|
" else:\n",
|
|
" print(\"---GENERATE SOLUTION---\")\n",
|
|
" \n",
|
|
" # Prompt \n",
|
|
" prompt = PromptTemplate(\n",
|
|
" template=template,\n",
|
|
" input_variables=[\"context\", \"question\"],\n",
|
|
" )\n",
|
|
"\n",
|
|
" # Chain\n",
|
|
" chain = (\n",
|
|
" {\n",
|
|
" # \"context\": lambda x: docs,\n",
|
|
" \"context\": lambda x: concatenated_content,\n",
|
|
" \"question\": itemgetter(\"question\"),\n",
|
|
" }\n",
|
|
" | prompt\n",
|
|
" | llm_with_tool \n",
|
|
" | parser_tool\n",
|
|
" )\n",
|
|
"\n",
|
|
" code_solution = chain.invoke({\"question\":question})\n",
|
|
"\n",
|
|
" iter = iter+1 \n",
|
|
" return {\"keys\": {\"generation\": code_solution, \"question\": question, \"iterations\": iter}}\n",
|
|
"\n",
|
|
"def check_code_imports(state):\n",
|
|
" \"\"\"\n",
|
|
" Check imports\n",
|
|
"\n",
|
|
" Args:\n",
|
|
" state (dict): The current graph state\n",
|
|
"\n",
|
|
" Returns:\n",
|
|
" state (dict): New key added to state, error\n",
|
|
" \"\"\"\n",
|
|
" \n",
|
|
" ## State\n",
|
|
" print(\"---CHECKING CODE IMPORTS---\")\n",
|
|
" state_dict = state[\"keys\"]\n",
|
|
" question = state_dict[\"question\"]\n",
|
|
" code_solution = state_dict[\"generation\"]\n",
|
|
" imports = code_solution[0].imports\n",
|
|
" iter = state_dict[\"iterations\"]\n",
|
|
"\n",
|
|
" try: \n",
|
|
" # Attempt to execute the imports\n",
|
|
" exec(imports)\n",
|
|
" except Exception as e:\n",
|
|
" print(\"---CODE IMPORT CHECK: FAILED---\")\n",
|
|
" # Catch any error during execution (e.g., ImportError, SyntaxError)\n",
|
|
" error = f\"Execution error: {e}\"\n",
|
|
" if \"error\" in state_dict:\n",
|
|
" error_prev_runs = state_dict[\"error\"]\n",
|
|
" error = error_prev_runs + \"\\n --- Most recent run error --- \\n\" + error \n",
|
|
" else:\n",
|
|
" print(\"---CODE IMPORT CHECK: SUCCESS---\")\n",
|
|
" # No errors occurred\n",
|
|
" error = \"None\"\n",
|
|
"\n",
|
|
" return {\"keys\": {\"generation\": code_solution, \"question\": question, \"error\": error, \"iterations\":iter}}\n",
|
|
"\n",
|
|
"def check_code_execution(state):\n",
|
|
" \"\"\"\n",
|
|
" Check code block execution\n",
|
|
"\n",
|
|
" Args:\n",
|
|
" state (dict): The current graph state\n",
|
|
"\n",
|
|
" Returns:\n",
|
|
" state (dict): New key added to state, error\n",
|
|
" \"\"\"\n",
|
|
" \n",
|
|
" ## State\n",
|
|
" print(\"---CHECKING CODE EXECUTION---\")\n",
|
|
" state_dict = state[\"keys\"]\n",
|
|
" question = state_dict[\"question\"]\n",
|
|
" code_solution = state_dict[\"generation\"]\n",
|
|
" prefix = code_solution[0].prefix\n",
|
|
" imports = code_solution[0].imports\n",
|
|
" code = code_solution[0].code\n",
|
|
" code_block = imports +\"\\n\"+ code\n",
|
|
" iter = state_dict[\"iterations\"]\n",
|
|
"\n",
|
|
" try: \n",
|
|
" # Attempt to execute the code block\n",
|
|
" exec(code_block)\n",
|
|
" except Exception as e:\n",
|
|
" print(\"---CODE BLOCK CHECK: FAILED---\")\n",
|
|
" # Catch any error during execution (e.g., ImportError, SyntaxError)\n",
|
|
" error = f\"Execution error: {e}\"\n",
|
|
" if \"error\" in state_dict:\n",
|
|
" error_prev_runs = state_dict[\"error\"]\n",
|
|
" error = error_prev_runs + \"\\n --- Most recent run error --- \\n\" + error \n",
|
|
" else:\n",
|
|
" print(\"---CODE BLOCK CHECK: SUCCESS---\")\n",
|
|
" # No errors occurred\n",
|
|
" error = \"None\"\n",
|
|
"\n",
|
|
" return {\"keys\": {\"generation\": code_solution, \n",
|
|
" \"question\": question, \n",
|
|
" \"error\": error, \n",
|
|
" \"prefix\":prefix,\n",
|
|
" \"imports\":imports,\n",
|
|
" \"iterations\":iter,\n",
|
|
" \"code\":code}}\n",
|
|
"\n",
|
|
"### Edges\n",
|
|
"\n",
|
|
"def decide_to_check_code_exec(state):\n",
|
|
" \"\"\"\n",
|
|
" Determines whether to test code execution, or re-try answer generation.\n",
|
|
"\n",
|
|
" Args:\n",
|
|
" state (dict): The current graph state\n",
|
|
"\n",
|
|
" Returns:\n",
|
|
" str: Next node to call\n",
|
|
" \"\"\"\n",
|
|
"\n",
|
|
" print(\"---DECIDE TO TEST CODE EXECUTION---\")\n",
|
|
" state_dict = state[\"keys\"]\n",
|
|
" question = state_dict[\"question\"]\n",
|
|
" code_solution = state_dict[\"generation\"]\n",
|
|
" error = state_dict[\"error\"]\n",
|
|
"\n",
|
|
" if error == \"None\":\n",
|
|
" # All documents have been filtered check_relevance\n",
|
|
" # We will re-generate a new query\n",
|
|
" print(\"---DECISION: TEST CODE EXECUTION---\")\n",
|
|
" return \"check_code_execution\"\n",
|
|
" else:\n",
|
|
" # We have relevant documents, so generate answer\n",
|
|
" print(\"---DECISION: RE-TRY SOLUTION---\")\n",
|
|
" return \"generate\"\n",
|
|
"\n",
|
|
"def decide_to_finish(state):\n",
|
|
" \"\"\"\n",
|
|
" Determines whether to finish (re-try code 3 times.\n",
|
|
"\n",
|
|
" Args:\n",
|
|
" state (dict): The current graph state\n",
|
|
"\n",
|
|
" Returns:\n",
|
|
" str: Next node to call\n",
|
|
" \"\"\"\n",
|
|
"\n",
|
|
" print(\"---DECIDE TO TEST CODE EXECUTION---\")\n",
|
|
" state_dict = state[\"keys\"]\n",
|
|
" question = state_dict[\"question\"]\n",
|
|
" code_solution = state_dict[\"generation\"]\n",
|
|
" error = state_dict[\"error\"]\n",
|
|
" iter = state_dict[\"iterations\"]\n",
|
|
"\n",
|
|
" if error == \"None\" or iter == 3:\n",
|
|
" # All documents have been filtered check_relevance\n",
|
|
" # We will re-generate a new query\n",
|
|
" print(\"---DECISION: TEST CODE EXECUTION---\")\n",
|
|
" return \"end\"\n",
|
|
" else:\n",
|
|
" # We have relevant documents, so generate answer\n",
|
|
" print(\"---DECISION: RE-TRY SOLUTION---\")\n",
|
|
" return \"generate\""
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 23,
|
|
"id": "1e19e44d-1628-41ea-8d45-51ea3ebd3c00",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"from langgraph.graph import END, StateGraph\n",
|
|
"\n",
|
|
"workflow = StateGraph(GraphState)\n",
|
|
"\n",
|
|
"# Define the nodes\n",
|
|
"workflow.add_node(\"generate\", generate) # generation solution\n",
|
|
"workflow.add_node(\"check_code_imports\", check_code_imports) # check imports\n",
|
|
"workflow.add_node(\"check_code_execution\", check_code_execution) # check execution\n",
|
|
"\n",
|
|
"# Build graph\n",
|
|
"workflow.set_entry_point(\"generate\")\n",
|
|
"workflow.add_edge(\"generate\", \"check_code_imports\")\n",
|
|
"workflow.add_conditional_edges(\n",
|
|
" \"check_code_imports\",\n",
|
|
" decide_to_check_code_exec,\n",
|
|
" {\n",
|
|
" \"check_code_execution\": \"check_code_execution\",\n",
|
|
" \"generate\": \"generate\",\n",
|
|
" },\n",
|
|
")\n",
|
|
"workflow.add_conditional_edges(\n",
|
|
" \"check_code_execution\",\n",
|
|
" decide_to_finish,\n",
|
|
" {\n",
|
|
" \"end\": END,\n",
|
|
" \"generate\": \"generate\",\n",
|
|
" },\n",
|
|
")\n",
|
|
"\n",
|
|
"# Compile\n",
|
|
"app = workflow.compile()"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 24,
|
|
"id": "8cf3924b-3121-4c52-8264-338ef2a82e14",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"---GENERATE SOLUTION---\n",
|
|
"---CHECKING CODE IMPORTS---\n",
|
|
"---CODE IMPORT CHECK: SUCCESS---\n",
|
|
"---DECIDE TO TEST CODE EXECUTION---\n",
|
|
"---DECISION: TEST CODE EXECUTION---\n",
|
|
"---CHECKING CODE EXECUTION---\n",
|
|
"---CODE BLOCK CHECK: FAILED---\n",
|
|
"---DECIDE TO TEST CODE EXECUTION---\n",
|
|
"---DECISION: RE-TRY SOLUTION---\n",
|
|
"---RE-GENERATE SOLUTION w/ ERROR FEEDBACK---\n",
|
|
"---CHECKING CODE IMPORTS---\n",
|
|
"---CODE IMPORT CHECK: SUCCESS---\n",
|
|
"---DECIDE TO TEST CODE EXECUTION---\n",
|
|
"---DECISION: TEST CODE EXECUTION---\n",
|
|
"---CHECKING CODE EXECUTION---\n",
|
|
"Why did the bear break up with his girlfriend?\n",
|
|
"Because he couldn't bear the relationship anymore!\n",
|
|
"---CODE BLOCK CHECK: SUCCESS---\n",
|
|
"---DECIDE TO TEST CODE EXECUTION---\n",
|
|
"---DECISION: TEST CODE EXECUTION---\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"question = \"I am passing text key 'foo' to my prompt and want to process it with a function, process_text(...), prior to the prompt. How can I do this using LCEL?\"\n",
|
|
"config = {\"recursion_limit\": 50}\n",
|
|
"answer = app.invoke({\"keys\":{\"question\":question, \"iterations\":0}},config=config)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 27,
|
|
"id": "eb8999e8-fa58-45b9-9506-3eb7ce32f0a0",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"data": {
|
|
"text/plain": [
|
|
"\"To process a text key 'foo' with a function before passing it to a prompt using LCEL, you can use a RunnableLambda. This allows you to define a custom function that processes the input text and then passes the modified text to the prompt. Here's how you can do it:\""
|
|
]
|
|
},
|
|
"execution_count": 27,
|
|
"metadata": {},
|
|
"output_type": "execute_result"
|
|
}
|
|
],
|
|
"source": [
|
|
"answer['keys']['generation'][0].prefix"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 30,
|
|
"id": "486205af-0e59-4b74-94eb-518cfc55b01f",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"exec(answer['keys']['generation'][0].imports)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 31,
|
|
"id": "216c3c91-1954-4ee4-bc7c-e78a0ea655d5",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Why did the bear break up with his girlfriend? \n",
|
|
"\n",
|
|
"Because he couldn't bear the relationship any longer!\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"exec(answer['keys']['generation'][0].code)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "4fc107f0-eecc-46f9-88d2-15c568537dfb",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": []
|
|
}
|
|
],
|
|
"metadata": {
|
|
"kernelspec": {
|
|
"display_name": "Python 3 (ipykernel)",
|
|
"language": "python",
|
|
"name": "python3"
|
|
},
|
|
"language_info": {
|
|
"codemirror_mode": {
|
|
"name": "ipython",
|
|
"version": 3
|
|
},
|
|
"file_extension": ".py",
|
|
"mimetype": "text/x-python",
|
|
"name": "python",
|
|
"nbconvert_exporter": "python",
|
|
"pygments_lexer": "ipython3",
|
|
"version": "3.9.16"
|
|
}
|
|
},
|
|
"nbformat": 4,
|
|
"nbformat_minor": 5
|
|
}
|