Files
langgraph/examples/web-research.ipynb
T

503 lines
20 KiB
Plaintext

{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"id": "cd80bc40-f10d-4ab3-826d-6cd0636d11e0",
"metadata": {},
"outputs": [],
"source": [
"from operator import itemgetter\n",
"\n",
"from langchain.chat_models import ChatOpenAI, ChatAnthropic\n",
"from langchain.prompts import SystemMessagePromptTemplate, ChatPromptTemplate\n",
"from langchain.schema.output_parser import StrOutputParser\n",
"from langchain.runnables.openai_functions import OpenAIFunctionsRouter\n",
"\n",
"from permchain.connection_inmemory import InMemoryPubSubConnection\n",
"from permchain.pubsub import PubSub\n",
"from permchain.topic import Topic"
]
},
{
"cell_type": "markdown",
"id": "54c553be-9ed1-452c-a4ab-828f34dbb3ce",
"metadata": {},
"source": [
"## Content Fetcher"
]
},
{
"cell_type": "markdown",
"id": "56a6788d-b67c-4331-af8d-7741a66f03af",
"metadata": {},
"source": [
"First, we are going to define our content fetcher. This is responsible for taking a search query an getting relevant web pages."
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "a9c32e92-6f19-4cf1-8b87-1b756de0e263",
"metadata": {},
"outputs": [],
"source": [
"from langchain.utilities import GoogleSearchAPIWrapper\n",
"from langchain.document_loaders import AsyncHtmlLoader\n",
"from langchain.document_transformers import Html2TextTransformer"
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "89d4a96a-2f59-491f-81fd-4a5d755c0081",
"metadata": {},
"outputs": [],
"source": [
"from duckduckgo_search import DDGS\n",
"\n",
"ddgs = DDGS()"
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "dcdc3812-0cdc-4677-bf9d-f9d7d5cac7e2",
"metadata": {},
"outputs": [],
"source": [
"def retrieve_documents(query):\n",
" query = query.strip().strip('\"')\n",
" search_results = ddgs.text(query)\n",
" urls_to_look = []\n",
" for res in search_results:\n",
" if res.get(\"href\", None):\n",
" urls_to_look.append(res[\"href\"])\n",
" if len(urls_to_look) >= 4:\n",
" break\n",
"\n",
" # Relevant urls\n",
" # Load, split, and add new urls to vectorstore\n",
" if urls_to_look:\n",
" loader = AsyncHtmlLoader(urls_to_look)\n",
" html2text = Html2TextTransformer()\n",
" docs = loader.load()\n",
" docs = list(html2text.transform_documents(docs))\n",
" else:\n",
" docs = []\n",
" return docs"
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "45bb7661-35db-4a67-a62e-9c791c9de359",
"metadata": {},
"outputs": [],
"source": [
"import nest_asyncio\n",
"\n",
"nest_asyncio.apply()"
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "d087d2b4-d1fa-4f63-81de-d3d4e1dc5b1b",
"metadata": {},
"outputs": [],
"source": [
"# docs = retrieve_documents(\"langchain\")"
]
},
{
"cell_type": "markdown",
"id": "73e0b79f-f6bd-4f68-9433-645ee1eea81e",
"metadata": {},
"source": [
"## Summarizer\n",
"We will now come up with an actor to summarize the results given a query and some search results"
]
},
{
"cell_type": "code",
"execution_count": 7,
"id": "901e1f8d-c973-4998-a731-5dab0c147b8c",
"metadata": {},
"outputs": [],
"source": [
"prompt = ChatPromptTemplate.from_template(\n",
" \"Answer the user's question given the search results\\n\\n<question>{question}</question><search_results>{search_results}</search_results>\"\n",
")"
]
},
{
"cell_type": "code",
"execution_count": 8,
"id": "915bec33-d210-4471-b051-859ecba608be",
"metadata": {},
"outputs": [],
"source": [
"summarizer_chain = (\n",
" prompt\n",
" | ChatOpenAI(max_retries=0).with_fallbacks(\n",
" [ChatOpenAI(model=\"gpt-3.5-turbo-16k\"), ChatAnthropic(model=\"claude-2\")]\n",
" )\n",
" | StrOutputParser()\n",
")"
]
},
{
"cell_type": "markdown",
"id": "6bf403ec-39a4-4061-9401-06850ffe3761",
"metadata": {},
"source": [
"## All together now!"
]
},
{
"cell_type": "code",
"execution_count": 9,
"id": "edc0def4-d184-4438-9099-e6604ba9ff28",
"metadata": {},
"outputs": [],
"source": [
"summarizer_inbox = Topic(\"summarizer\")"
]
},
{
"cell_type": "code",
"execution_count": 10,
"id": "23f89611-7b0f-4f01-b9a7-119124e3341d",
"metadata": {},
"outputs": [],
"source": [
"search_actor = (\n",
" Topic.IN.subscribe()\n",
" | {\n",
" \"search_results\": retrieve_documents,\n",
" \"question\": Topic.IN.current(),\n",
" }\n",
" | summarizer_inbox.publish()\n",
")"
]
},
{
"cell_type": "code",
"execution_count": 11,
"id": "2d4a6b51-bd93-47c2-a301-9593a47df7d4",
"metadata": {},
"outputs": [],
"source": [
"summ_actor = (\n",
" summarizer_inbox.subscribe() | {\"answer\": summarizer_chain} | Topic.OUT.publish()\n",
")"
]
},
{
"cell_type": "code",
"execution_count": 12,
"id": "11d3b066-7f95-4ad9-82d0-ba64bbf3e3fa",
"metadata": {},
"outputs": [],
"source": [
"web_researcher = PubSub(\n",
" processes=(search_actor, summ_actor),\n",
" connection=InMemoryPubSubConnection(),\n",
").with_config(run_name=\"WebResearcher\")"
]
},
{
"cell_type": "code",
"execution_count": 13,
"id": "bc022d51-69f0-4da9-8025-70afdc3cc6a8",
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"Fetching pages: 100%|###################################################| 4/4 [00:01<00:00, 2.46it/s]\n"
]
},
{
"data": {
"text/plain": [
"[{'answer': 'LangSmith is a platform that helps developers build production-grade language model applications and allows for efficient development lifecycles, maintenance, and improvement of AI models. It is built by the developers who created LangChain and integrates seamlessly with that library. LangSmith provides features such as tracing runs associated with an active instance and testing and evaluating prompts or answers generated by the language model applications. It aims to address the challenges of building reliable and maintainable language model applications for production. For more information, you can refer to the LangSmith documentation.'}]"
]
},
"execution_count": 13,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"web_researcher.invoke(\"What is langsmith?\")"
]
},
{
"cell_type": "code",
"execution_count": 14,
"id": "000f4f24-15ba-476f-8a33-d023081b18d2",
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"Fetching pages: 0%| | 0/4 [00:00<?, ?it/s]\n",
"Fetching pages: 100%|###################################################| 4/4 [00:00<00:00, 8.78it/s]\u001b[A\n",
"Fetching pages: 100%|###################################################| 4/4 [00:01<00:00, 2.76it/s]\n"
]
},
{
"data": {
"text/plain": [
"[[{'answer': 'Based on the search results, LangSmith is a platform that helps developers build and evaluate language model applications. It is designed to assist in moving from prototyping to production and aims to address the challenges of building and maintaining reliable and consistent language model applications. LangSmith is built by the creators of LangChain, a popular language model software tool. It provides features for tracing, testing, evaluating, and monitoring language model applications. LangSmith integrates seamlessly with LangChain and requires a sign-up and API key to access its capabilities.'}],\n",
" [{'answer': 'According to the search results, a llama is a domesticated livestock species that is a descendant of the guanaco and belongs to the camel family. Llamas are primarily used as pack animals and a source of food, wool, hides, tallow for candles, and dried dung for fuel. They are found primarily in South American countries such as Bolivia, Peru, Colombia, Ecuador, Chile, and Argentina. Llamas are known for their long necks, long legs, small heads, large pointed ears, and ability to graze on grass and other plants. They are gregarious animals and can interbreed with other lamoids, such as guanacos, vicuñas, and alpacas. Llama fleece is sheared every two years and consists of coarse guard hairs and short crimped fibers. The fleece is used for knitwear, woven fabrics, rugs, rope, and fabric.'}]]"
]
},
"execution_count": 14,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"web_researcher.batch([\"what is langsmith\", \"what is llama\"])"
]
},
{
"cell_type": "markdown",
"id": "5952e9b8-2a56-4d2d-997a-dceb7652186f",
"metadata": {},
"source": [
"## Trying to use it as a sub component"
]
},
{
"cell_type": "code",
"execution_count": 15,
"id": "43ca019d-a500-4c77-8e62-a46e54ffae7d",
"metadata": {},
"outputs": [],
"source": [
"from langchain.output_parsers.openai_functions import JsonKeyOutputFunctionsParser"
]
},
{
"cell_type": "code",
"execution_count": 16,
"id": "858a82ae-a73f-4da2-9210-298af789ea30",
"metadata": {},
"outputs": [],
"source": [
"template = \"\"\"Write between 2 and 5 sub questions that serve as google search queries to search online that form an objective opinion from the following: {question}\"\"\"\n",
"functions = [\n",
" {\n",
" \"name\": \"sub_questions\",\n",
" \"description\": \"List of sub questions\",\n",
" \"parameters\": {\n",
" \"type\": \"object\",\n",
" \"properties\": {\n",
" \"questions\": {\n",
" \"type\": \"array\",\n",
" \"description\": \"List of sub questions to ask.\",\n",
" \"items\": {\"type\": \"string\"},\n",
" },\n",
" },\n",
" },\n",
" },\n",
"]\n",
"prompt = ChatPromptTemplate.from_template(template)\n",
"question_chain = (\n",
" prompt\n",
" | ChatOpenAI(temperature=0).bind(\n",
" functions=functions, function_call={\"name\": \"sub_questions\"}\n",
" )\n",
" | JsonKeyOutputFunctionsParser(key_name=\"questions\")\n",
")"
]
},
{
"cell_type": "code",
"execution_count": 17,
"id": "c0298fdc-0e7c-4e79-9cb7-cdd4d50fe88f",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"['What is the purpose of Langsmith?',\n",
" 'Who developed Langsmith?',\n",
" 'What are the key features of Langsmith?',\n",
" 'Are there any alternatives to Langsmith?',\n",
" 'What are the reviews or feedback on Langsmith?']"
]
},
"execution_count": 17,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"question_chain.invoke({\"question\": \"what is langsmith?\"})"
]
},
{
"cell_type": "code",
"execution_count": 18,
"id": "a0101bd0-cd95-4b13-ab26-d5d34d703bf9",
"metadata": {},
"outputs": [],
"source": [
"template = \"\"\"You are tasked with writing a research report to answer the following question:\n",
"\n",
"<question>\n",
"{question}\n",
"</question>\n",
"\n",
"In order to do that, you first came up with several sub questions and researched those. please find those below:\n",
"\n",
"<research>\n",
"{research}\n",
"</research>\n",
"\n",
"Now, write your final report answering the original question!\"\"\"\n",
"prompt = ChatPromptTemplate.from_template(template)\n",
"report_chain = prompt | ChatOpenAI() | StrOutputParser()"
]
},
{
"cell_type": "code",
"execution_count": 19,
"id": "d7715e0c-23c0-4985-97a7-bf5b151cf734",
"metadata": {},
"outputs": [],
"source": [
"research_inbox = Topic(\"research\")\n",
"writer_inbox = Topic(\"writer_inbox\")"
]
},
{
"cell_type": "code",
"execution_count": 20,
"id": "f274027a-c9f0-4efa-b798-1921b9b376d9",
"metadata": {},
"outputs": [],
"source": [
"subquestion_actor = (\n",
" # Listed in inputs\n",
" Topic.IN.subscribe()\n",
" | question_chain\n",
" # The draft always goes to the editors inbox\n",
" | research_inbox.publish()\n",
")\n",
"research_actor = (\n",
" research_inbox.subscribe()\n",
" | {\n",
" \"research\": web_researcher.map(),\n",
" # \"research\": lambda x: [web_researcher.invoke({\"question\": i}) for i in x],\n",
" \"question\": Topic.IN.current() | itemgetter(\"question\"),\n",
" }\n",
" | writer_inbox.publish()\n",
")\n",
"write_actor = writer_inbox.subscribe() | report_chain | Topic.OUT.publish()"
]
},
{
"cell_type": "code",
"execution_count": 21,
"id": "789b636d-23ce-44fb-a8e3-fdfbfabe77ff",
"metadata": {},
"outputs": [],
"source": [
"longer_researcher = PubSub(\n",
" processes=(subquestion_actor, research_actor, write_actor),\n",
" connection=InMemoryPubSubConnection(),\n",
").with_config(run_name=\"LongResearcher\")"
]
},
{
"cell_type": "code",
"execution_count": 22,
"id": "8f713a31-5f60-4d90-9b95-3f42d8fbbddb",
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"Fetching pages: 0%| | 0/4 [00:00<?, ?it/s]\n",
"Fetching pages: 0%| | 0/4 [00:00<?, ?it/s]\u001b[A\n",
"\n",
"\n",
"Fetching pages: 0%| | 0/4 [00:00<?, ?it/s]\u001b[A\u001b[A\u001b[A\n",
"\n",
"\n",
"\n",
"Fetching pages: 0%| | 0/4 [00:00<?, ?it/s]\u001b[A\u001b[A\u001b[A\u001b[A\n",
"\n",
"Fetching pages: 0%| | 0/4 [00:00<?, ?it/s]\u001b[A\u001b[A\n",
"\n",
"\n",
"Fetching pages: 100%|###################################################| 4/4 [00:01<00:00, 3.33it/s]\u001b[A\u001b[A\u001b[A\n",
"\n",
"\n",
"\n",
"\n",
"Fetching pages: 100%|###################################################| 4/4 [00:01<00:00, 3.02it/s]\u001b[A\u001b[A\u001b[A\u001b[A\n",
"\n",
"Fetching pages: 100%|###################################################| 4/4 [00:01<00:00, 2.86it/s]\u001b[A\n",
"\n",
"\n",
"Fetching pages: 100%|###################################################| 4/4 [00:01<00:00, 2.33it/s]\u001b[A\u001b[A\n",
"Fetching pages: 100%|###################################################| 4/4 [00:02<00:00, 1.94it/s]\n"
]
},
{
"data": {
"text/plain": [
"[\"Research Report: Understanding LangSmith - A Unified Platform for Building LLM Applications\\n\\nIntroduction:\\nThe purpose of this research report is to provide a comprehensive understanding of LangSmith, a unified platform designed to assist developers in building production-grade Language Model applications (LLMs). By exploring various sub-questions, we have gathered information about LangSmith's features, development team, alternatives, and user feedback.\\n\\n1. What is LangSmith?\\nLangSmith is a unified platform developed by LangChain, the creators of LangChain itself. It aims to streamline the development lifecycle, maintenance, and improvement of LLM applications. By providing tools for debugging, testing, evaluating, and monitoring LLM applications, LangSmith enables developers to transition from prototype to production seamlessly. It addresses the challenges associated with building reliable and maintainable LLM applications in production environments.\\n\\n2. Features and Integration:\\nLangSmith offers a range of features to facilitate the development and management of LLM applications. These include tracing runs, testing and evaluating LLM-generated prompts or answers, and visualizing and replaying traces. The platform integrates seamlessly with LangChain, providing native integration for debugging and monitoring LLM applications.\\n\\n3. Getting Started with LangSmith:\\nTo utilize LangSmith, users need to sign up for an account and create an API key. Additionally, having a GitHub repository and an OpenAI API key is necessary for integration. Although LangSmith is currently in beta, periodic access to new sign-ups is available.\\n\\n4. Alternatives to LangSmith:\\nBased on our research, we have identified several alternatives to LangSmith for developers working with LLM applications. These alternatives offer similar functionalities and may serve as viable options depending on specific project requirements. Some notable alternatives include:\\n\\n- LangChain: An open source framework for building conversational AI agents, which integrates with LangSmith for debugging and monitoring.\\n- Autoblocks: A tool that monitors and improves AI models powered by large language models, providing an SDK for easy integration.\\n- BenchLLM: An open source tool specifically designed for evaluating large language models, supporting models from various providers including OpenAI and LangChain.\\n- GradientJ: A comprehensive platform for building, evaluating, and managing large language models, offering features such as prompt chaining and data integration.\\n- Portkey: An LMOps platform catering to the deployment of production-ready LLM applications, offering model management, monitoring, and versioning tools.\\n- Vellum AI: A platform equipped with tools for developing LLM applications, including prompt engineering, version control, testing, and monitoring. Compatible with multiple LLM providers.\\n- Openlayer: A collaborative platform that facilitates aligning expectations around LLM quality and performance, providing diagnostic tools for issue resolution and iteration.\\n- Metal: A tool that focuses on providing LLM developers with a seamless workflow, although specific details about its features are not available.\\n\\n5. User Feedback:\\nLangSmith has received positive reviews and feedback from the community. Although the reviews were based on the tool's description and potential rather than personal usage, LangSmith has an overall rating of 5/5. Users have praised the platform for simplifying the transition of projects from the prototyping phase to full-fledged production. LangSmith's ability to manage the complexity of LLM applications and enhance product development and iteration capabilities has been highlighted.\\n\\nConclusion:\\nIn conclusion, LangSmith is a unified platform developed by LangChain to assist developers in building production-grade Language Model applications. It offers a range of features for debugging, testing, evaluating, and monitoring LLM applications, aiming to simplify the development lifecycle, maintenance, and improvement of these applications. Although alternatives exist, LangSmith has received positive feedback and has the potential to enhance productivity and workflow for developers working with LLMs.\"]"
]
},
"execution_count": 22,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"longer_researcher.invoke({\"question\": \"what is langsmith?\"})"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "fde8b227-64ec-4e96-b337-fc888e7ad787",
"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.11.4"
}
},
"nbformat": 4,
"nbformat_minor": 5
}