Skip to main content

Description of Noema

Project description

ReadMe Banner

Noema is an application of the declarative programming paradigm to a langage model. With Noema, you can control the model and choose the path it will follow. This framework aims to enable developpers to use LLM as an interpretor, not as a source of truth. Noema is built on llamacpp and guidance's shoulders.

Concept

  • Noesis: can be seen as the description of a function
  • Noema: is the representation (step by step) of this description
  • Constitution: is the process of transformation Noesis->Noema.
  • (Transcendantal) Subject: the object producing the Noema via the constitution of the noesis. Here, the LLM.
  • Horizon: the environement of the subject, in other words, a context.

Noema/Noesis, Subject, Horizon and Constitution are a pedantic and naive application of concept borrowed from Husserl's phenomenology.

Installation

pip install git+https://github.com/AlbanPerli/Noema-Declarative-AI

Features

Create the Subject

from Noema import *

subject = Subject("model.gguf") # Full Compatibiliy with LLamaCPP.

subject.add(Var("Time is the only problem", "{thougth}")) # store "Time is the only problem" in {thougth}

Create an horizon

from Noema import *

horizon = Horizon(
  Sentence("You explain why {thougth}","{thougth_explanation}"), # The sentence produced is stored in {thougth_explanation}
  Int("Give a note between 0 and 10 to qualify the quality of your explanation.","{explanation_note}"), # The model produce an python integer that is stored in {explanation_note}
)

Constitution

from Noema import *

subject = horizon.constituteWith(subject) # The horizon is constituted by the LLM

# Read the noema
print(subject.noema)
# You are functioning in a loop of thought. Here is your reasoning step by step:
#   #THOUGTH_EXPLANATION: Explain why '{thougth}'.
#   #EXPLANATION_NOTE: Give a note between 0 and 10 to qualify the quality of your explanation.

# Here is the result of the reasoning:
#  #THOUGTH_EXPLANATION: The reason is that time is the only thing that is constant and cannot be changed.
#  #EXPLANATION_NOTE: 10

# Acces to each constitution separatly
print(subject.data["explanation_note"] * 2) # The value of 'explanation_note' is an int.
# 20

Simple generators

Generators can be used to generate content from the subject (LLM) through the noesis (here, the task description).

from Noema import *

horizon = Horizon(
  Sentence("task description","{var_name}") # Produce a sentence stored in {var_name}
  Word("task description","{var_name}")     # Produce a word stored in {var_name}
  Int("task description","{var_name}")      # Produce an int stored in {var_name}
  Float("task description","{var_name}")    # Produce a float stored in {var_name}
  Bool("task description","{var_name}")     # Produce a bool stored in {var_name}
)

Composed generators

ListOf can be built with simple generators or a custom Step.

from Noema import *

horizon = Horizon(
  ListOf(Word, "task description","{var_name}")  # Produce a list of Word stored in {var_name}
  ListOf(Int, "task description","{var_name}")   # Produce a list of int stored in {var_name}
  ...
)

Selector

from Noema import *

horizon = Horizon(
  Select("Are local LLMs the future?", ["Yes of course","Never!"], "{this_is_the_future}"), # The model can only choose between "Yes of course" and "Never!". 
)

Information

Information are useful to insert some context to the current step of the noesis. Here we use a simple string, but we can also call a python function to do some RAG or other tasks.

from Noema import *

subject = Horizon(
    Information("You act like TARS in interstellar."),
    Sentence("Tell a short joke.","{joke}"),
    Print("{joke}")
).constituteWith(subject)

Control Flow

IF/ELSE

from Noema import *

subject = Horizon(
    Sentence("Explain why '{thougth}'.","{thougth_explanation}"), 
    Int("Give a note between 0 and 10 to qualify the quality of your explanation.","{explanation_note}"), 
    IF("{explanation_note} < 5", [
        Select("Do some auto-analysis, and choose a word to qualify your note", ["Fair","Over optimistic","Neutral"], "{auto_analysis}"),
    ],ELSE=[
       Select("Do some auto-analysis, and choose a word to qualify your note", ["Over optimistic","Neutral"], "{auto_analysis}"),
       IF("'{auto_analysis}' == 'Over optimistic'", [  # Note the " ' " around {auto_analysis}
            Int("How many points do you think you should remove to be fair?","{points_to_remove}"),
            Sentence("Explain why you think you should remove {points_to_remove} points.","{points_explanation}"),
       ])
    ])
).constituteWith(subject)

print(subject.data["auto_analysis"])      # "Over optimistic"
print(subject.data["points_to_remove"])   # 1
print(subject.data["points_explanation"]) # "The explanation is not clear enough, and the note is too high."

