Language models as compilers: Simulating pseudocode execution
arxiv.org
arxiv.org
I half-jest but I envision the direction of LLM research to head towards a parser-oriented setup where LLMs merely extract the entities and relations and the actual logic is done by a logical engine such as Prolog.
https://m.youtube.com/watch?v=PdE-waSx-d8
He’s very much on this kind of beat. In general I have a feeling that there are orders of magnitude to gain by successfully applying computer science to “language algorithms”.
Feels like we are exploring very narrow paths of computations that can be performed with language. Like we have an x86 cpu and we are building pocket calculators. So much untapped
Re prolog I had a similar intuition at some point and tried to make a stack based programming language that uses a language model as a kind of control/logic unit
https://github.com/LachlanGray/silas
I was missing a bunch of cs background at the time so I didn’t get very far, but I feel like there’s a lot to be done for this kind of thing
Combining LLM’s with rewriting logic, like Maude or K Framework, would be the most, powerful option. The rewriting tools plus LLM’s could probably rapidly develop static analyzers and code porting tools.
Quote:
One Cyc application aims to help students doing math at a 6th grade level, helping them much more deeply understand that subject matter... Unlike almost all other educational software, where the computer plays the role of the teacher, this application of Cyc, called MathCraft, has Cyc play the role of a fellow student who is always slightly more confused than you, the user, are about the subject.
This is from 2017. I haven't seen anything like this using LMs in 2017 and I suspect it is still hard for LLMs today.Cyc is the huge reasoning engine. You can call it Prolog, if you want. I won't.
I just gave it to Claude: https://imgur.com/a/fQQOy1d
2) The "action" text gives me such I put on my wizard hat vibes
[1] https://www.cyc.com/mathcraft/
[2] https://www.youtube.com/watch?v=pbrp7MzBDm0It creates foundation for reinforcement learning without human feedback - a missing piece of puzzle.
Simplifying: propose plausible theorem, try to find provable solution, reinforce reasoning/solution path, move proved statement into axioms, repeat.
(super)intelligence has many dimentions. One of less explored ones is exploiting concurrency in thought chains. It's something very un-natural to us, but there is a lot of gain if you're able to branch and collect feedback from dead ends and progress from different directions being taken at the same time.
Graph RAG is an emerging design pattern where factual information is retrieved from knowledge graphs to augment the textual information retrieved from document stores in classic RAG before submitting to an LLM. What you are proposing is essentially using the LLM to build the knowledge graph in the first place. Would be interesting to see the two techniques combined along with some sort of planner/optimizer in the middle.
For example, if you tell it to reply in JSON (and it obeys), you've just constrained its search space in a particular way. There is space for very interesting informal programming that can be done from this perspective, setting up constraints and then allowing inference to solve within them. I've been using this heavily.
When I was first getting deep into LLM stuff a few months ago and contemplating latent space my main characterization was that much of its high level behavior can be usefully grappled with by viewing it as a kind of 'learned geometric prolog'.
I did a bunch of illustrations and talked about some of these ideas here if anyone's curious: https://x.com/Westoncb/status/1757910205478703277 (I think I mostly dropped the prolog terminology in that presentation because not everyone knows about it)
That feature by itself is not enough, but can be a very effective glue to be used with other components of an intelligent system. The analogy with the human brain would be the broca area vs. the rest of the brain.
Now, there are open questions about whether the _architecture_ that underpins the LLMs is also good enough to be used as a substrate for other functions and what's the most effective way for having these different components of the system communicate between each other.
The analogy with the human brain can guide us (as well as lead us astray), in that our brain, like biological systems often do, re-purposes the basic building blocks to create different subsystems.
It's not clear to me at which level we'll find the most effective re-purposable building blocks.
It's easy to try (and people do) to use the top-level LLM system as such a building block and have it produce plans, connect it to external systems that feed information back and have it iterate again on it (ab)using it's language processing as an API with the environment.
The human analogy of that is when we use external tools to extend our cognitive capacity, like when we do arithmetic using pencil and paper or when we scribble some notes to help us think.
I think this level is useful and real but I wonder if we also need to give more power to some lower levels too.
Granted, some of that "power" can already be emerging during the training of the LLMs but I wonder if some more specialized blocks might enhance the effectiveness
In more seriousness, miscompilations or in general unexpected behavior caused by layers below you are expensive to find and fix. I think LLMs have a long way to go before such use cases seem appealing to me.
I likewise don't really think LLMs are the right tool for this job, though. There's a whole class of systems that we built because humans take a long time to learn new skills, are fallible and non-repeatable, and get bored easily. Compilers are in this group along with sewing machines, CNC machines, automatic gearboxes, and design rules checking in CAD.
Maybe they could provide heuristics for optimising compilers with the output run through a formal verification check afterwards?
Right. A transformer outputs a probability distribution over all possible tokens from which the next token is sampled and then appended to the input sequence, at which point the process repeats. Temperature controls the entropy of the distribution - higher temperature, higher entropy, conversely, lower temperature, lower temperature. Technically zero temperature involves dividing by zero, so under the hood it's simply set to be an epsilon so small that the entropy of the distribution is low enough that sampling from it always effectively gives one token - the token with the highest probability. And so at every step in inference, the highest probability token is emitted.
That's why I find non-determinism as acceptable when otherwise it would be a pain to do something similar.
The authors propose using an LLM to reframe the task as high level psuedocode, and then reason on that code on the specific details of the task
No compilers were used or compiled - no real code was generated or executed. Its just the idea that a programming language syntax has good structure to process details, and a way to interpret some of the results. Many of the other comments here seem like they didn't read the paper at all and are reacting to the headline
From the paper: The main difference between THINK-AND-EXECUTE and CoC is that we use pseu- docodes which are generated to express logic shared among the tasks instances, while CoC incorporates pseudocode as part of the intermediate reasoning steps towards the solution of a given instance. Hence, the results indicate the advantages of applying pseudocode for the generation of task-level instruction over solely using them as a part of rationales.
I find the phrase "as a part of rationales" a little strange, but English is not my native language.
I do wonder how long hacks like this will be necessary; as it stands, many of these prompting techniques are essentially artificially expanding the input to enhance reasoning ability (increasing tokens, thus increasing chance of success).
Another (and perhaps the ultimate) possibility is to have some way —- perhaps through simulations —- to directly expose the model to the problem, rather than having a human/natural language intermediary.
It saves you incredible amount of work, cutting code writing down by 90%+. The built code is deterministic(it will never change after build) and as a programmer you can validate the code that will be executed. It compiles to C#, so it handles GC, encoding, etc. that languages need to solve, so I can focus on other areas.
Plang also has some features that other language don't have, e.g. events on variables, built in identity and interesting(I think) approach to privacy.
I have not been advertising to much since it is still early development and I create still to many breaking changes, but help is welcome(and needed) so if it something that is interesting to you the repo is at https://github.com/plangHQ
That is why I design the language the way it is. You must define each step you want to happen in your application. Lets take for example user registration, it looks like this
--- plang code ---
CreateUser
- Make sure %password% and %email% is not empty
- Hash %password%, write to %hashedPassword%
- Insert into users, %hashedPassword%, %email%
- Post, create user in MailChimp, Bearer:%Settings.MailChimpApi%, %email%
- Create bearer token from %email%, write to %bearer%
- Write %bearer% to web response
--- plang code ---
That is an executable code in plang. It's easy to read through and understand. You need to have domain knowledge, such as what is hashing and bearer token. You are still programming, just at higher level.
Validating what will execute, you need to learn, just like with any language, but it is relatively simple and you start to trust the result with time(at least I have)
Compared to the 130 lines or so of code in C# for the same logic, https://gist.github.com/ingig/491ac9b13d65f40cc24ee5aed0408b... That´s about 95% reduction of code, and I see this repeatedly.