Deductive Time Travel – Prolog in the LLM Era – Thanksgiving Special

Welcome to the Prolog in the LLM Era Thanksgiving Special!

Starring … pyswip SWI-Prolog … the Semantic Web … data mesh … and … special guest star, ChatGPT!

Notes:

  • This blog is best consumed by first reading at least Part 1 of the series (preferably the first 3 parts): Prolog in the LLM Era – Part 1
  • This blog is kind of chatty because I want to remind my architect friends to recognize and value the expertise held by all knowledge workers. It’s a counter-flow approach: instead of the single direction of AI feeding decisions down to people, it’s about knowledge workers (far out-numbering analysts and managers) contributing their unique insights and perspectives back into AI. We need to be cognizant of remaining in control. If the masses of us have nothing to contribute in terms of our voices, we’ve lost most of our agency. The direction of focusing on “better and better” ways of utilizing AI is a slippery slope to pure individual complacency—which is a dangerous thing.
  • This blog series, Prolog in the LLM Era, is designed to convey key considerations and potential applications for Prolog within AI and knowledge-driven environments. Prolog, as a factored subset of broader code logic, can be scaled out more easily than more complex systems. However, this series does not aim to provide a blueprint for building a fully optimized Prolog server. Developing a Prolog server with the sophistication of platforms like SQL Server, Oracle, or SSAS is beyond the scope of this series.

Abstract (TL;DR)

Time travel in data is about understanding the context behind decisions of the past, enabling us to apply historical solutions more effectively to today’s challenges. Prolog, as a soft-coded logic system, allows for a separation of logic from procedural code, creating “time-traveling” rule snapshots that evolve independently of execution. This approach preserves decision rules in historical form, much like data warehousing and ML model versioning capture snapshots of data, guiding us with insights from prior contexts.

Integrating Prolog with Large Language Models (LLMs) as well as Knowledge Graphs (KGs) enhances the adaptability and context-awareness of AI systems by combining historical patterns with real-time data. This results in a robust foundation for decision-making that can dynamically incorporate the lessons of the past, shaping a resilient, contextually-grounded AI approach for modern enterprises.

Prologue

Practically every statement made by some sort of consultant could start with, “It depends”. Answers depend on the context, goals, resources, constraints, and a whole lot more.

What a super power it would be for a consultant of any type, if they could travel back in time and be fully immersed in the context that led to the success or failure of past decisions. With firsthand exposure to the motivations, pressures, and limitations faced by decision-makers of the time, they would gain an unparalleled wisdom of why certain choices were made, why some strategies thrived while others fell short, and how real-world challenges influenced each outcome. This depth of insight would go beyond what historical records or case studies alone can offer, revealing the subtle factors—like unspoken cultural norms, tacit knowledge, or the influence of emerging technologies—that drove decisions in ways we might overlook today, and thus lead to unexpected, bad outcomes.

Armed with this contextual awareness, a consultant could identify patterns, avoid pitfalls, and apply timeless lessons to create more adaptable and resilient solutions for today’s complex challenges. They could bring an enriched perspective, not just on what worked or didn’t, but on why it did or didn’t—enabling them to craft solutions with a depth and nuance that mere data or hindsight often fail to provide.

AI today plays the role of a consultant—beyond a glorified search engine. For an AI, being exposed to rules authored by a variety of experts knowledge workers within their historical context would be transformative. These expert-authored (or AI-assisted) rules would serve as distilled snapshots of knowledge, encoded with the assumptions, priorities, and limitations of their time and place. By learning from these contextually rich rules, the AI could develop a layered understanding of how experts approached problems under specific conditions, including factors that may no longer be obvious today.

This exposure would enable the AI to not only mimic past decisions but also discern patterns in reasoning across different eras, highlighting how changing contexts shaped expert judgment. Such an AI could, for example, detect when modern circumstances closely parallel past situations and offer insights that integrate historical solutions with current knowledge. Additionally, by understanding the constraints that informed older rules—such as resource limitations, societal norms, or technological boundaries—the AI could more effectively adapt to similar constraints in new situations.

Ultimately, this would result in an AI that isn’t just reactively predictive but strategically aware, drawing on historical wisdom, that was purposefully encoded by experts, to generate solutions that are forged from real-world experience, context-sensitive, and capable of bridging past insights with present-day challenges. This ability to carry forward the depth and nuance of expert thinking across time could allow the AI to support consultants, analysts, and decision-makers with unprecedented depth, crafting solutions that honor the complexities of both past and present.

History and Learning

History is the foundation of meaningful learning, the source from which true understanding emerges. Without history, learning is a meaningless word. That’s literally true for machine learning (ML), which trains models off historic data. The alternative is programming—dictating sets of explicit instructions without depth and context.

Genuine learning involves more than just sequences of data, rules, and commands; it includes what we’re taught and, just as importantly, what we experience. It’s a vast tapestry of motivations, assumptions, laws, and contexts. This rich complexity allows us to create, understand, and think beyond the boundaries of pre-defined tasks.

