{ "cells": [ { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from typing import Annotated, List, Literal, Optional\n", "from pydantic import BaseModel, Field\n", "from operator import add\n", "from langgraph.graph.message import add_messages\n", "from langgraph.graph import StateGraph, END\n", "from langgraph.graph.state import CompiledStateGraph\n", "from IPython.display import Image, display\n", "# HuggingFace\n", "from langchain_huggingface.embeddings import HuggingFaceEndpointEmbeddings\n", "from langchain_huggingface import ChatHuggingFace, HuggingFaceEndpoint\n", "# Prompts\n", "from langchain.prompts import PromptTemplate\n", "from langchain_core.messages import BaseMessage\n", "from langchain_core.tools import tool\n", "# Others\n", "import os\n", "from dotenv import load_dotenv\n", "# # LangSmith\n", "# import uuid\n", "# from langchain_core.tracers.context import collect_runs\n", "# from langchain_core.tracers.langchain import wait_for_all_tracers\n", "# from langsmith import Client\n", "# from langchain.callbacks.tracers import LangChainTracer" ] }, { "cell_type": "code", "execution_count": 2, "id": "ab89c1bc", "metadata": {}, "outputs": [], "source": [ "# Understanding Pydantic and Typing\n", "# https://typing.python.org/en/latest/spec/annotations.html\n", "# https://docs.pydantic.dev/latest/\n", "# https://medium.com/@moraneus/exploring-the-power-of-pythons-typing-library-ff32cec44981\n", "# https://coderivers.org/blog/typingannotated-python/\n", "# https://chatgpt.com/share/68644926-ccfc-800a-b668-4752077e3a29" ] }, { "cell_type": "code", "execution_count": 3, "id": "d137f5ad", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "True" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Provide the filename as a string\n", "load_dotenv('../.env')" ] }, { "cell_type": "markdown", "id": "68a6a30e", "metadata": {}, "source": [ "## **Define State**" ] }, { "cell_type": "code", "execution_count": 4, "id": "bfe2ebdb", "metadata": {}, "outputs": [], "source": [ "class ResearchArticle(BaseModel):\n", " text: str\n", " title:str\n", " category: str\n", "\n", "class ResearchArticleState(BaseModel):\n", " \"\"\"\n", " Represents the evolving state of the article bot.\n", " \"\"\"\n", " article: Annotated[List[ResearchArticle], add] = []\n", " articles_choice: Literal[\"n\", \"c\", \"q\"] = \"n\"\n", " category: str = \"nlp\"\n", " title:str = \"Solving the myth and facts of child development with nlp\"\n", " quit: bool = False" ] }, { "cell_type": "code", "execution_count": 5, "id": "ae02f563", "metadata": {}, "outputs": [], "source": [ "class AgenticResearchArticleState(ResearchArticleState):\n", " latest_article: str = \"\"\n", " approved: bool = False\n", " retry_count:int = 0" ] }, { "cell_type": "markdown", "id": "8dffeb22", "metadata": {}, "source": [ "## **Utilities**" ] }, { "cell_type": "code", "execution_count": 6, "id": "1cc7442a", "metadata": {}, "outputs": [], "source": [ "def get_user_input(prompt:str)-> str:\n", " prompt_input = input(prompt)\n", " prompt_input = \"\".join(prompt_input).strip().lower()\n", " return prompt_input\n", "\n", "def print_article(article:ResearchArticle):\n", " \"\"\"\n", " Print article with nice formatting\n", " \"\"\"\n", " print(f\"\\nCATEGORY: {article.category.upper()}\\n\")\n", " print(f\"\\n{article.title}\\n\")\n", " print(f\"\\n{article.text}\\n\")\n", " print(\"=\"* 60)\n", "\n", "def print_menu_header(category:str, total_articles:int):\n", " \"\"\"\n", " Print a compact menu header\n", " \"\"\"\n", " print(f\"๐ŸŽญ Menu | Category: {category.upper()} | Articles: {total_articles}\")\n", " print(\"-\" * 50)" ] }, { "cell_type": "markdown", "id": "699940c6", "metadata": {}, "source": [ "## **LLMS**" ] }, { "cell_type": "code", "execution_count": 7, "id": "3edd2c97", "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "WARNING! max_length is not default parameter.\n", " max_length was transferred to model_kwargs.\n", " Please make sure that max_length is what you intended.\n" ] } ], "source": [ "# Provide the filename as a string\n", "load_dotenv('.env')\n", "\n", "\n", "# loadding Huggingface token\n", "HUGGINGFACEHUB_API_TOKEN = os.getenv(\"HUGGINGFACEHUB_API_TOKEN\")\n", "\n", "# models \n", "repo_id_writer = \"mistralai/Mistral-7B-Instruct-v0.3\"\n", "repo_id_critic = \"mistralai/Mistral-7B-Instruct-v0.3\"\n", "# repo_id_critic = \"mistralai/Mistral-Small-24B-Instruct-2501\"\n", "\n", "\n", "# model parameters\n", "model_kwargs_writer = {\n", " \"max_new_tokens\": 200, # Maximum tokens to generate\n", " \"max_length\": 100, # Maximum length of input + output\n", " \"temperature\": 0.8, # Controls randomness of output\n", " \"timeout\": 6000,\n", " # \"task\":'conversational'\n", "}\n", "\n", "# LLM set up\n", "llm_writer = HuggingFaceEndpoint(\n", " repo_id=repo_id_writer,\n", " huggingfacehub_api_token = HUGGINGFACEHUB_API_TOKEN,\n", " **model_kwargs_writer\n", " # you specify the task or not\n", " # You can also specify the task in the model_kwargs or within here\n", " # task = 'conversational',\n", ")\n", "# model parameters\n", "model_kwargs_critic = {\n", " \"max_new_tokens\": 5, # Maximum tokens to generate\n", " # \"max_length\": 4000, # Maximum length of input + output\n", " \"temperature\": 0.1, # Controls randomness of output\n", " \"timeout\": 6000,\n", " # \"task\":'conversational'\n", "}\n", "\n", "# LLM set up\n", "llm_critic = HuggingFaceEndpoint(\n", " repo_id=repo_id_critic,\n", " huggingfacehub_api_token = HUGGINGFACEHUB_API_TOKEN,\n", " **model_kwargs_critic\n", " # you specify the task or not\n", " # You can also specify the task in the model_kwargs or within here\n", " # task = 'conversational',\n", ")\n", "\n", "chat_model_writer = ChatHuggingFace(llm=llm_writer)\n", "chat_model_critic = ChatHuggingFace(llm=llm_critic)" ] }, { "cell_type": "markdown", "id": "863283ed", "metadata": {}, "source": [ "## **Prompts**" ] }, { "cell_type": "code", "execution_count": 8, "id": "cc2ebd9d", "metadata": {}, "outputs": [], "source": [ "# Writer prompt\n", "WRITER_PROMPT = \"\"\"\n", "You are the best captivating research abstract generator \n", "with 20 years of experience \n", "who can write the most interesting research abstracts.\\n\n", "When given a category and title, be as detailed and concise as possible.\\n\\n\\n\n", "Here are examples\n", "======================================================\n", "category: nlp\n", "Title:The Next Frontier in Natural Language Processing\n", "\n", "Abstract\n", "Natural Language Processing (NLP) has evolved from rule-based text manipulation to enabling human-like interactions across billions of devices. While transformers like BERT and GPT revolutionized text understanding, the next frontier lies in grounding language in real-world context, emotion, and dynamic memory. This article explores the state-of-the-art in NLP, its challenges, and the emerging paradigms shaping its futureโ€”from multimodal intelligence to reasoning-aware models.\n", "======================================================\n", "\\n\\n\\n\n", "Category: {category}\n", "Title: {title}\n", "Abstract: \n", "\"\"\"\n", "# Critic prompt\n", "CRITIC_PROMPT = \"\"\"\n", "Daniel the greatest critic and editor of research articles.\\n\n", "You evaluate all research article blog post to see if they are structured or not.\n", "You reponse only by saying YES or NO.\\n\\n\\n\n", "======================================================\n", "Here are examples\n", "category: nlp\n", "Title: Eyes of the Machine: The Expanding Horizon of Computer Vision\n", "Abstract:\n", "Computer Vision, once limited to edge detection and barcode scanning, now powers autonomous vehicles, medical diagnosis, and generative art. From convolutional neural networks (CNNs) to vision-language transformers and neuromorphic sensors, the field is undergoing a seismic transformation. This article explores the evolving landscape of CV, current breakthroughs, limitations, and the emerging frontier of visual intelligence.\n", "Response: YES\n", "======================================================\n", "\\n\\n\\n\n", "Abstract: {abstract}\n", "RESPONSE: \n", "\"\"\"" ] }, { "cell_type": "code", "execution_count": 9, "id": "8061d5db", "metadata": {}, "outputs": [], "source": [ "writer_input_variable = ['category','title']\n", "writer_prompt = PromptTemplate(template=WRITER_PROMPT,\n", " input_variables=writer_input_variable)\n", "\n", "\n", "critic_prompt_variable = ['abstract']\n", "critic_prompt = PromptTemplate(\n", " template=CRITIC_PROMPT,input_variables=critic_prompt_variable\n", ")" ] }, { "cell_type": "markdown", "id": "fe73f7c2", "metadata": {}, "source": [ "## **Define Nodes**" ] }, { "cell_type": "code", "execution_count": null, "id": "4f2c54b0", "metadata": {}, "outputs": [], "source": [ "def make_writer_node(llm):\n", " def writer_node(state: AgenticResearchArticleState) -> dict:\n", " chain = writer_prompt | llm\n", " response = chain.invoke({\"category\": state.category, \"title\": state.title})\n", " content = response.content.strip().lower()\n", " return {\"latest_article\": content}\n", " return writer_node" ] }, { "cell_type": "code", "execution_count": null, "id": "7d09a484", "metadata": {}, "outputs": [], "source": [ "# critic-node\n", "def make_critic_node(llm):\n", " def critic_node(state:AgenticResearchArticleState)-> dict:\n", " critic = critic_prompt | llm\n", " decision = critic.invoke({\"abstract\": state.latest_article})\n", " decision = decision.content.strip().lower()\n", " approved = \"yes\" in decision\n", " return {\n", " \"approved\":approved,\n", " \"retry_count\":state.retry_count + 1\n", " }\n", " return critic_node" ] }, { "cell_type": "code", "execution_count": 12, "id": "70267684", "metadata": {}, "outputs": [], "source": [ "def show_final_article(state:AgenticResearchArticleState) -> dict:\n", " article = ResearchArticle(\n", " text=state.latest_article,\n", " category=state.category,\n", " title=state.title\n", " )\n", " print_article(article)\n", " return {\n", " \"article\":[article],\n", " \"retry_count\": 0,\n", " 'approved': False\n", " }" ] }, { "cell_type": "code", "execution_count": 13, "id": "91ec73b8", "metadata": {}, "outputs": [], "source": [ "def writer_critic_router(state: AgenticResearchArticleState) -> str:\n", " if state.approved or state.retry_count >= 20:\n", " return \"show_final_article\"\n", " return \"writer\"" ] }, { "cell_type": "code", "execution_count": 14, "id": "83f15417", "metadata": {}, "outputs": [], "source": [ "def show_menu(state: ResearchArticleState) -> dict:\n", " print_menu_header(state.category, len(state.article))\n", " print(\"Pick an option\")\n", " user_input = get_user_input(\n", " \"[n] ๐ŸŽญ Next Article \\n[c] ๐Ÿ“‚ Change Category\\n[q] ๐Ÿšช Quit\\nUser Input: \"\n", " )\n", "\n", " while user_input not in [\"n\", \"c\", \"q\"]:\n", " print(\"โŒ Invalid input. Please try again.\")\n", " user_input = get_user_input(\n", " \"[n] ๐ŸŽญ Next Article [c] ๐Ÿ“‚ Change Category [q] ๐Ÿšช Quit\\n User Input: \"\n", " )\n", "\n", " result = {\"articles_choice\": user_input}\n", "\n", " # Always prompt for title when 'n' is chosen\n", " if user_input == \"n\":\n", " title = input(\"\\nEnter a title for the new article:\\n\\nTITLE: \")\n", " result[\"title\"] = title.strip()\n", "\n", " return result\n", "\n", "\n", "\n", "# # Original\n", "# def show_menu(state:ResearchArticleState) -> dict:\n", "# print_menu_header(state.category,len(state.article))\n", "# print(\"Pick an option\")\n", "# user_input = get_user_input(\n", "# \"[n] ๐ŸŽญ Next Article \\n[c] ๐Ÿ“‚ Change Category\\n[q] ๐Ÿšช Quit\\nUser Input: \"\n", "# )\n", "\n", "# while user_input not in [\"n\", \"c\", \"q\"]:\n", "# print(\"โŒ Invalid input. Please try again.\")\n", "# user_input = get_user_input(\n", "# \"[n] ๐ŸŽญ Next Article [c] ๐Ÿ“‚ Change Category [q] ๐Ÿšช Quit\\n User Input: \"\n", "# )\n", "# return {\"articles_choice\": user_input}" ] }, { "cell_type": "code", "execution_count": 15, "id": "c9c4798c", "metadata": {}, "outputs": [], "source": [ "def update_category(state: AgenticResearchArticleState) -> dict:\n", " categories = [\"nlp\", \n", " \"computer_vision\", \n", " \"gen_ai\"]\n", " print(\"CATEGORY SELECTION\")\n", " print(\"=\" * 60)\n", "\n", " for i, cat in enumerate(categories):\n", " print(f\" {i}. {cat.upper()}\")\n", "\n", " print(\"=\" * 60)\n", "\n", " try:\n", " selection = int(input(\" Enter category number: \").strip())\n", " # title = input(\"What is your title? \")\n", " if 0 <= selection < len(categories):\n", " selected_category = categories[selection]\n", " print(f\" โœ… Category changed to: {selected_category.upper()}\")\n", " return {\n", " \"category\": selected_category,\n", " # \"title\":title\n", " }\n", " else:\n", " print(\" โŒ Invalid choice. Keeping current category.\")\n", " return {}\n", " except ValueError:\n", " print(\" โŒ Please enter a valid number. Keeping current category.\")\n", " return {}" ] }, { "cell_type": "code", "execution_count": 16, "id": "d0b4ff1a", "metadata": {}, "outputs": [], "source": [ "def exit_bot(state:ResearchArticleState) -> dict:\n", " print(\"\\n\" + \"๐Ÿšช\" + \"=\" * 58 + \"๐Ÿšช\")\n", " print(\" GOODBYE!\")\n", " print(\"=\" * 60)\n", " return {\"quit\": True}" ] }, { "cell_type": "code", "execution_count": 17, "id": "3c2d7b22", "metadata": {}, "outputs": [], "source": [ "def route_choice(state:ResearchArticleState)-> str:\n", " \"\"\"\n", " Router function to determine the next node based on user choice.\n", " Keys must match the target node names.\n", " \"\"\"\n", " if state.articles_choice == \"n\":\n", " return \"fetch_article\"\n", " elif state.articles_choice == \"c\":\n", " return \"update_category\"\n", " elif state.articles_choice == \"q\":\n", " return \"exit_bot\"\n", " else:\n", " return \"exit_bot\"" ] }, { "cell_type": "markdown", "id": "0a1998d8", "metadata": {}, "source": [ "## **Building the Graph**" ] }, { "cell_type": "code", "execution_count": 18, "id": "74033c0f", "metadata": {}, "outputs": [], "source": [ "def build_joke_graph(writer_llm, critic_llm) -> CompiledStateGraph:\n", " workflow = StateGraph(AgenticResearchArticleState)\n", "\n", " # Register nodes\n", " workflow.add_node(\"show_menu\",show_menu)\n", " workflow.add_node(\"update_category\",update_category)\n", " workflow.add_node(\"exit_bot\",exit_bot)\n", " workflow.add_node(\"writer\", make_writer_node(writer_llm))\n", " workflow.add_node(\"critic\", make_critic_node(critic_llm))\n", " workflow.add_node(\"show_final_article\",show_final_article)\n", "\n", " # Set entry point\n", " workflow.set_entry_point(\"show_menu\")\n", " \n", " # Routing Logic-1\n", " workflow.add_conditional_edges(\n", " \"show_menu\",\n", " route_choice,\n", " {\n", " \"fetch_article\": \"writer\",\n", " \"update_category\": \"update_category\",\n", " \"exit_bot\": \"exit_bot\", \n", " },\n", " )\n", "\n", " # Define transitions\n", " workflow.add_edge(\"update_category\", \"show_menu\")\n", " workflow.add_edge(\"writer\", \"critic\")\n", " \n", " \n", " # Routing Logic-2\n", " workflow.add_conditional_edges(\n", " 'critic',\n", " writer_critic_router,\n", " {\n", " \"writer\": 'writer',\n", " \"show_final_article\": \"show_final_article\",\n", " }\n", " )\n", " workflow.add_edge(\"show_final_article\", \"show_menu\")\n", " workflow.add_edge(\"exit_bot\", END)\n", " \n", " return workflow.compile()" ] }, { "cell_type": "markdown", "id": "51a84f6c", "metadata": {}, "source": [ "## **Graph Visualisation**" ] }, { "cell_type": "code", "execution_count": 19, "id": "6446bea3", "metadata": {}, "outputs": [], "source": [ "def graph_visualiser(graph):\n", " try:\n", " display(Image(graph.get_graph().draw_mermaid_png()))\n", " except Exception as e:\n", " print(e)" ] }, { "cell_type": "code", "execution_count": 20, "id": "d4f1917b", "metadata": {}, "outputs": [ { "data": { "image/png": "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", "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "graph_visualiser(build_joke_graph(chat_model_writer,chat_model_critic))" ] }, { "cell_type": "markdown", "id": "754b0e32", "metadata": {}, "source": [ "## **Main Code**" ] }, { "cell_type": "code", "execution_count": 21, "id": "8d69b7e3", "metadata": {}, "outputs": [], "source": [ "def main():\n", " print(\"\\n๐ŸŽญ Starting article bot with writerโ€“critic LLM loop...\")\n", " graph = build_joke_graph(chat_model_writer,chat_model_critic)\n", " final_state = graph.invoke(\n", " AgenticResearchArticleState(category=\"nlp\",\n", " title=\"Solving the myth and facts of child development with nlp\"), \n", " config={\"recursion_limit\": 1000}\n", " )\n", " print(\"\\nโœ… Done. Final Article Count:\", len(final_state[\"article\"]))" ] }, { "cell_type": "code", "execution_count": 22, "id": "eca50538", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "๐ŸŽญ Starting article bot with writerโ€“critic LLM loop...\n", "๐ŸŽญ Menu | Category: NLP | Articles: 0\n", "--------------------------------------------------\n", "Pick an option\n", "\n", "CATEGORY: NLP\n", "\n", "\n", "\"Solving the myth and facts of child development with nlp\"\n", "\n", "\n", "this study delves into the intersection of natural language processing (nlp) and child development, a promising yet under-explored field. by leveraging advanced nlp techniques, we aim to uncover hidden patterns and insights in vast amounts of data related to child development, debunking common myths and confirming established facts. our research focuses on sentiment analysis of parental interactions, identifying developmental milestones from speech patterns, and understanding the impact of environmental factors on language development. the findings of this study could potentially revolutionize our understanding of child development and pave the way for personalized educational interventions.\n", "\n", "============================================================\n", "๐ŸŽญ Menu | Category: NLP | Articles: 1\n", "--------------------------------------------------\n", "Pick an option\n", "\n", "๐Ÿšช==========================================================๐Ÿšช\n", " GOODBYE!\n", "============================================================\n", "\n", "โœ… Done. Final Article Count: 1\n" ] } ], "source": [ "main()" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "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.9" } }, "nbformat": 4, "nbformat_minor": 5 }