{ "cells": [ { "cell_type": "code", "execution_count": null, "id": "ba470a39", "metadata": {}, "outputs": [], "source": [ "from dotenv import load_dotenv\n", "import os\n", "load_dotenv()\n", "OPENROUTER_API_KEY = os.getenv(\"OPENROUTER_API_KEY\", \"\")\n", "MAIN_LLM_MODEL = os.getenv(\"MAIN_LLM_MODEL\", \"google/gemini-2.0-flash-lite-001\")\n", "\n", "from langfuse.callback import CallbackHandler\n", "\n", "LANGFUSE_SECRET_KEY = os.getenv(\"LANGFUSE_SECRET_KEY\", \"\")\n", "LANGFUSE_PUBLIC_KEY = os.getenv(\"LANGFUSE_PUBLIC_KEY\", \"\")\n", "LANGFUSE_HOST = os.getenv(\"LANGFUSE_HOST\", \"\")\n", "\n", "# Initialize Langfuse CallbackHandler for LangGraph/Langchain (tracing)\n", "if LANGFUSE_SECRET_KEY and LANGFUSE_PUBLIC_KEY and LANGFUSE_HOST:\n", " # Initialize the Langfuse CallbackHandler with the provided keys\n", " langfuse_handler = CallbackHandler(secret_key=LANGFUSE_SECRET_KEY, public_key=LANGFUSE_PUBLIC_KEY, host=LANGFUSE_HOST)\n", "else:\n", " # If keys are not provided, set the handler to None\n", " langfuse_handler = None" ] }, { "cell_type": "code", "execution_count": 2, "id": "dfbd8f8e", "metadata": {}, "outputs": [ { "data": { "image/png": "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", "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "from langgraph.prebuilt import create_react_agent\n", "from langchain_openai import ChatOpenAI\n", "from IPython.display import Image, display # Import necessary modules\n", "\n", "model = ChatOpenAI(\n", " model=MAIN_LLM_MODEL,\n", " api_key=OPENROUTER_API_KEY,\n", " streaming=True,\n", ")\n", "\n", "def tool() -> None:\n", " \"\"\"Testing tool.\"\"\"\n", " ...\n", "\n", "agent = create_react_agent(\n", " model,\n", " tools=[tool],\n", ")\n", "\n", "png_bytes = agent.get_graph().draw_mermaid_png()\n", "\n", "display(Image(png_bytes)) # Display the image" ] }, { "cell_type": "code", "execution_count": null, "id": "f1ccc527", "metadata": {}, "outputs": [], "source": [ "from langchain.tools import Tool\n", "from urllib.parse import urlparse\n", "\n", "@tool\n", "def get_u\n" ] }, { "cell_type": "code", "execution_count": null, "id": "4285ccba", "metadata": {}, "outputs": [], "source": [ "from typing import TypedDict, Annotated, Optional\n", "from langgraph.graph.message import add_messages\n", "from langchain_core.messages import AnyMessage, HumanMessage, AIMessage\n", "from langgraph.prebuilt import ToolNode, tools_condition\n", "from langgraph.graph import START, StateGraph\n", "from langchain_openai import ChatOpenAI # Use ChatOpenAI for OpenRouter\n", "from pydantic import SecretStr\n", "\n", "# Generate the chat interface, including the tools\n", "if OPENROUTER_API_KEY is None:\n", " raise ValueError(\"OPENROUTER_API_KEY is not set. Please ensure it is defined in your .env file or environment variables.\")\n", "\n", "\n", "\n", "\n", "def create_agent_graph() -> StateGraph:\n", " \n", " main_llm = ChatOpenAI(\n", " model=MAIN_LLM_MODEL, # e.g., \"mistralai/mistral-7b-instruct\"\n", " api_key=SecretStr(OPENROUTER_API_KEY), # Your OpenRouter API key\n", " base_url=\"https://openrouter.ai/api/v1\", # Standard OpenRouter API base\n", " verbose=True # Optional: for debugging\n", " )\n", "\n", "\n", " tools = [search_tool, weather_info_tool, hub_stats_tool] # Ensure these tools are defined\n", " chat_with_tools = main_llm.bind_tools(tools)\n", "\n", " class AgentState(TypedDict):\n", " input_file: Optional[str]\n", " messages: Annotated[list[AnyMessage], add_messages]\n", " \n", " def assistant(state: AgentState):\n", " return {\n", " \"messages\": [chat_with_tools.invoke(state[\"messages\"])],\n", " }\n", " # The graph\n", " builder = StateGraph(AgentState)\n", " # Define nodes: these do the work\n", " builder.add_node(\"assistant\", assistant)\n", " builder.add_node(\"tools\", ToolNode(tools))\n", " # Define edges: these determine how the control flow moves\n", " builder.add_edge(START, \"assistant\")\n", " builder.add_conditional_edges(\n", " \"assistant\",\n", " # If the latest message requires a tool, route to tools\n", " # Otherwise, provide a direct response\n", " tools_condition,\n", " )\n", " builder.add_edge(\"tools\", \"assistant\")\n", " \n", " return builder\n", "\n", "\n", "agent_graph = create_agent_graph()\n", "alfred = agent_graph.compile()\n", "\n", "if langfuse_handler:\n", " config = {\"callbacks\": [langfuse_handler]}\n", "else:\n", " config = None\n", "\n", "messages = [HumanMessage(content=\"Who is Facebook and what's their most popular model?\")]\n", "response = alfred.invoke(\n", " input = {\"messages\": messages}, \n", " config=config\n", " )\n", "\n", "print(\"🎩 Alfred's Response:\")\n", "print(response['messages'][-1].content)" ] }, { "cell_type": "code", "execution_count": null, "id": "f7ef828d", "metadata": {}, "outputs": [], "source": [ "from langfuse.callback import CallbackHandler\n", "\n", "# Initialize Langfuse CallbackHandler for LangGraph/Langchain (tracing)\n", "langfuse_handler = CallbackHandler()\n", "\n", "compiled_graph = agent_graph.compile()\n", "legitimate_email = ''\n", "# Process legitimate email\n", "legitimate_result = compiled_graph.invoke(\n", " input={\"email\": legitimate_email, \"is_spam\": None, \"spam_reason\": None, \"email_category\": None, \"draft_response\": None, \"messages\": []},\n", " config={\"callbacks\": [langfuse_handler]}\n", ")" ] } ], "metadata": { "kernelspec": { "display_name": "agents", "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.13.2" } }, "nbformat": 4, "nbformat_minor": 5 }