In contrast, training is a streamlined process. Focused and efficient, it’s based on carefully cleansed data, curated and honed for specific goals. The world from which this data is drawn is stripped of its complexity, abstracted down to fit the needs of a particular task. Feedback loops may guide this process, but only within the constraints of simplified, predictable conditions. Training serves a purpose, but it excludes the intricate maze of historical connections—the correlations and cycles that history reveals to those who look beyond surface patterns.

Therefore, a history of structures richer than what our cleansed and modeled databases hold is essential. In these raw, interconnected webs are the patterns and cycles from which we learn not just how to act, but how to understand. And it’s here that Prolog, as a bridge between the older and current AI worlds, finds its strength, allowing us to tap into fundamental truths woven through the fabric of history, beyond the limits of any structured database.

Time Travel

Time travel, in this context, is about immersing ourselves in the circumstances and constraints that shaped past decisions. Even if history doesn’t exactly repeat, guidance from the past remains our richest source of learning. If history didn’t mostly repeat—or at least rhyme, as Mark Twain may have said—then much of what we learn in school and in machine learning would be reduced to repetitive training exercises, applying patterns without the benefit of deeper historical context. But with true historical immersion, we gain the ability to apply past solutions with greater confidence, understanding not only what worked but also why it worked.

When we look to the past, we examine decisions made in response to the questions of the time and the outcomes they produced. Most questions we ask today have likely been asked in some form before. Some are esoteric and rare, posed by generals, physicists, or inventors throughout history, while others are universal questions we ask billions of times every day: “What can I eat?” or “Can I safely cross the street?”

Though many questions remain the same over time, the answers vary greatly depending on the era’s context. An answer reached ten years ago may or may not hold up in hindsight. As successful as a past answer may have been (or, conversely, as tragic), there’s no guarantee it will work (or fail) today.

In essence, time travel lets us examine the broader state of data as it existed in a specific historical moment, offering insights into the context that shaped past decisions. This contextual understanding doesn’t necessarily justify the choices made, but it helps us understand why they were made within their unique circumstances. With this richer perspective, we can adapt past solutions with a clearer sense of how they might apply—or require adjustment—today.

Separation of Logic and Procedure

