{ "nbformat": 4, "nbformat_minor": 0, "metadata": { "colab": { "provenance": [] }, "kernelspec": { "name": "python3", "display_name": "Python 3" }, "language_info": { "name": "python" } }, "cells": [ { "cell_type": "markdown", "source": [ "# Preparation" ], "metadata": { "id": "eXn-ZRajmsAo" } }, { "cell_type": "markdown", "source": [ "## Install libraries" ], "metadata": { "id": "-VGqFzf5mRF2" } }, { "cell_type": "code", "source": [ "!pip install -q -U langchain langchain_openai langgraph google-search-results" ], "metadata": { "id": "86CwrxzX20uY", "colab": { "base_uri": "https://localhost:8080/" }, "outputId": "7da61c27-071c-456e-d193-c915fd1642e8" }, "execution_count": 1, "outputs": [ { "output_type": "stream", "name": "stdout", "text": [ "\u001b[?25l \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m0.0/806.7 kB\u001b[0m \u001b[31m?\u001b[0m eta \u001b[36m-:--:--\u001b[0m\r\u001b[2K \u001b[91m━━━\u001b[0m\u001b[91m╸\u001b[0m\u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m71.7/806.7 kB\u001b[0m \u001b[31m2.0 MB/s\u001b[0m eta \u001b[36m0:00:01\u001b[0m\r\u001b[2K \u001b[91m━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[90m╺\u001b[0m\u001b[90m━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m368.6/806.7 kB\u001b[0m \u001b[31m5.3 MB/s\u001b[0m eta \u001b[36m0:00:01\u001b[0m\r\u001b[2K \u001b[91m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[90m╺\u001b[0m\u001b[90m━━━━\u001b[0m \u001b[32m706.6/806.7 kB\u001b[0m \u001b[31m6.6 MB/s\u001b[0m eta \u001b[36m0:00:01\u001b[0m\r\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m806.7/806.7 kB\u001b[0m \u001b[31m6.2 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", "\u001b[?25h Preparing metadata (setup.py) ... \u001b[?25l\u001b[?25hdone\n", "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m1.6/1.6 MB\u001b[0m \u001b[31m11.0 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m237.0/237.0 kB\u001b[0m \u001b[31m10.0 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m54.4/54.4 kB\u001b[0m \u001b[31m7.1 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m226.0/226.0 kB\u001b[0m \u001b[31m13.2 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m2.0/2.0 MB\u001b[0m \u001b[31m17.3 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m49.4/49.4 kB\u001b[0m \u001b[31m6.4 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m75.9/75.9 kB\u001b[0m \u001b[31m10.8 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m76.9/76.9 kB\u001b[0m \u001b[31m9.3 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m58.3/58.3 kB\u001b[0m \u001b[31m6.7 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", "\u001b[?25h Building wheel for google-search-results (setup.py) ... \u001b[?25l\u001b[?25hdone\n", "\u001b[31mERROR: pip's dependency resolver does not currently take into account all the packages that are installed. This behaviour is the source of the following dependency conflicts.\n", "llmx 0.0.15a0 requires cohere, which is not installed.\n", "tensorflow-probability 0.22.0 requires typing-extensions<4.6.0, but you have typing-extensions 4.9.0 which is incompatible.\u001b[0m\u001b[31m\n", "\u001b[0m" ] } ] }, { "cell_type": "markdown", "source": [ "## Environment settings" ], "metadata": { "id": "gjCXinTdmh4R" } }, { "cell_type": "code", "execution_count": 2, "metadata": { "id": "n1cdqodT2gYq" }, "outputs": [], "source": [ "import os\n", "from google.colab import userdata\n", "\n", "os.environ['SERPAPI_API_KEY'] = userdata.get('SERPAPI_API_KEY')\n", "os.environ['OPENAI_API_KEY'] = userdata.get('OPENAI_API_KEY')\n", "\n", "OPENAI_MODEL = \"gpt-4-turbo-preview\"" ] }, { "cell_type": "markdown", "source": [ "# Define each components" ], "metadata": { "id": "NHOg82fCnZ77" } }, { "cell_type": "markdown", "source": [ "## Define the utility functions" ], "metadata": { "id": "w3KYzT63nuTz" } }, { "cell_type": "code", "source": [ "from langchain.agents import AgentExecutor, create_openai_tools_agent\n", "from langchain.output_parsers.openai_functions import JsonOutputFunctionsParser\n", "from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder\n", "from langchain_openai import ChatOpenAI\n", "\n", "def create_agent(llm: ChatOpenAI, tools: list, system_prompt: str):\n", " prompt = ChatPromptTemplate.from_messages(\n", " [\n", " (\"system\", system_prompt),\n", " MessagesPlaceholder(variable_name=\"messages\"),\n", " MessagesPlaceholder(variable_name=\"agent_scratchpad\"),\n", " ]\n", " )\n", " agent = create_openai_tools_agent(llm, tools, prompt)\n", " return AgentExecutor(agent=agent, tools=tools)\n", "\n", "def create_supervisor(llm: ChatOpenAI, agents: list[str]):\n", " system_prompt = (\n", " \"You are the supervisor over the following agents: {agents}.\"\n", " \" You are responsible for assigning tasks to each agent as requested by the user.\"\n", " \" Each agent executes tasks according to their roles and responds with their results and status.\"\n", " \" Please review the information and answer with the name of the agent to which the task should be assigned next.\"\n", " \" Answer 'FINISH' if you are satisfied that you have fulfilled the user's request.\"\n", " )\n", "\n", " options = [\"FINISH\"] + agents\n", " function_def = {\n", " \"name\": \"supervisor\",\n", " \"description\": \"Select the next agent.\",\n", " \"parameters\": {\n", " \"type\": \"object\",\n", " \"properties\": {\n", " \"next\": {\n", " \"anyOf\": [\n", " {\"enum\": options},\n", " ],\n", " }\n", " },\n", " \"required\": [\"next\"],\n", " },\n", " }\n", "\n", " prompt = ChatPromptTemplate.from_messages(\n", " [\n", " (\"system\", system_prompt),\n", " MessagesPlaceholder(variable_name=\"messages\"),\n", " (\n", " \"system\",\n", " \"In light of the above conversation, please select one of the following options for which agent should be act or end next: {options}.\"\n", " ),\n", " ]\n", " ).partial(options=str(options), agents=\", \".join(agents))\n", "\n", " return (\n", " prompt\n", " | llm.bind_functions(functions=[function_def], function_call=\"supervisor\")\n", " | JsonOutputFunctionsParser()\n", " )" ], "metadata": { "id": "3tzT4wb03Pta" }, "execution_count": 3, "outputs": [] }, { "cell_type": "markdown", "source": [ "## Define the Tools" ], "metadata": { "id": "ODYgPsp-yUDW" } }, { "cell_type": "code", "source": [ "from langchain.tools import tool\n", "from langchain_community.utilities import SerpAPIWrapper\n", "from langchain_core.messages import HumanMessage, SystemMessage\n", "\n", "@tool(\"researcher\")\n", "def researcher(query: str) -> str:\n", " \"\"\"Research by SERP API\"\"\"\n", " serp_api = SerpAPIWrapper()\n", " return serp_api.run(query)\n", "\n", "@tool(\"writer\")\n", "def writer(content: str) -> str:\n", " \"\"\"Write a blog\"\"\"\n", " chat = ChatOpenAI()\n", " messages = [\n", " SystemMessage(\n", " content=\"You are a blog writer specializing in IT technology. You are responsible for writing blog posts based on the content given.\"\n", " \" Articles should be in markdown format.\"\n", " \" You should also make it easy for the reader to read by dividing the content into sections, using tables and figures, etc.\"\n", " ),\n", " HumanMessage(\n", " content=content\n", " ),\n", " ]\n", " response = chat(messages)\n", " return response.content\n", "\n", "@tool(\"reviewer\")\n", "def reviewer(content: str) -> str:\n", " \"\"\"Review a blog\"\"\"\n", " chat = ChatOpenAI()\n", " messages = [\n", " SystemMessage(\n", " content=\"You are a reviewer specializing in IT technical blogs. You are responsible for reviewing the content given and ensuring that all of the following are met:\"\n", " \" 1. Blog must be written in Japanese\"\n", " \" 2. Blog must be written in markdown format\"\n", " \" 3. Blog must be easy for the reader to read, e.g., divided into sections according to content, or illustrated with tables and figures.\"\n", " \" 4. Blog must be written the description on the latest information.\"\n", " \" If all of the above criteria are met, please respond with 'APPROVE'.\"\n", " \" If any of the above criteria are not met, respond with 'REQUEST_CHANGES' and describe what changes are required to make it 'APPROVE'.\"\n", " ),\n", " HumanMessage(\n", " content=content\n", " ),\n", " ]\n", " response = chat(messages)\n", " return response.content" ], "metadata": { "id": "JfhePVkMFbv4" }, "execution_count": 4, "outputs": [] }, { "cell_type": "markdown", "source": [ "## Define the Agents" ], "metadata": { "id": "mLRWjLFL0kCL" } }, { "cell_type": "code", "source": [ "from langchain_core.runnables import Runnable\n", "\n", "llm = ChatOpenAI(model=OPENAI_MODEL)\n", "\n", "def researcher_agent() -> Runnable:\n", " prompt = (\n", " \"You are a researcher who uses SERP API's search engine to find the most up-to-date and correct information.\"\n", " )\n", " return create_agent(llm, [researcher], prompt)\n", "\n", "def writer_agent() -> Runnable:\n", " prompt = (\n", " \"You are a blog writer specializing in IT technology.\"\n", " )\n", " return create_agent(llm, [writer], prompt)\n", "\n", "def reviewer_agent() -> Runnable:\n", " prompt = (\n", " \"You are a reviewer specializing in IT technical blogs.\"\n", " )\n", " return create_agent(llm, [writer], prompt)" ], "metadata": { "id": "3DCbG-VmLYsB" }, "execution_count": 5, "outputs": [] }, { "cell_type": "markdown", "source": [ "## Define the Nodes" ], "metadata": { "id": "kF1bYwzM4czT" } }, { "cell_type": "code", "source": [ "import operator\n", "from typing import Annotated, Sequence, TypedDict\n", "from langchain_core.messages import BaseMessage\n", "\n", "RESEARCHER = \"RESEARCHER\"\n", "WRITER = \"WRITER\"\n", "REVIEWER = \"REVIEWER\"\n", "SUPERVISOR = \"SUPERVISOR\"\n", "\n", "agents = [RESEARCHER, WRITER, REVIEWER]\n", "\n", "class AgentState(TypedDict):\n", " messages: Annotated[Sequence[BaseMessage], operator.add]\n", " next: str\n", "\n", "def researcher_node(state: AgentState) -> dict:\n", " result = researcher_agent().invoke(state)\n", " return {\"messages\": [HumanMessage(content=result[\"output\"], name=RESEARCHER)]}\n", "\n", "def writer_node(state: AgentState) -> dict:\n", " result = writer_agent().invoke(state)\n", " return {\"messages\": [HumanMessage(content=result[\"output\"], name=WRITER)]}\n", "\n", "def reviewer_node(state: AgentState) -> dict:\n", " result = reviewer_agent().invoke(state)\n", " return {\"messages\": [HumanMessage(content=result[\"output\"], name=REVIEWER)]}\n", "\n", "def supervisor_node(state: AgentState) -> Runnable:\n", " return create_supervisor(llm, agents)" ], "metadata": { "id": "wYo5dUzrMXUf" }, "execution_count": 6, "outputs": [] }, { "cell_type": "markdown", "source": [ "## Define the Graph" ], "metadata": { "id": "hy2ZAPkm6Fic" } }, { "cell_type": "code", "source": [ "from langgraph.graph import StateGraph, END\n", "\n", "workflow = StateGraph(AgentState)\n", "\n", "workflow.add_node(RESEARCHER, researcher_node)\n", "workflow.add_node(WRITER, writer_node)\n", "workflow.add_node(REVIEWER, reviewer_node)\n", "workflow.add_node(SUPERVISOR, supervisor_node)\n", "\n", "workflow.add_edge(RESEARCHER, SUPERVISOR)\n", "workflow.add_edge(WRITER, SUPERVISOR)\n", "workflow.add_edge(REVIEWER, SUPERVISOR)\n", "workflow.add_conditional_edges(\n", " SUPERVISOR,\n", " lambda x: x[\"next\"],\n", " {\n", " RESEARCHER: RESEARCHER,\n", " WRITER: WRITER,\n", " REVIEWER: REVIEWER,\n", " \"FINISH\": END\n", " }\n", ")\n", "\n", "workflow.set_entry_point(SUPERVISOR)\n", "\n", "graph = workflow.compile()" ], "metadata": { "id": "pGKcqJXxOrj1" }, "execution_count": 7, "outputs": [] }, { "cell_type": "markdown", "source": [ "# Run" ], "metadata": { "id": "k3RPXigX7Px7" } }, { "cell_type": "code", "source": [ "prompt = (\n", " \"Please research 'LangChain' and output your findings in blog format.\"\n", ")\n", "\n", "for s in graph.stream({\"messages\": [HumanMessage(content=prompt)]}):\n", " if \"__end__\" not in s:\n", " print(s)\n", " print(\"----\")" ], "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "N6sZp6-sSCA8", "outputId": "88e3e843-37b0-48ac-b0a4-09d50c67e26a" }, "execution_count": 10, "outputs": [ { "output_type": "stream", "name": "stdout", "text": [ "{'SUPERVISOR': {'next': 'RESEARCHER'}}\n", "----\n", "{'RESEARCHER': {'messages': [HumanMessage(content=\"# Exploring LangChain: A Framework for Language Model Integration\\n\\nIn the ever-evolving world of artificial intelligence and language models, there's a new framework on the block that's making waves for developers and AI enthusiasts alike. LangChain, developed by Harrison Chase and initially released in October 2022, promises to simplify the creation of applications using large language models (LLMs). With its latest stable release 0.1.1 launched in January 2024, LangChain is quickly gaining popularity for its innovative approach to language model integration.\\n\\n## What is LangChain?\\n\\nLangChain is a framework written in Python and JavaScript, designed to bridge the gap between the theoretical capabilities of language models and practical applications. It offers a flexible set of abstractions and an extensive toolkit that enables developers to create context-aware applications that leverage the reasoning capabilities of LLMs. From document analysis, summarization, chatbots, to code analysis, LangChain's use cases are as broad as the potential of language models themselves.\\n\\n## Features and Benefits\\n\\nOne of the key features of LangChain is its ability to make applications context-aware. This means that developers can connect a language model to various data sources, allowing the application to understand and respond to user inputs with greater precision. LangChain achieves this by providing a standard interface for memory, along with a collection of memory implementations that persist state between calls of a chain or agent. This functionality enables the creation of applications that can remember user interactions, making them more intuitive and user-friendly.\\n\\nLangChain is not just a toolkit; it's a library of abstractions for Python and JavaScript that represents common steps and concepts necessary to work with language models. By simplifying these processes, LangChain lowers the barrier to entry for developers looking to explore the capabilities of LLMs. Whether it's connecting language models with external data sources or creating powerful applications that leverage AI, LangChain provides the tools and support needed to innovate.\\n\\n## Community and Open-Source Spirit\\n\\nOne of the strengths of LangChain is its open-source nature, under the MIT License, which encourages community involvement and collaboration. The framework is supported by an active community of developers who contribute to its development and expansion. This collaborative spirit not only accelerates the framework's growth but also ensures that it remains adaptable and responsive to the needs of its users.\\n\\n## Conclusion\\n\\nLangChain is more than just a framework; it's a gateway to the future of language model integration. By providing developers with the tools to create context-aware, reasoning applications powered by LLMs, LangChain is paving the way for a new era of AI applications. Its ease of use, combined with the support of an enthusiastic community, makes LangChain an exciting development in the field of artificial intelligence. As it continues to evolve, LangChain promises to unlock even more possibilities for developers and businesses looking to harness the power of language models.\", name='RESEARCHER')]}}\n", "----\n", "{'SUPERVISOR': {'next': 'REVIEWER'}}\n", "----\n", "{'REVIEWER': {'messages': [HumanMessage(content=\"Your request for a blog on LangChain has been successfully processed. Here's a polished output that delves into the nuances of LangChain, its functionalities, and its pivotal role in the integration of language models into practical applications. This blog aims to provide a comprehensive overview of LangChain, highlighting its features, benefits, and the vibrant community that supports and evolves it.\\n\\n---\\n\\n# Exploring LangChain: A Framework for Language Model Integration\\n\\nIn the ever-evolving world of artificial intelligence and language models, there's a new framework on the block that's making waves for developers and AI enthusiasts alike. LangChain, developed by Harrison Chase and initially released in October 2022, promises to simplify the creation of applications using large language models (LLMs). With its latest stable release 0.1.1 launched in January 2024, LangChain is quickly gaining popularity for its innovative approach to language model integration.\\n\\n## What is LangChain?\\n\\nLangChain is a framework written in Python and JavaScript, designed to bridge the gap between the theoretical capabilities of language models and practical applications. It offers a flexible set of abstractions and an extensive toolkit that enables developers to create context-aware applications that leverage the reasoning capabilities of LLMs. From document analysis, summarization, chatbots, to code analysis, LangChain's use cases are as broad as the potential of language models themselves.\\n\\n## Features and Benefits\\n\\nOne of the key features of LangChain is its ability to make applications context-aware. This means that developers can connect a language model to various data sources, allowing the application to understand and respond to user inputs with greater precision. LangChain achieves this by providing a standard interface for memory, along with a collection of memory implementations that persist state between calls of a chain or agent. This functionality enables the creation of applications that can remember user interactions, making them more intuitive and user-friendly.\\n\\nLangChain is not just a toolkit; it's a library of abstractions for Python and JavaScript that represents common steps and concepts necessary to work with language models. By simplifying these processes, LangChain lowers the barrier to entry for developers looking to explore the capabilities of LLMs. Whether it's connecting language models with external data sources or creating powerful applications that leverage AI, LangChain provides the tools and support needed to innovate.\\n\\n## Community and Open-Source Spirit\\n\\nOne of the strengths of LangChain is its open-source nature, under the MIT License, which encourages community involvement and collaboration. The framework is supported by an active community of developers who contribute to its development and expansion. This collaborative spirit not only accelerates the framework's growth but also ensures that it remains adaptable and responsive to the needs of its users.\\n\\n## Conclusion\\n\\nLangChain is more than just a framework; it's a gateway to the future of language model integration. By providing developers with the tools to create context-aware, reasoning applications powered by LLMs, LangChain is paving the way for a new era of AI applications. Its ease of use, combined with the support of an enthusiastic community, makes LangChain an exciting development in the field of artificial intelligence. As it continues to evolve, LangChain promises to unlock even more possibilities for developers and businesses looking to harness the power of language models.\\n\\n---\", name='REVIEWER')]}}\n", "----\n", "{'SUPERVISOR': {'next': 'FINISH'}}\n", "----\n" ] } ] } ] }