|
@@ -15,7 +15,7 @@
|
|
|
"metadata": {},
|
|
|
"outputs": [],
|
|
|
"source": [
|
|
|
- "! pip install -U langchain_community tiktoken langchainhub chromadb langchain langgraph tavily-python sentence-transformers"
|
|
|
+ "! pip install -U langchain-huggingface langchain_community langchain-ollama tiktoken langchainhub chromadb langchain langgraph tavily-python sentence-transformers beautifulsoup4"
|
|
|
]
|
|
|
},
|
|
|
{
|
|
@@ -99,7 +99,8 @@
|
|
|
"os.environ['LANGCHAIN_ENDPOINT'] = 'https://api.smith.langchain.com'\n",
|
|
|
"os.environ['LANGCHAIN_API_KEY'] = 'LANGCHAIN_API_KEY'\n",
|
|
|
"\n",
|
|
|
- "os.environ['TAVILY_API_KEY'] = 'TAVILY_API_KEY'"
|
|
|
+ "os.environ['TAVILY_API_KEY'] = 'TAVILY_API_KEY'\n",
|
|
|
+ "os.environ[\"USER_AGENT\"] = \"USER_AGENT_KEY\""
|
|
|
]
|
|
|
},
|
|
|
{
|
|
@@ -126,7 +127,7 @@
|
|
|
"from langchain.text_splitter import RecursiveCharacterTextSplitter\n",
|
|
|
"from langchain_community.document_loaders import WebBaseLoader\n",
|
|
|
"from langchain_community.vectorstores import Chroma\n",
|
|
|
- "from langchain_community.embeddings import HuggingFaceEmbeddings\n",
|
|
|
+ "from langchain_huggingface import HuggingFaceEmbeddings\n",
|
|
|
"\n",
|
|
|
"urls = [\n",
|
|
|
" \"https://lilianweng.github.io/posts/2023-06-23-agent/\",\n",
|
|
@@ -146,7 +147,7 @@
|
|
|
"vectorstore = Chroma.from_documents(\n",
|
|
|
" documents=doc_splits,\n",
|
|
|
" collection_name=\"rag-chroma\",\n",
|
|
|
- " embedding=HuggingFaceEmbeddings(),\n",
|
|
|
+ " embedding=HuggingFaceEmbeddings(model_name=\"sentence-transformers/all-mpnet-base-v2\"),\n",
|
|
|
")\n",
|
|
|
"retriever = vectorstore.as_retriever()"
|
|
|
]
|
|
@@ -158,27 +159,27 @@
|
|
|
"metadata": {},
|
|
|
"outputs": [],
|
|
|
"source": [
|
|
|
- "### Retrieval Grader \n",
|
|
|
+ "### Retrieval Grader\n",
|
|
|
"\n",
|
|
|
"from langchain.prompts import PromptTemplate\n",
|
|
|
- "from langchain_community.chat_models import ChatOllama\n",
|
|
|
+ "from langchain_ollama import ChatOllama\n",
|
|
|
"from langchain_core.output_parsers import JsonOutputParser\n",
|
|
|
"\n",
|
|
|
"# LLM\n",
|
|
|
"llm = ChatOllama(model=local_llm, format=\"json\", temperature=0)\n",
|
|
|
"\n",
|
|
|
"prompt = PromptTemplate(\n",
|
|
|
- " template=\"\"\"You are a grader assessing relevance \n",
|
|
|
- " of a retrieved document to a user question. If the document contains keywords related to the user question, \n",
|
|
|
- " grade it as relevant. It does not need to be a stringent test. The goal is to filter out erroneous retrievals. \n",
|
|
|
- " \n",
|
|
|
+ " template=\"\"\"You are a grader assessing relevance\n",
|
|
|
+ " of a retrieved document to a user question. If the document contains keywords related to the user question,\n",
|
|
|
+ " grade it as relevant. It does not need to be a stringent test. The goal is to filter out erroneous retrievals.\n",
|
|
|
+ "\n",
|
|
|
" Give a binary score 'yes' or 'no' score to indicate whether the document is relevant to the question.\n",
|
|
|
" Provide the binary score as a JSON with a single key 'score' and no premable or explanation.\n",
|
|
|
- " \n",
|
|
|
- " Here is the retrieved document: \n",
|
|
|
+ "\n",
|
|
|
+ " Here is the retrieved document:\n",
|
|
|
" {document}\n",
|
|
|
- " \n",
|
|
|
- " Here is the user question: \n",
|
|
|
+ "\n",
|
|
|
+ " Here is the user question:\n",
|
|
|
" {question}\n",
|
|
|
" \"\"\",\n",
|
|
|
" input_variables=[\"question\", \"document\"],\n",
|
|
@@ -206,12 +207,12 @@
|
|
|
"\n",
|
|
|
"# Prompt\n",
|
|
|
"prompt = PromptTemplate(\n",
|
|
|
- " template=\"\"\"You are an assistant for question-answering tasks. \n",
|
|
|
- " Use the following pieces of retrieved context to answer the question. If you don't know the answer, just say that you don't know. \n",
|
|
|
+ " template=\"\"\"You are an assistant for question-answering tasks.\n",
|
|
|
+ " Use the following pieces of retrieved context to answer the question. If you don't know the answer, just say that you don't know.\n",
|
|
|
" Use three sentences maximum and keep the answer concise:\n",
|
|
|
- " Question: {question} \n",
|
|
|
- " Context: {context} \n",
|
|
|
- " Answer: \n",
|
|
|
+ " Question: {question}\n",
|
|
|
+ " Context: {context}\n",
|
|
|
+ " Answer:\n",
|
|
|
" \"\"\",\n",
|
|
|
" input_variables=[\"question\", \"document\"],\n",
|
|
|
")\n",
|
|
@@ -239,25 +240,25 @@
|
|
|
"metadata": {},
|
|
|
"outputs": [],
|
|
|
"source": [
|
|
|
- "### Hallucination Grader \n",
|
|
|
+ "### Hallucination Grader\n",
|
|
|
"\n",
|
|
|
"# LLM\n",
|
|
|
"llm = ChatOllama(model=local_llm, format=\"json\", temperature=0)\n",
|
|
|
"\n",
|
|
|
"# Prompt\n",
|
|
|
"prompt = PromptTemplate(\n",
|
|
|
- " template=\"\"\"You are a grader assessing whether \n",
|
|
|
- " an answer is grounded in / supported by a set of facts. Give a binary score 'yes' or 'no' score to indicate \n",
|
|
|
- " whether the answer is grounded in / supported by a set of facts. Provide the binary score as a JSON with a \n",
|
|
|
+ " template=\"\"\"You are a grader assessing whether\n",
|
|
|
+ " an answer is grounded in / supported by a set of facts. Give a binary score 'yes' or 'no' score to indicate\n",
|
|
|
+ " whether the answer is grounded in / supported by a set of facts. Provide the binary score as a JSON with a\n",
|
|
|
" single key 'score' and no preamble or explanation.\n",
|
|
|
- " \n",
|
|
|
+ "\n",
|
|
|
" Here are the facts:\n",
|
|
|
- " {documents} \n",
|
|
|
+ " {documents}\n",
|
|
|
"\n",
|
|
|
- " Here is the answer: \n",
|
|
|
+ " Here is the answer:\n",
|
|
|
" {generation}\n",
|
|
|
" \"\"\",\n",
|
|
|
- " input_variables=[\"generation\", \"documents\"],\n",
|
|
|
+ " input_variables=[\"generation\", \"documents\"]\n",
|
|
|
")\n",
|
|
|
"\n",
|
|
|
"hallucination_grader = prompt | llm | JsonOutputParser()\n",
|
|
@@ -271,19 +272,19 @@
|
|
|
"metadata": {},
|
|
|
"outputs": [],
|
|
|
"source": [
|
|
|
- "### Answer Grader \n",
|
|
|
+ "### Answer Grader\n",
|
|
|
"\n",
|
|
|
"# LLM\n",
|
|
|
"llm = ChatOllama(model=local_llm, format=\"json\", temperature=0)\n",
|
|
|
"\n",
|
|
|
"# Prompt\n",
|
|
|
"prompt = PromptTemplate(\n",
|
|
|
- " template=\"\"\"You are a grader assessing whether an \n",
|
|
|
- " answer is useful to resolve a question. Give a binary score 'yes' or 'no' to indicate whether the answer is \n",
|
|
|
+ " template=\"\"\"You are a grader assessing whether an\n",
|
|
|
+ " answer is useful to resolve a question. Give a binary score 'yes' or 'no' to indicate whether the answer is\n",
|
|
|
" useful to resolve a question. Provide the binary score as a JSON with a single key 'score' and no preamble or explanation.\n",
|
|
|
- " \n",
|
|
|
+ "\n",
|
|
|
" Here is the answer:\n",
|
|
|
- " {generation} \n",
|
|
|
+ " {generation}\n",
|
|
|
"\n",
|
|
|
" Here is the question: {question}\n",
|
|
|
" \"\"\",\n",
|
|
@@ -304,28 +305,28 @@
|
|
|
"### Router\n",
|
|
|
"\n",
|
|
|
"from langchain.prompts import PromptTemplate\n",
|
|
|
- "from langchain_community.chat_models import ChatOllama\n",
|
|
|
+ "from langchain_ollama import ChatOllama\n",
|
|
|
"from langchain_core.output_parsers import JsonOutputParser\n",
|
|
|
"\n",
|
|
|
"# LLM\n",
|
|
|
"llm = ChatOllama(model=local_llm, format=\"json\", temperature=0)\n",
|
|
|
"\n",
|
|
|
"prompt = PromptTemplate(\n",
|
|
|
- " template=\"\"\"You are an expert at routing a \n",
|
|
|
- " user question to a vectorstore or web search. Use the vectorstore for questions on LLM agents, \n",
|
|
|
- " prompt engineering, and adversarial attacks. You do not need to be stringent with the keywords \n",
|
|
|
- " in the question related to these topics. Otherwise, use web-search. Give a binary choice 'web_search' \n",
|
|
|
- " or 'vectorstore' based on the question. Return the a JSON with a single key 'datasource' and \n",
|
|
|
- " no premable or explanation. \n",
|
|
|
- " \n",
|
|
|
- " Question to route: \n",
|
|
|
+ " template=\"\"\"You are an expert at routing a\n",
|
|
|
+ " user question to a vectorstore or web search. Use the vectorstore for questions on LLM agents,\n",
|
|
|
+ " prompt engineering, and adversarial attacks. You do not need to be stringent with the keywords\n",
|
|
|
+ " in the question related to these topics. Otherwise, use web-search. Give a binary choice 'web_search'\n",
|
|
|
+ " or 'vectorstore' based on the question. Return the a JSON with a single key 'datasource' and\n",
|
|
|
+ " no premable or explanation.\n",
|
|
|
+ "\n",
|
|
|
+ " Question to route:\n",
|
|
|
" {question}\"\"\",\n",
|
|
|
" input_variables=[\"question\"],\n",
|
|
|
")\n",
|
|
|
"\n",
|
|
|
"question_router = prompt | llm | JsonOutputParser()\n",
|
|
|
"question = \"llm agent memory\"\n",
|
|
|
- "docs = retriever.get_relevant_documents(question)\n",
|
|
|
+ "docs = retriever.invoke(question)\n",
|
|
|
"doc_txt = docs[1].page_content\n",
|
|
|
"print(question_router.invoke({\"question\": question}))"
|
|
|
]
|
|
@@ -371,7 +372,7 @@
|
|
|
" question: question\n",
|
|
|
" generation: LLM generation\n",
|
|
|
" web_search: whether to add search\n",
|
|
|
- " documents: list of documents \n",
|
|
|
+ " documents: list of documents\n",
|
|
|
" \"\"\"\n",
|
|
|
" question : str\n",
|
|
|
" generation : str\n",
|
|
@@ -412,7 +413,7 @@
|
|
|
" print(\"---GENERATE---\")\n",
|
|
|
" question = state[\"question\"]\n",
|
|
|
" documents = state[\"documents\"]\n",
|
|
|
- " \n",
|
|
|
+ "\n",
|
|
|
" # RAG generation\n",
|
|
|
" generation = rag_chain.invoke({\"context\": documents, \"question\": question})\n",
|
|
|
" return {\"documents\": documents, \"question\": question, \"generation\": generation}\n",
|
|
@@ -432,7 +433,7 @@
|
|
|
" print(\"---CHECK DOCUMENT RELEVANCE TO QUESTION---\")\n",
|
|
|
" question = state[\"question\"]\n",
|
|
|
" documents = state[\"documents\"]\n",
|
|
|
- " \n",
|
|
|
+ "\n",
|
|
|
" # Score each doc\n",
|
|
|
" filtered_docs = []\n",
|
|
|
" web_search = \"No\"\n",
|
|
@@ -451,7 +452,7 @@
|
|
|
" web_search = \"Yes\"\n",
|
|
|
" continue\n",
|
|
|
" return {\"documents\": filtered_docs, \"question\": question, \"web_search\": web_search}\n",
|
|
|
- " \n",
|
|
|
+ "\n",
|
|
|
"def web_search(state):\n",
|
|
|
" \"\"\"\n",
|
|
|
" Web search based based on the question\n",
|
|
@@ -493,7 +494,7 @@
|
|
|
" print(\"---ROUTE QUESTION---\")\n",
|
|
|
" question = state[\"question\"]\n",
|
|
|
" print(question)\n",
|
|
|
- " source = question_router.invoke({\"question\": question}) \n",
|
|
|
+ " source = question_router.invoke({\"question\": question})\n",
|
|
|
" print(source)\n",
|
|
|
" print(source['datasource'])\n",
|
|
|
" if source['datasource'] == 'web_search':\n",
|
|
@@ -648,7 +649,7 @@
|
|
|
"source": [
|
|
|
"Trace: \n",
|
|
|
"\n",
|
|
|
- "https://smith.langchain.com/public/8d449b67-6bc4-4ecf-9153-759cd21df24f/r"
|
|
|
+ "https://smith.langchain.com/public/bbdef8eb-0c42-4df6-9eaa-3e7e75c87df9/r"
|
|
|
]
|
|
|
},
|
|
|
{
|
|
@@ -660,7 +661,6 @@
|
|
|
"source": [
|
|
|
"# Compile\n",
|
|
|
"app = workflow.compile()\n",
|
|
|
- "\n",
|
|
|
"# Test\n",
|
|
|
"from pprint import pprint\n",
|
|
|
"inputs = {\"question\": \"Who are the Bears expected to draft first in the NFL draft?\"}\n",
|
|
@@ -677,13 +677,13 @@
|
|
|
"source": [
|
|
|
"Trace: \n",
|
|
|
"\n",
|
|
|
- "https://smith.langchain.com/public/c785f9c0-f519-4a38-ad5a-febb59a2139c/r"
|
|
|
+ "https://smith.langchain.com/public/0e6378e7-b8d4-4979-8357-05f854584cc6/r"
|
|
|
]
|
|
|
},
|
|
|
{
|
|
|
"cell_type": "code",
|
|
|
"execution_count": null,
|
|
|
- "id": "a1059b3e-d197-47fc-b55f-82a3406016f3",
|
|
|
+ "id": "337d5b89-7030-4ae9-85ed-f5f9f6da0c26",
|
|
|
"metadata": {},
|
|
|
"outputs": [],
|
|
|
"source": []
|
|
@@ -705,7 +705,7 @@
|
|
|
"name": "python",
|
|
|
"nbconvert_exporter": "python",
|
|
|
"pygments_lexer": "ipython3",
|
|
|
- "version": "3.11.9"
|
|
|
+ "version": "3.12.7"
|
|
|
}
|
|
|
},
|
|
|
"nbformat": 4,
|