When I wrote SCL (Soft-Coded Logic, my Prolog variant) back in 2004, its tagline was “separation of logic and procedure.” The hard-coded conditional logic of if-then clauses (ex. goal > price) could be treated as calls to a Prolog engine, which could merge Prolog logic, dynamically applying it to the terms in the conditional. That is the soft-coded logic. This separation allowed logic to evolve independently of the code that executed it (the .EXE files compiled from C# and Java code).

Circa 2004, this idea was influenced by XSLT’s concept of separating data from presentation (formally known as separation of content and presentation). The value is the presentation and transformation rules could be preserved data is updated or vice versa. This same approach could be extended by applying Prolog to different contexts, like varying geographies or organizational structures.

Fast-forward to today, where “time travel” is now a fundamental concept in cloud-scale database management. Delta Lake in Databricks, for instance, enables database time travel, which is also a key benefit of the Data Vault approach.

Similarly, model versioning is now standard practice in ML. Platforms like MLflow make it easy to track which model version made a prediction, including its input and hyperparameters. For example, a model approving a home loan in 2008 made its decision based on 2008’s lending rules, which would differ significantly from 2024’s.

Because logic technologies such as Prolog and Rules Engines had been implemented relatively rarely across the broad enterprise world, most rules had been hard-coded as software written in languages such as COBOL, C++, and Java. At best, constants were soft-coded into some sort of “config file”. But if the actual rule changed (not just the terms of the rule), that became part of an update project.

With reasonable feasibility, we can save the history of ML model versions because, byte-wise, they’re relatively small—in the neighborhood of less than a KB to thousands of KBs. But large language models (LLMs), like GPT-4, are relatively immense—for example, GPT-4 typically occupies hundreds of gigabytes, depending on optimizations. Further, because training LLMs is very time-consuming and costly, they are infrequently updated. But other sorts of ML models (putting aside LLMs) are easier to train and so are usually re-trained more frequently—sometimes less than a day timeframe.

LLMs respond to queries based on a wide range of parameters (strings of natural language text), and the context window alone can be vast. OpenAI offers access to earlier versions of GPT, generally for the purpose of lower cost. But there can be use cases where it’s crucial to clarify if a model’s response differs over time due to better data, improved algorithms, more training data, or a shift in contextual knowledge.

Therefore, isolating logic in the form of Prolog creates a system that is not only adaptable but also historically anchored. By maintaining each Prolog rule set as a standalone snapshot of decision criteria, we can effectively “time travel” through past logics, revisiting the precise rules and contexts that shaped decisions at any given point. This separation allows us to adapt by choosing the most relevant historical logic to apply today, without rewriting or distorting the underlying code.

In this way, Prolog doesn’t just evolve with us; it allows us to adapt by consulting the past on demand, offering a unique blend of flexibility and historical fidelity that traditional, hard-coded systems lack. In a constantly changing environment, a soft-coded, time-traveling logic foundation like Prolog is a powerful strategic tool.

Prolog Snippets

In my book, Enterprise Intelligence, a major topic is the creation and maintenance of a Knowledge Graph (KG) in a distributed manner. The KG’s value lies in its role as a knowledge base built by people (today with LLM assistance), acting as a reality check for algorithmically trained LLMs.

While this approach of a symbiotic relationship between KGs and LLMs is widely recognized today, I also advocate for developing and managing the KG using a data mesh framework. Originally intended for building an enterprise semantic layer in a distributed fashion, the data mesh framework distributes the development and maintenance by domain, thus avoiding the bottlenecks and inherent overwhelming complexity of monolithic projects.

This blog suggests extending the data mesh approach to enterprise logic. That is, the authoring of expert rules in a distributed fashion, across the many subject matter experts across a wide breadth of domains, and across time.

Here, the granularity can go beyond domains to finer levels, such as by function (similar to microservices or ML models), by subject matter expert (capturing each expert’s perspective), or by specific entities like customers, partners, or regulatory bodies. I refer to each of these elements as “Prolog Snippets.”

Prolog is a declarative language, like SQL, which means it focuses on defining what needs to be true rather than how to achieve it. This approach contrasts with imperative languages like C++, Python, or Java, where the code specifies each step of execution. Declarative languages allow the system to derive answers by reasoning over the relationships between facts and rules, rather than following a sequence of commands. Prolog, for instance, allows us to state a set of conditions or relationships (rules and facts) and then ask questions against this logical framework. This makes Prolog especially suitable for expressing complex logic that doesn’t need to be executed in a linear or state-dependent manner.

Because Prolog rules are inherently stateless, they align well with a microservices-like architecture, where each Prolog Snippet acts as an independent, self-contained rule set. However, unlike traditional microservices, Prolog doesn’t follow a strictly functional approach. Instead of acting as standalone functions that deliver a single result, Prolog can reference external “metafacts” and “metarules” (as I discuss in Prolog AI Agents) to dynamically adjust its logic based on context. This makes Prolog adaptable to a distributed knowledge graph model, where different Prolog Snippets may draw on domain-specific data or logic, simulating a sort of “intelligent” microservice that evolves with its context.

If Prolog is implemented in this loosely-coupled, declarative way—following the data mesh principles and integrated in a microservices-like framework—tracking and revisiting the Prolog rules active at any point in time becomes feasible. This approach would allow us to observe the logic that governed decisions in the past and capture valuable historical insights that inform the Knowledge Graph and enterprise-wide intelligence.

Data Warehouses Pioneered Storing a History of Data – Data Memory

For decades, the craft of data warehousing (DW) has been the state of the art in the storage of massive volumes of historic data in a structured, highly-queryable manner. Here are a few notes on how DW and BI are about history:

Before the maturity of DW/BI, OLTP applications would have, say, six months of “history”. Hardware to store and retrieve extensive histories were too expensive for what could be very many concurrent users.

  • DW/BI emphasized the querying of high-volumes of data for a relatively low number of concurrent analysts. Millions to many billions of facts (sales, web page clicks, patients visits, stock quotes, etc.) could be queried within a reasonable timeframe—sub-second to a few minutes, as opposed to many minutes to hours.
  • The notions of slowly-changing dimensions (SCD Type 2) enabled the storage of object histories as well as extensive fact history. For example, a detailed record of every attribute changes for customers as well as a complete history of sales. The alternative to SCD Type 2 is to simply overwrite the old value with the new value—which is SCD Type 1.
    • Note that for the data vault methodology, roughly speaking, all objects are by default SCD.

That DW/BI data is highly-curated and highly-structured. That is, as opposed to massive volumes of unstructured data that is difficult to easily query—for example, the dump of all those photos from your cellphone cameras over the past couple of decades.

Today’s AI can easily extract structured data from unstructured data, such as pictures. It can identify many of the objects in each of those pictures, even down to specific places, people, and symbols of all sorts (such as brand logos, text, and iconic places and objects). It can even generate a summary of the picture as a whole. For example, “A view of a busy 7-11 parking lot in a suburban area.”

But these are just statements of fact, data about the picture. What about why people attend something like a baseball game or that there is such a thing as a stadium where thousands of people congregate? Today’s AI such as ChatGPT is capable of inferring treatises on such questions having been trained on the corpus of our human writings.

That’s excellent. But anything derived from AI today is just a hypothesis based on assumptions that are in turn based on sometimes questionable text open to interpretation. The AI (currently) has no direct connection to the real world. In fact, it only recently has easy access to the Internet to test its hypotheses. Virtually every query issued to an LLM by the average consumer is a glorified Google search (at least what we’re used to since the late 1990s).

A history of Prolog versions is much richer than a history of data. Back in the 1980s, painstakingly hand-authored Prolog code made up what were called “expert systems”. It was intended to capture and reflect the expertise of experts in a field. Data itself, whether it’s in a SQL Server database or a photograph, doesn’t capture the expertise of experts. Whatever might seem beyond cold, hard facts is just captured craftsmanship of the programmers.

Now those “expert systems” were pretty crappy. The Prolog comprising it was authored by experts of a domain, but it was just the periphery of the broader set of knowledge encased in the brains of those experts. I thought at the time that encoding expert knowledge in Prolog is about as difficult as encoding it as a book. But such books, even the best of them, are difficult for anyone to fully digest. So if humans would be challenged digesting expertise in such books, gaining the ability to apply that expertise, it’s that much tougher for dumb software that does exactly what we program it to do with mathematically impeccable accuracy (which is ironically what we want) from software).

