←back to Blog

A Coding Guide to Build a Tool-Calling ReAct Agent Fusing Prolog Logic with Gemini and LangGraph

«`html

A Coding Guide to Build a Tool-Calling ReAct Agent Fusing Prolog Logic with Gemini and LangGraph

Understanding the Target Audience

The target audience for this guide includes software developers, data scientists, and AI researchers interested in integrating symbolic logic with generative AI. They may work in sectors such as technology, finance, and education, where logical reasoning and AI applications are increasingly relevant.

Pain Points

  • Difficulty in combining symbolic reasoning with modern AI techniques.
  • Challenges in implementing logic-based systems in practical applications.
  • Need for efficient tools that facilitate reasoning over complex datasets.

Goals

  • To develop a deeper understanding of Prolog and its applications in AI.
  • To create robust systems that leverage both symbolic and statistical reasoning.
  • To enhance their skill set in using LangChain and Gemini for AI development.

Interests

  • Exploring the intersection of AI and symbolic logic.
  • Hands-on coding and experimentation with AI frameworks.
  • Learning about new technologies and methodologies in AI development.

Communication Preferences

The audience prefers clear, concise, and technical communication. They appreciate well-structured guides that include practical examples and code snippets, allowing them to follow along easily.

Tutorial Overview

This tutorial demonstrates how to fuse symbolic logic with generative AI by setting up a Prolog knowledge base and integrating it with LangChain and Gemini. We will create a ReAct-style agent capable of reasoning over family relationships and performing mathematical operations.

Setup Instructions

To get started, install SWI-Prolog and the necessary Python packages:

!apt-get install swi-prolog -y
!pip install pyswip langchain-google-genai langgraph langchain-core
    

Code Implementation

We load the required libraries and set up the environment:

import os
from pyswip import Prolog
from langchain_google_genai import ChatGoogleGenerativeAI
from langchain_core.messages import HumanMessage
from langchain_core.tools import tool
from langgraph.prebuilt import create_react_agent
import json

GOOGLE_API_KEY = "Use Your Own API Key Here"
os.environ["GOOGLE_API_KEY"] = GOOGLE_API_KEY

llm = ChatGoogleGenerativeAI(model="gemini-1.5-flash", temperature=0)
    

Prolog Interface Class

The following class wraps the Prolog interface, allowing us to load a knowledge base and execute queries:

class AdvancedPrologInterface:
    def __init__(self):
        self.prolog = Prolog()
        self._load_knowledge_base()
    
    def _load_knowledge_base(self):
        """Load comprehensive Prolog knowledge base"""
        rules = [
            "parent(john, mary, alice)",
            "parent(john, mary, bob)",
            "parent(bob, susan, charlie)",
            "parent(alice, david, emma)",
            "parent(charlie, lisa, frank)",
            "male(john)", "male(bob)", "male(david)", "male(charlie)", "male(frank)",
            "female(mary)", "female(alice)", "female(susan)", "female(emma)", "female(lisa)",
            "grandparent(X, Z) :- parent(X, _, Y), parent(Y, _, Z)",
            "sibling(X, Y) :- parent(P1, P2, X), parent(P1, P2, Y), X \\= Y",
            "uncle(X, Y) :- sibling(X, Z), parent(Z, _, Y), male(X)",
            "aunt(X, Y) :- sibling(X, Z), parent(Z, _, Y), female(X)",
            "cousin(X, Y) :- parent(P1, _, X), parent(P2, _, Y), sibling(P1, P2)",
            "factorial(0, 1)",
            "factorial(N, F) :- N > 0, N1 is N - 1, factorial(N1, F1), F is N * F1",
            "list_member(X, [X|_])",
            "list_member(X, [_|T]) :- list_member(X, T)",
            "list_length([], 0)",
            "list_length([_|T], N) :- list_length(T, N1), N is N1 + 1",
            "animal(dog)", "animal(cat)", "animal(whale)", "animal(eagle)",
            "mammal(dog)", "mammal(cat)", "mammal(whale)",
            "bird(eagle)", "bird(sparrow)",
            "can_fly(eagle)", "can_fly(sparrow)",
            "can_swim(whale)", "can_swim(fish)",
            "aquatic_mammal(X) :- mammal(X), can_swim(X)"
        ]
        
        for rule in rules:
            try:
                self.prolog.assertz(rule)
            except Exception as e:
                print(f"Warning: Could not assert rule '{rule}': {e}")
    
    def query(self, query_string):
        """Execute Prolog query and return results"""
        try:
            results = list(self.prolog.query(query_string))
            return results if results else [{"result": "No solutions found"}]
        except Exception as e:
            return [{"error": f"Query failed: {str(e)}"}]
    

Tool Wrapping

We define various tools to interact with the Prolog knowledge base:

@tool
def family_relationships(query: str) -> str:
    """Query family relationships in Prolog format."""
    results = prolog_interface.query(query)
    return json.dumps(results, indent=2)

@tool
def mathematical_operations(operation: str, number: int) -> str:
    """Perform mathematical operations using Prolog."""
    if operation == "factorial":
        query = f"factorial({number}, Result)"
        results = prolog_interface.query(query)
        return json.dumps(results, indent=2)
    else:
        return json.dumps([{"error": f"Operation '{operation}' not supported"}])

@tool
def advanced_queries(query_type: str, entity: str = "") -> str:
    """Perform advanced relationship queries."""
    queries = {
        'all_children': f"parent(_, _, {entity})" if entity else "parent(_, _, X)",
        'all_grandchildren': f"grandparent(_, {entity})" if entity else "grandparent(_, X)",
        'all_siblings': f"sibling({entity}, X)" if entity else "sibling(X, Y)",
        'all_cousins': f"cousin({entity}, X)" if entity else "cousin(X, Y)"
    }
    
    if query_type in queries:
        results = prolog_interface.query(queries[query_type])
        return json.dumps(results, indent=2)
    else:
        return json.dumps([{"error": f"Query type '{query_type}' not supported"}])
    

Agent Creation

We create a ReAct agent and demonstrate its capabilities:

tools = [family_relationships, mathematical_operations, advanced_queries]
agent = create_react_agent(llm, tools)

def run_family_analysis():
    """Comprehensive family relationship analysis"""
    print(" Family Relationship Analysis")
    print("=" * 50)
    
    queries = [
        "Who are all the parents in the family database?",
        "Find all grandparent-grandchild relationships",
        "Show me all the siblings in the family",
        "Who are John and Mary's children?",
        "Calculate the factorial of 6 using Prolog"
    ]
    
    for i, query in enumerate(queries, 1):
        print(f"\n Query {i}: {query}")
        print("-" * 30)
        
        try:
            response = agent.invoke({"messages": [("human", query)]})
            answer = response["messages"][-1].content
            print(f" Response: {answer}")
        except Exception as e:
            print(f" Error: {str(e)}")
    

Conclusion

This tutorial successfully demonstrates the integration of Prolog with generative AI through the use of LangChain and Gemini. By combining symbolic reasoning with advanced AI capabilities, users can create powerful tools for logical analysis and decision-making.

For further exploration, users are encouraged to expand the knowledge base with additional rules and facts, or to adapt the framework for different applications.

Additional Resources

For the complete code and further examples, please refer to the original source material.

«`