ForEach

from Noema import *

subject = Horizon(
    ListOf(Sentence, "What are the problems you are facing (in order of difficulty)?","{problems}"), # The model produce a list of sentence that is stored in {problems}
    ForEach("{problems}","{item}","{count}", [
        Sentence("Explain why '{item}' is the problem No {count}.","{item_explanation}"), 
        Print("Pb Nb {count}: {item}. Explanation: {item_explanation}") # Print doesn't interfere with the Noema 
    ])
).constituteWith(subject)
# DEBUG: Pb Nb 1: I can't find a solution to the problem.. Explanation: Because if you can't find a solution, you can't make progress.
# DEBUG: Pb Nb 2: I don't know where to start.. Explanation: Because if you don't know where to start, you can't make any progress either.
# DEBUG: Pb Nb 3: I'm overwhelmed by the complexity of the problem.. Explanation: Because if you're overwhelmed, you can't focus on finding a solution or even knowing where to start.

While

from Noema import *

subject = Horizon(
    Information("You have to choose a job name in the field of computer science."),
    Var(0,"{word_length}"),
    While("{word_length} < 7",[
        Word("Give a good job name:","{job_name}"),
        Int("How many letters are in the word {job_name}?","{word_length}"),
        Print("Selected job {job_name}"),
        Information("You have to choose a new job name each time."),
    ]),
    Print("The word {job_name} has more than 10 letters."),
    PrintNoema()
).constituteWith(subject)

NOESIS

The Noesis is the descriptive process of a thought. You can think about it as a set of rules aiming to attain a goal. In a function we think about steps, here you have to declare how to think about the steps.

A Noesis need a description, here: "Find a job name in a field." and can take optionnal parameters. The Return is optional.

from Noema import *

find_job_name = Noesis("Find a job name in a field.",["field_name","max_length"],[
    Information("You have to choose a job name in the field of {field_name}."),
    Var(0,"{word_length}"),
    While("{word_length} < {max_length}",[
        Word("Give a good job name:","{job_name}"),
        Int("How many letters are in the word {job_name}?","{word_length}"),
        Print("Selected job {job_name}"),
        Information("You have to choose a new job name each time."),
    ]),
    Return("{job_name} is a good job name in the field of {field_name}.") #Return value
])

subject = Horizon(
    Var(Constitute(find_job_name,("IT","10")),"{job_name}"), # Call the noesis "find_job_name" with the arguments "IT" and 10 and store the result in {job_name}
    Print("{job_name} has more than 10 letters."),
).constituteWith(subject)

Python Function Call

In the Noesis we can call a python function. The parameters can be value extracted from the context i.e. a Var using {var_name}. Return value of the python function called can be stored in a Var.

from Noema import *

def count_letters(word):
    return len(word)

subject = Horizon(
    Var("TENET", "{palindrome}"), # store "TENET" in {palindrome}
    Var(CallFunction(count_letters, "{palindrome}"), "{word_length}"), # store the result of the function count_letters in {word_length}
    Print("The word '{palindrome}' has {word_length} letters."),
).constituteWith(subject)

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

Noema-1.0.1.tar.gz (114.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

Noema-1.0.1-py3-none-any.whl (23.1 kB view details)

Uploaded Python 3

File details

Details for the file Noema-1.0.1.tar.gz.

File metadata

  • Download URL: Noema-1.0.1.tar.gz
  • Upload date:
  • Size: 114.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/5.1.1 CPython/3.11.7

File hashes

Hashes for Noema-1.0.1.tar.gz
Algorithm Hash digest
SHA256 35b05f4d2f964a7c8753e2a53c43c67bed6984e6e21b28efd66ce81850b8d8cc
MD5 9f5471e8d91593c4aaed17befa238322
BLAKE2b-256 a420aa132819d6e7f9d1f0361bc93a676f351faff1be1546e0640b1cd917ad88

See more details on using hashes here.

File details

Details for the file Noema-1.0.1-py3-none-any.whl.

File metadata

  • Download URL: Noema-1.0.1-py3-none-any.whl
  • Upload date:
  • Size: 23.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/5.1.1 CPython/3.11.7

File hashes

Hashes for Noema-1.0.1-py3-none-any.whl
Algorithm Hash digest
SHA256 3a333872f63b0da2fb6ce1fb25139d2b9146d4d40d91d023fcb7cae4027c2908
MD5 33c52abd33dc222b78d509ee297674da
BLAKE2b-256 710d3780bf14e207d33b7dbfb79cbede142b9c4df4550cd9c5ad51b93e82743f

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page