However, the LLMs of today can supplement the expertise of human experts purposefully encoded in Prolog. It provides the vast matrix of background knowledge and a useful level of understanding from which the expertise emerged.

But, but, but … the LLMs have probably been trained with volumes of books written by experts. Isn’t that the same thing? Not quite. The predictive nature of LLMs is such that they famously “just predict the next word” (as oversimplified as that is to say) and even “hallucinate”. Natural language is very flexible, thus ambiguous. That’s a good thing. Our brains are a flexible cascading translator, not a compiler.

In Part 7 of “Prolog in the LLM Era” I discussed how Prolog and/or KGs complement LLMs by providing a deterministic human-vetted counterpart to the LLM’s predictive nature.

Twenty or thirty years ago, before the quality of LLMs today, the big advantage of Prolog was that it is machine-readable and pretty much human-readable—the same argument XML made 20 years ago in terms of data.

  • Books, even articles, don’t lend themselves well to frequent updates. Prolog can be authored and rolled out in a CI/CD manner.
  • Books contain the knowledge of one to a few experts, while there may be thousands in the world, with old ones retiring and new ones coming onto the scene.
  • Books are bound by scope. No domain of expertise lives in a vacuum. So the knowledge in a book must be complemented with a mechanism for supplemental knowledge. Kind of like references of a book, or hyperlinks in an electronic version.

Experts have built their knowledge on the foundation laid their predecessors across a web of adjacent domains, spanning across time and contexts. Over their careers, they’ve built upon and evolved that knowledge in the real world where its validity is ruthlessly tested.

Video taken from a surveillance camera is really the history of a chunk of 3D space. Each frame contains the state of the 3D space at some instant of time. But each frame, even the series of frames as a whole, are just a snapshot of that time and space. In fact, “snapshot” is the term we use in data warehousing to summarize what the data space looked like at some point in time.

Prolog Example – Rule Memory

Here is an example of two Prolog snippets, the second superseding the first, that reflects the thinking of diagnosing an ulcer a few decades ago versus today.

Although I’ve stressed that the idea is for Prolog to be authored by human experts, these two examples were “authored” by ChatGPT. I’m not an expert at anything beyond coding and business intelligence, so I asked for its help to develop something relatable to most even though it’s out of bounds for me to offer expert guidance.

In this case, the topic is diagnosing ulcers. This is a good example of engaging an AI to work alongside people to craft Prolog. As it would be for building conventional software or even knowledge graphs, I imagine a similarly cross-functional team of subject matter experts (doctors in this case), Prolog experts (ontological experts is the KG counterpart) who can encode the SME rules, and stakeholders (the administration accountable for the performance of the healthcare system).

This example illustrates:

  • An older and newer version of Prolog rules for the same problem.
  • Metadata such as the author(s), the effective date range of the rules, etc.
  • Attributes tags used to “index” the Prolog as LLM embeddings. For example, a summary, descriptions of predicates, and a glossary of terms.

Disclaimer: I nor ChatGPT are doctors. This example is just for demo purposes.

In the past, coronary artery disease (CAD) was thought to be caused primarily by stress, diet, and lifestyle, without the biomarker-based understanding we have today.

Example 1: Original Prolog for Diagnosing CAD

The following Prolog, the first of the two, encodes the rules for diagnosing CAD. Prolog snippets could represent rules for a healthcare organization or many individual doctors each with their own opinions.

Each Prolog history could store metadata such as the activation date, the date it was superseded, a summary, an embedding generated from that summary, and a list of predicates. This summary could be generated by an LLM from the Prolog rules themselves, especially if the rules are annotated with metadata.

Subject Matter Experts: Dr. Bret Payne
Coders: Dr. Bret Payne
Scope: Opinion of Skynet Healthcare
Date Activated: 11-02-2005
Date Superseded: 12-08-2006
Summary: These predicates reflect the focus on lifestyle in coronary artery disease (CAD) diagnosis.

Predicates:

— symptom/2: Defines CAD symptoms with severity.
— lifestyle_factor/2: Defines lifestyle factors relevant to diagnosis.
— diagnosis/1: Confirms CAD diagnosis based on outdated criteria.
— CAD/0: Activates diagnosis based on symptoms and stress factors.

Usage Context: Historical reference for CAD diagnosis before biomarker understanding; educational contexts in medical history.

Rule: Symptom – chest_pain
Codes: ICD-10: R07.9, IRI: https://example.org/chest_pain
Description: Checks for chest pain, a common symptom in CAD diagnosis, historically attributed to stress or diet.

Rule: Lifestyle Factor – high_stress_levels
Description: Checks for high stress levels, once thought to cause CAD. Embedding for historical diagnostic reasoning tied to stress.

*/

% Input Variables: Symptoms observed in 1955
symptom(patient, chest_pain).
symptom(patient, fatigue).
symptom(patient, shortness_of_breath).

% 1955 Diagnosis for coronary artery disease (CAD).
possible_diagnosis(patient, CAD) :-
symptom(patient, chest_pain),
symptom(patient, shortness_of_breath),
symptom(patient, fatigue).

% Treatment Recommendation (1955)
treatment(patient, rest_and_diet) :- possible_diagnosis(patient, CAD).

