Prompting and Chain of Thought
The three single-prompt strategies differ only in how the question is presented. Each makes one call to the model (ZeroShotChainOfThought sometimes makes two), so they are the cheapest strategies and a good place to start. The examples are in the reasoning-agents project.
Direct prompting
BasicPrompting sends the question and asks for the answer in <answer></answer> tags. It is the baseline against which the other strategies can be compared.
import astra.langchain4j.reasoning.*;
agent Direct extends BasicPrompting {
module System S;
rule +!main(list args) {
try {
model.loadApiKeyFromEnv("OPENAI_API_KEY");
model.initialize("gpt-4o-mini",
"astra.langchain4j.configuration.OpenAiConfiguration", []);
!solve("Which planet is closest to the Sun?", string answer);
console.println("Answer: " + answer);
} recover {
console.println("The question could not be answered.");
}
S.exit();
}
}
Run it with mvn -Dastra.main=Direct. The output ends with a line such as:
[main] Answer: Mercury
Zero-shot chain of thought
Chain-of-thought prompting asks the model to show its reasoning before it answers, which improves results on problems that need several steps. The zero-shot form (Kojima et al., 2022) does this without examples, by adding “Let’s think step by step” to the prompt.
import astra.langchain4j.reasoning.*;
agent ZeroShot extends ZeroShotChainOfThought {
module System S;
rule +!main(list args) {
try {
model.loadApiKeyFromEnv("OPENAI_API_KEY");
model.initialize("gpt-4o-mini",
"astra.langchain4j.configuration.OpenAiConfiguration", []);
!solve("A shop sells pens in packs of 4. How many packs are needed for 30 pens?",
string answer);
console.println("Answer: " + answer);
} recover {
console.println("The question could not be answered.");
}
S.exit();
}
}
Run it with mvn -Dastra.main=ZeroShot. The agent prints the model’s reasoning, which should work out that 7 packs hold only 28 pens, then the extracted answer, 8.
If the reply has no <answer> tags, the agent makes a second call containing the question and the reasoning, ending with “Therefore, the answer is”, and uses that reply as the answer.
Few-shot chain of thought
The few-shot form (Wei et al., 2022) starts the prompt with worked examples, each showing the reasoning that leads to its answer, so that the model reasons about the new question in the same way. The examples depend on the kind of problem, so they are supplied as beliefs:
example(string question, string reasoning, string answer)
import astra.langchain4j.reasoning.*;
agent FewShot extends FewShotChainOfThought {
module System S;
initial example(
"Tom has 3 boxes of 5 apples and eats 2. How many apples are left?",
"3 boxes of 5 apples is 15 apples. Eating 2 leaves 15 - 2 = 13.",
"13"),
example(
"A train leaves at 9:40 and the journey takes 35 minutes. When does it arrive?",
"9:40 plus 20 minutes is 10:00, and the remaining 15 minutes gives 10:15.",
"10:15");
rule +!main(list args) {
try {
model.loadApiKeyFromEnv("OPENAI_API_KEY");
model.initialize("gpt-4o-mini",
"astra.langchain4j.configuration.OpenAiConfiguration", []);
!solve("A film starts at 18:50 and lasts 1 hour 45 minutes. When does it end?",
string answer);
console.println("Answer: " + answer);
} recover {
console.println("The question could not be answered.");
}
S.exit();
}
}
Run it with mvn -Dastra.main=FewShot. The expected answer is 20:35. The examples teach the model to work in steps and to give the answer as a bare value, such as 10:15 rather than a sentence.
The examples are read each time !solve(...) is adopted, so an agent can add or replace example beliefs between questions, for example to choose examples that resemble the current question. If there are no example beliefs, the agent prints a warning and sends the question with only the instruction to reason step by step.
Where next?
When a single prompt is not enough, pipelines split the reasoning into separate calls.