Prolog snippets are functions in the same way as ML models are functions. They take inputs and output something. In this case, the inputs are:

  • symptoms – chest pain and shortness of breath.
  • lifestyle – high stress and dietary habits.

These metadata (summary, comments, descriptions, etc.) could then be converted into embeddings, which are compact numerical representations of the data’s meaning and context. Embeddings allow for efficient similarity searching, as each one captures the essence of the metadata in a way that can be compared against other embeddings. They can be stored in a vector database for use in Retrieval Augmented Generation (RAG) processes, where similar past data can be quickly retrieved, or used to fine-tune a foundation LLM, enhancing its understanding of historical context and rule logic.

Metadata in Example 1

Here is a list of explanations of the metadata as illustrated in Example 1 above:

  • Subject Matter Experts: Lists the experts who provided domain-specific knowledge to inform the rules. This helps establish the credibility and source of the rule logic.
  • Coders: Indicates the individuals responsible for coding the Prolog rule, distinguishing between domain expertise and technical implementation.
  • Scope: Describes the intended application or organizational context for the rule set, clarifying its relevance or limitations.
  • Date Activated: The date when the rule set was implemented or made active, providing a historical reference for when this knowledge was applied.
  • Date Superseded: The date when this rule set was replaced or updated, indicating the timeframe within which the rules were in effect.
  • Summary: A brief overview of the rule set’s purpose and key points, capturing the main focus or emphasis of the rule (such as specific symptoms or factors considered).
  • Predicates: Lists and briefly describes each predicate, outlining its role in the rule logic. For example, predicates might define symptoms, factors, or diagnosis triggers.
    • Note that for the chest_pain predicate, there is the tag, “Codes”. This is a list of codes that map the predicate to some sort of external source. For example, chest_pain maps to the ICD-10 code, R07.9. Additionally, an IRI (International Resource Identifier) that maps it to an ontology/taxonomy of the Semantic Web world.
  • Usage Context: Specifies the intended use or applicable contexts, such as historical, educational, or specific industry settings. This helps users understand the context in which the rules are relevant.
  • Rule Descriptions: Provides descriptions for individual rules, explaining the purpose of each rule or condition within the Prolog logic.
  • Input Variables: Lists the variables required as inputs, specifying data or conditions that need to be present for the rule to operate effectively.

Example 2 – Updated Prolog for Diagnosing CAD

The following Prolog represents a newer way to diagnose and treat CAD. With the establishment of LDL as a biomarker in later years, medical understanding shifted, and cholesterol levels became the primary focus. However, let’s say it took the healthcare system a few years to fully integrate this idea, so it wasn’t implemented until later.

/*

Subject Matter Experts: Dr. H. Lori, Dr. Mark Twain
Coders: Eugene Asahara, ChatGPT
Date Activated: 12-09-2006 Date Superseded: TBD
Summary: Reflects biomarker-based diagnosis of CAD, useful in contexts of updated health diagnostics, patient history tracking, and cardiovascular health studies.

Predicates:

–symptom/2: Defines symptoms typical of CAD.
–condition/2: Defines relevant biomarker conditions.
–diagnosis/1: Confirms CAD diagnosis based on modern criteria.
–CAD/0: Activates diagnosis if high LDL and symptoms are present.

Usage Context: Modern diagnostic framework for CAD, useful in clinical diagnosis or medical history education.

% Rule: Condition – high_ldl % Description: Confirms the presence of high LDL, now understood to be a primary indicator of CAD risk. Embedding useful for cardiovascular health diagnostics.

*/

% Modern symptoms with available biomarkers (LDL levels)
symptom(patient, chest_pain).
symptom(patient, fatigue).
symptom(patient, shortness_of_breath).
biomarker(patient, ldl, high).

% Modern Diagnosis for coronary artery disease (CAD) with High LDL
possible_diagnosis(patient, CAD) :-
symptom(patient, chest_pain),
symptom(patient, shortness_of_breath),
biomarker(patient, ldl, high).

% Modern Treatment Recommendation treatment(patient, statins) :-
possible_diagnosis(patient, CAD),
biomarker(patient, ldl, high).

In this case, the newer one reflects a new scientifically derived way of thinking. In other cases, updated rules might reflect changes based on the whims of whoever is in charge.

Testing the Prolog Time Travel

Below is a prompt demonstrating how an LLM (ChatGPT) could be used to time travel. Although I’m using ChatGPT—in the way a human interacts with an LLM—for demo purposes, think of this as part of a RAG process where the RAG coordinator is engaging an LLM as a Prolog interpreter.

Based solely on this Prolog that reflects the thinking of heart conditions back in 1955, what diagnosis and treatment would you recommend:


% Symptoms observed by the patient.
symptom(patient, chest_pain).
symptom(patient, fatigue).
symptom(patient, shortness_of_breath).


% 1955 Diagnosis for Heart Condition
possible_diagnosis(patient, heart_condition) :-
symptom(patient, chest_pain),
symptom(patient, shortness_of_breath),
symptom(patient, fatigue).


% Treatment Recommendation (1955)
treatment(patient, rest_and_diet) :- possible_diagnosis(patient, heart_condition).

Here is the response from ChatGPT:

Based on this Prolog script from 1955, here’s the diagnosis and recommended treatment:

Diagnosis

Heart Condition: Given the combination of symptoms — chest pain, fatigue, and shortness of breath — the script identifies the patient as potentially having a heart condition.

Treatment Recommendation

Rest and Diet: The recommended treatment for a heart condition in 1955 is rest and diet. This would likely include physical rest to avoid straining the heart and a controlled diet to support cardiovascular health, probably low in saturated fats and cholesterol to reduce the risk of worsening the condition.

While this approach aligns with medical practices of the 1950s, modern treatments for heart conditions might include a range of additional interventions, such as medications (e.g., beta-blockers, ACE inhibitors) or procedures (e.g., stenting) depending on the specific type and severity of the heart condition.

Now, let’s use the Prolog that implements the current rules:

Based solely on this Prolog that reflects the current thinking of heart conditions, what diagnosis and treatment would you recommend:

% Modern symptoms exhibited by a patient, with available biomarkers (LDL levels)
symptom(patient, chest_pain).
symptom(patient, fatigue).
symptom(patient, shortness_of_breath).
biomarker(patient, ldl, high).


% Modern Diagnosis for Heart Condition with High LDL
possible_diagnosis(patient, heart_disease) :-
symptom(patient, chest_pain),
symptom(patient, shortness_of_breath),
biomarker(patient, ldl, high).


% Modern Treatment Recommendation
treatment(patient, statins) :-
possible_diagnosis(patient, heart_disease),
biomarker(patient, ldl, high).

This is the diagnosis and treatment based on modern criteria (again, this is just for demo purposes):

Based on this modern Prolog script, here’s the diagnosis and recommended treatment:

Diagnosis

Heart Disease: The updated criteria here indicate that if the patient has chest pain, shortness of breath, and a high LDL (low-density lipoprotein) biomarker level, a diagnosis of heart disease is likely. This reflects the modern understanding that high LDL is a key risk factor for cardiovascular issues.

Treatment Recommendation

Statins: Given the diagnosis of heart disease with high LDL, the recommended treatment is statins. Statins are a class of drugs used to lower cholesterol levels, particularly LDL, by inhibiting the enzyme HMG-CoA reductase, which is involved in cholesterol production in the liver. Statins are commonly prescribed today to reduce LDL levels, aiming to decrease the risk of heart attack and other cardiovascular events.
This approach aligns with modern cardiovascular treatment strategies, which often include lifestyle modifications (diet and exercise) and medication (e.g., statins) to manage cholesterol levels and reduce cardiovascular risk.

Prolog Version History

Since Prolog is code, it makes sense that it might be housed in a code repository such as GitHub, where each version is naturally maintained. GitHub should be a convenient, almost ubiquitous, solution for storing thousands of versions of thousands of Prolog documents (which is relatively small).

But GitHub is pretty much just a repository with history. Coders generally use that history to roll back changes in case their updates are really screwed up. That’s the same for writers using the history features built into Word and other content creation software.

As a coder and content creator, I’ve rarely looked at earlier versions of code to discover what the outdated code did or what a Word document expressed some time ago. I’m generally only concerned with current requirements. The look at older versions to see what changes lead to a bug I’m troubleshooting, but I very rarely care about why. I just want to fix my bug.

What about consumers (end-users) of the software? In the role of consumer, they are not programmers or content creators, so they won’t be rolling back or looking to an older version to prove they had a novel thought before someone else. Frankly, I don’t think there is any compelling widespread use case for consumers of software to peruse a history of code.

Those involved with analytics are a kind of consumer—consumers of data. Unlike typical consumers of software, analytics consumers are involved with decisions making—directly or indirectly by providing intel to managers, executives, and other decision makers.

Strategic decision makers are part historian. They look to past decisions made by others for guidance. But decisions made by others in the past were made under different circumstances. What might have lead to good outcomes in the past might not fare well today—and vice-versa.

A history of all Prolog code provides a rich context at some given time. What were the rules in play at some time? Not just for a Prolog diagnosing ulcers or heart issues, but what:

  • Was the political environment?
  • Was the technical state of the art?
  • Were the fads at play?
  • Were the tools and insights we take for granted today?

Human and AI analytics consumers would utilize the history of Prolog code the way that a human advisor, deeply well-versed with history, would ingest hundreds if not thousands of volumes of books.

Implementation at Scale

There are two primary ways to deploy and query Prolog:

  1. Prompt Engineering in a Retrieval Augmented Generation system: Prolog could be embedded into a call to an LLM as explicit rules.
  2. Calls to a Prolog Engine: This is the conventional way Prolog is engaged. A Prolog query is submitted and an answer is returned.

A detailed discussion of implementation is a hefty book in itself. For this humble blog, I will briefly discuss the ideas.

Prompt Engineering in a RAG System

The Prolog examples above already demonstrated this method of infusing Prolog into LLM prompts. The advantage of resolving Prolog by embedding it into an LLM prompt is that it avoids having to deploy a “Prolog Server”—yet another server. Additionally, I imagine any reader of this blog series has already or is in the middle of deploying RAG systems, so it’s easy to implement Prolog rules in this manner.

I need to reiterate here that the advantage of coding expert knowledge as Prolog is that it is encoded in an explicit manner. Encoding rules as natural language (i.e. writing an article or book) is always ambiguous. The value is that the explicit encoded knowledge acts as a reality-check for the predictive nature of LLM responses.

In the examples above, ChatGPT didn’t process the Prolog with a Prolog engine. Rather, it is capable of parsing Prolog in the same way it parses and interprets any other code such as Python and SQL.

Another advantage of this method is that the LLM can readily digest the explicit rules encoded in Prolog with its vast knowledge trained from terabytes of our written knowledge.

In the prompts of the Prolog examples, I began my prompt with: “Based solely on this Prolog …” Now, that doesn’t guarantee the LLM will listen. Over the past few months I’ve issued similar prompts many times and it does seem to listen fairly well. For extra good measure, I sometimes add to the prompt, “If you return the wrong answer, I will lose my job and my wife will leave me, and you are to blame.” Ha!

The disadvantage are:

  • We can’t be sure we’ll receive a deterministic answer. Most of the point of Prolog (or Knowledge Graphs) is that it is explicit.
  • A direct call to Prolog would usually be faster than processing through the whole LLM architecture.

Vector Database

For each Prolog snippet, we capture and store specific metadata attributes that provide essential context, such as a summary, list of rules, effective date, and a unique URL linking to the Prolog source. This metadata is pivotal not only for documenting each Prolog rule’s purpose and context but also for building embeddings that encode the historical and domain-specific knowledge represented by each snippet.

Creating Embeddings for Vector Storage:

  1. Generating Embeddings from Metadata and Summaries: Each Prolog snippet’s metadata is converted into one or more embeddings. Embeddings represent the snippet’s summary, rules, effective date, and other essential properties in a numerical format, capturing the relationships between its concepts. Embedding models (such as sentence-transformers) can process the snippet’s summary and detailed metadata, creating representations that are semantically rich and suitable for quick, context-aware retrieval.
  2. Storing Embeddings with Metadata in a Vector Database: These embeddings, along with their associated metadata (effective date, Prolog URL, and specific identifiers for the rules and logic), are stored in a vector database. A vector database enables efficient retrieval of relevant embeddings based on similarity queries, allowing us to locate historical versions of Prolog rules or summaries that best match a specific context or query.
  3. Version Control and Retrieval: By including the effective date and other identifiers as searchable metadata, this vector database enables a form of “time travel” for Prolog rules. Users or applications can query the vector database not only for specific logical functions or summaries but also by time frame, helping to reconstruct the historical context of a decision or rule. For example, an analyst can retrieve the specific Prolog rules that were in effect on a given date, comparing the logic and understanding of that time against current interpretations.

Fine-Tuning the Text for an LLM

In addition to storing Prolog metadata and summaries as embeddings, the entire catalog and history of the Prolog itself can also be used to fine-tune a large language model (LLM). Fine-tuning with the catalog of Prolog lets the LLM incorporate specialized domain knowledge, providing responses that reflect historical context and nuanced understanding of expert-encoded rules. This fine-tuning allows the LLM to generate responses that align not only with present-day understanding but also with the logic and knowledge prevalent at different points in time.

Your passage makes sense conceptually, but it could benefit from slight rewording to clarify some nuanced points and improve readability. Here’s a refined version with adjustments for clarity and accuracy:


Together, fine-tuning and a separate, updated data source (e.g., a vector database) create an advanced query assistant. Fine-tuning provides the LLM with context-sensitive insights by embedding knowledge of Prolog’s historical evolution, while the vector database ensures access to dynamically updated logic. This combination enables the LLM to mimic an expert familiar with the evolution of domain-specific logic, offering deeper, interpretive responses that integrate both historical and actively maintained rule-based content.

However, while fine-tuning an LLM with Prolog rules enhances its familiarity with domain-specific knowledge, there are notable limitations:

  1. The LLM Can’t Execute Prolog Natively: Fine-tuning an LLM with Prolog rules enriches its understanding of the logic and history encoded by SMEs, but it doesn’t equip the LLM to directly solve Prolog queries. While LLMs like ChatGPT may understand Prolog syntax and reasoning patterns when provided in prompts, they don’t execute Prolog code or reason in the same procedural manner as a Prolog interpreter. Instead, they can simulate reasoning by following encoded logic “in their heads” based on the information presented in the query.
  2. Lack of Real-Time Updates: Fine-tuning alone does not enable the LLM to adapt to ongoing updates in Prolog rules or knowledge in real time. To incorporate the most current logic, Prolog knowledge must be dynamically retrieved at query time, such as through a Retrieval Augmented Generation (RAG) process or another integration mechanism, ensuring access to up-to-date content.

A Prolog Server

Of course, any enterprise system must be deployed and utilized at scale. I’ve researched whether “off the shelf” Prolog systems exist that provide built-in distributed execution across multiple nodes.

Unfortunately, I haven’t found a suitable one. That doesn’t mean one doesn’t exist—a company could be in “stealth mode” with an unreleased product, or it may be that I didn’t search exhaustively.

At present, some Prolog implementations (e.g., SWI-Prolog and SICStus Prolog) offer multi-threaded and memory-efficient environments that can be deployed in clusters. In fact, it’s possible to implement a distributed Prolog architecture using SWI-Prolog, relying on a cluster architecture with each node running multiple Prolog threads that can handle concurrent queries. This setup can distribute workloads across nodes, but it doesn’t offer the optimized, load-balanced experience of a true “at-scale” Prolog server.

When I built the SCL Engine (Soft-Coded Logic Engine) years ago, I architected a rudimentary multi-threaded solution that was adequate for demonstration purposes. But that was a much simpler system and from a completely different technological era (2004-2007ish).

The big challenge with scaling Prolog is that its query times can be quite unpredictable, unlike many ML models we’re accustomed to—like recommendation systems, market basket analyses, etc.—which can be deployed in highly concurrent environments with thousands to millions of sessions. Prolog logic, especially with complex rules and recursive queries, can become significantly more complicated than many types of ML models, even ensemble models.

Creating a truly scalable Prolog server is a complex endeavor. It would require mechanisms to handle unpredictable query times, prioritize different types of Prolog logic (such as balancing shorter and longer queries), and dynamically manage dependencies. Just as high-scale SQL servers have built-in functionality for prioritizing query types, an at-scale Prolog server would need similar optimization, with advanced load balancing and possibly task preemption to handle complex recursive or interdependent logic queries.

In lieu of such a dedicated Prolog server, a somewhat scalable solution can still be achieved by partitioning lighter, stateless Prolog snippets from more complex, stateful ones:

  • Light, Stateless Prolog: Smaller Prolog rules, without query-time dependencies or imports, can run on stateless infrastructure like Azure Functions or AWS Lambda. These environments are highly scalable and can handle simpler Prolog queries concurrently and efficiently.
  • Clustered Approach for Complex Prolog: A more complex Prolog setup that requires importing additional rules at query time, or that involves intensive recursion, may not fit a serverless model. Instead, a clustered environment using SWI-Prolog or a similar implementation can still provide a multi-threaded, distributed setup, where nodes work together to handle concurrent, heavier Prolog queries.

The foundation for a scalable Prolog system exists in cloud-based clustering and stateless serverless infrastructure, both of which draw on established architecture principles. In the next section, I’ll outline a high-level architecture for the setup of a simple cluster of Prolog resolvers—a framework familiar to those experienced with Azure and AWS.

Prolog Cluster

With today’s distributed cloud services, setting up a scalable Prolog cluster architecture becomes achievable by coordinating the distribution and aggregation of Prolog calls across nodes. Here’s how this setup can work effectively with existing cloud resources:

  • Distributed Prolog Execution: Each Prolog call is managed by a cluster of SWI-Prolog instances running in multi-threaded mode on cloud platforms like AWS, Azure, or Google Cloud. Services like AWS ECS (Elastic Container Service) or Kubernetes (on any major cloud provider) can host these SWI-Prolog instances across multiple nodes, dynamically scaling the cluster as demand fluctuates. SWI-Prolog’s multi-threading capabilities make it particularly suitable for this architecture, allowing high performance and concurrency within each instance.
    • Chances are that the storage requirements for all Prolog across history would be within the magnitude of a few GBs. That means the Prolog likely could be feasibly replicated to all nodes in the cluster. Even if not all, most could be cached in each node.
  • Load Balancing and Coordination: A load balancer can distribute requests evenly across the Prolog instances, ensuring that each server handles a balanced share of the workload. Cloud services like AWS Elastic Load Balancing (ELB) or Azure Load Balancer can be employed to manage this distribution. Kubernetes’ internal load balancing also works effectively for handling these tasks if deployed in a Kubernetes environment, providing flexibility in choosing the load management approach.
  • Aggregation Layer: To gather and combine results from each Prolog instance, an aggregation layer can be added. This layer collects outputs from the distributed Prolog servers using a message queue system such as AWS SQS, Google Cloud Pub/Sub, or Apache Kafka. Each Prolog instance sends its results to the queue, from which an aggregator service can retrieve, process, and compile these results for a unified output.
  • Coordination and Monitoring: Cloud-native monitoring and orchestration tools, like AWS CloudWatch, Azure Monitor, or Google Stackdriver, can track performance metrics, uptime, and error rates across the Prolog cluster. These tools ensure the cluster scales efficiently, and they monitor system health and manage logs for debugging. For Kubernetes deployments, built-in monitoring tools such as Prometheus and Grafana offer detailed cluster health insights.
  • Data Sharing and State Management: If Prolog snippets need to share data or state, shared storage solutions like AWS EFS (Elastic File System) or Google Cloud Filestore can enable Prolog instances to read common datasets without compromising immutability. This makes it possible to manage shared data across nodes while maintaining a coherent state.

This clustered approach provides a scalable solution for Prolog execution, with each server handling multiple parallel threads of SWI-Prolog. While a dedicated Prolog server with built-in load prioritization does not exist, this cluster model offers a relatively straightforward and adaptable framework to scale Prolog processes across cloud resources.

Setting up a distributed Prolog service across a cloud platform does require some coordination, but leveraging current cloud infrastructure—especially with load balancing, message queues, and monitoring tools—makes it a feasible solution that can effectively manage distributed Prolog logic processing.

Leave a comment