Skip to content

Commit 61ad8bf

Browse files
committed
Update API to use ai()
1 parent 1337920 commit 61ad8bf

File tree

10 files changed

+110
-86
lines changed

10 files changed

+110
-86
lines changed

examples-java/src/main/java/com/embabel/example/factchecker/FactChecker.java

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,18 @@
1+
/*
2+
* Copyright 2024-2025 Embabel Software, Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
116
package com.embabel.example.factchecker;
217

318
import com.embabel.agent.api.annotation.AchievesGoal;
@@ -123,7 +138,7 @@ DistinctFactualAssertions identifyDistinctFactualAssertions(UserInput userInput,
123138
FactChecks factChecks(
124139
DistinctFactualAssertions distinctFactualAssertions,
125140
OperationContext context) {
126-
var promptRunner = context.promptRunner().withLlm(
141+
var promptRunner = context.ai().withLlm(
127142
LlmOptions.withModel(OpenAiModels.GPT_41_MINI)
128143
)
129144
.withToolGroup(CoreToolGroups.WEB);
@@ -152,7 +167,7 @@ FactChecks factChecks(
152167
}
153168

154169
private DistinctFactualAssertions generate(UserInput userInput, ActionContext context, LlmOptions llm) {
155-
return context.promptRunner()
170+
return context.ai()
156171
.withLlm(llm)
157172
.createObject(
158173
"""
@@ -182,7 +197,7 @@ private DistinctFactualAssertions getDistinctFactualAssertions(
182197
var assertionsContent = allAssertions.stream()
183198
.map(FactualAssertion::standaloneAssertion)
184199
.collect(Collectors.joining("\n"));
185-
return context.promptRunner().withLlm(
200+
return context.ai().withLlm(
186201
properties.deduplicationLlm()
187202
).createObject(
188203
"""

examples-java/src/main/java/com/embabel/example/handoff/Handoff.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818
import com.embabel.agent.api.annotation.*;
1919
import com.embabel.agent.api.common.OperationContext;
2020
import com.embabel.agent.domain.io.UserInput;
21-
import com.embabel.common.ai.model.LlmOptions;
2221
import com.embabel.example.horoscope.StarPerson;
2322
import com.embabel.example.horoscope.Writeup;
2423

@@ -43,8 +42,8 @@ Choice makeChoice(UserInput userInput, OperationContext operationContext) {
4342
@AchievesGoal(description = "Choose your own adventure",
4443
export = @Export(name = "chooseAdventure", remote = true, startingInputTypes = {UserInput.class}))
4544
AdventureLog chooseAdventure(Choice choice, OperationContext operationContext) {
46-
return operationContext.promptRunner()
47-
.withLlm(LlmOptions.withAutoLlm())
45+
return operationContext.ai()
46+
.withAutoLlm()
4847
.withHandoffs(StarPerson.class, Writeup.class)
4948
.createObject("""
5049
Based on the user's input, decide what to do. You might do something related to a horoscope or some fact checking.

examples-java/src/main/java/com/embabel/example/handoff/Subagents.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,18 @@
1+
/*
2+
* Copyright 2024-2025 Embabel Software, Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
116
package com.embabel.example.handoff;
217

318
import com.embabel.agent.api.annotation.AchievesGoal;

examples-java/src/main/java/com/embabel/example/horoscope/StarNewsFinder.java

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717

1818
import com.embabel.agent.api.annotation.*;
1919
import com.embabel.agent.api.common.OperationContext;
20-
import com.embabel.agent.api.common.PromptRunner;
2120
import com.embabel.agent.config.models.OpenAiModels;
2221
import com.embabel.agent.core.CoreToolGroups;
2322
import com.embabel.agent.domain.io.UserInput;
@@ -52,7 +51,7 @@ public StarNewsFinder(
5251

5352
@Action
5453
public Person extractPerson(UserInput userInput, OperationContext context) {
55-
return context.promptRunner().withLlm(LlmOptions.fromModel(OpenAiModels.GPT_41)).createObjectIfPossible(
54+
return context.ai().withLlm(OpenAiModels.GPT_41).createObjectIfPossible(
5655
"""
5756
Create a person from this user input, extracting their name:
5857
%s""".formatted(userInput.getContent()),
@@ -76,7 +75,7 @@ public StarPerson assembleStarPerson(Person person, Starry starry) {
7675

7776
@Action
7877
public StarPerson extractStarPerson(UserInput userInput, OperationContext context) {
79-
return context.promptRunner().withLlm(LlmOptions.fromModel(OpenAiModels.GPT_41)).createObjectIfPossible(
78+
return context.ai().withLlm(OpenAiModels.GPT_41).createObjectIfPossible(
8079
"""
8180
Create a person from this user input, extracting their name and star sign:
8281
%s""".formatted(userInput.getContent()),
@@ -110,7 +109,7 @@ public RelevantNewsStories findNewsStories(StarPerson person, Horoscope horoscop
110109
find news stories about training courses.""".formatted(
111110
person.name(), person.sign(), horoscope.summary(), storyCount);
112111

113-
return context.promptRunner().createObject(prompt, RelevantNewsStories.class);
112+
return context.ai().withDefaultLlm().createObject(prompt, RelevantNewsStories.class);
114113
}
115114

116115
// The @AchievesGoal annotation indicates that completing this action
@@ -151,6 +150,6 @@ public Writeup writeup(
151150
152151
Format it as Markdown with links.""".formatted(
153152
person.name(), person.sign(), horoscope.summary(), newsItems);
154-
return context.promptRunner().withLlm(llm).createObject(prompt, Writeup.class);
153+
return context.ai().withLlm(llm).createObject(prompt, Writeup.class);
155154
}
156155
}

examples-java/src/main/java/com/embabel/example/repeatuntil/GoatWriterConfig.java

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
import com.embabel.agent.api.common.workflow.loop.TextFeedback;
2020
import com.embabel.agent.config.models.OpenAiModels;
2121
import com.embabel.agent.core.Agent;
22-
import com.embabel.common.ai.model.LlmOptions;
2322
import org.springframework.context.annotation.Bean;
2423
import org.springframework.context.annotation.Configuration;
2524

@@ -40,8 +39,8 @@ public Agent goatWriter() {
4039
.repeating(context -> {
4140
var lastFeedback = context.getInput().lastFeedback();
4241
var feedback = lastFeedback != null ? "Feedback: " + lastFeedback.getFeedback() : "";
43-
return context.promptRunner()
44-
.withLlm(LlmOptions.withModel(OpenAiModels.GPT_5_NANO))
42+
return context.ai()
43+
.withLlm(OpenAiModels.GPT_5_NANO)
4544
.createObject(
4645
"""
4746
Describe a goat in 200 words. Be creative.
@@ -51,7 +50,7 @@ public Agent goatWriter() {
5150
Goat.class);
5251
})
5352
.withEvaluator(context ->
54-
context.promptRunner().createObject(
53+
context.ai().withDefaultLlm().createObject(
5554
"""
5655
Evaluate the goat description for creativity and detail.
5756
The goat must have a name.

examples-java/src/main/java/com/embabel/example/repeatuntil/ReviseStoryUntilSatisfied.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import com.embabel.agent.api.common.ActionContext;
2222
import com.embabel.agent.api.common.workflow.loop.RepeatUntilAcceptableBuilder;
2323
import com.embabel.agent.api.common.workflow.loop.TextFeedback;
24+
import com.embabel.agent.config.models.OpenAiModels;
2425
import com.embabel.agent.domain.io.UserInput;
2526
import com.embabel.common.ai.model.LlmOptions;
2627

@@ -38,10 +39,10 @@ class ReviseStoryUntilSatisfied {
3839
Story rewriteUntilSatisfied(
3940
UserInput userInput,
4041
ActionContext actionContext) {
41-
var writerPromptRunner = actionContext.promptRunner()
42-
.withLlm(LlmOptions.fromModel("gpt-4.1-mini").withTemperature(.8));
43-
var reviewerPromptRunner = actionContext.promptRunner()
44-
.withLlm(LlmOptions.fromModel("gpt-4.1-mini"));
42+
var writerPromptRunner = actionContext.ai()
43+
.withLlm(LlmOptions.withModel(OpenAiModels.GPT_41_MINI).withTemperature(.8));
44+
var reviewerPromptRunner = actionContext.ai()
45+
.withLlm(LlmOptions.withModel(OpenAiModels.GPT_41_MINI).withTemperature(0));
4546
return RepeatUntilAcceptableBuilder
4647
.returning(Story.class)
4748
.withMaxIterations(7)

examples-java/src/main/java/com/embabel/example/wikipedia/WikiAgent.java

Lines changed: 22 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@
2525
import java.util.List;
2626
import java.util.stream.Collectors;
2727

28-
record FocusAreas(List<FocusArea> focusAreas) {}
28+
record FocusAreas(List<FocusArea> focusAreas) {
29+
}
2930

3031
record FocusArea(String topic) {
3132
}
@@ -51,45 +52,45 @@ public WikiAgent(
5152

5253
@Action
5354
FocusAreas focusAreas(ResearchSubject researchSubject, OperationContext context) {
54-
return context.promptRunner()
55+
return context.ai()
5556
.withLlm(llm.withTemperature(.6))
5657
.withToolGroup(CoreToolGroups.WEB)
5758
.createObject("""
58-
What are some interesting topics to explore about %s?
59-
Please provide a list of focus areas, each as a separate line.
60-
Go beyond the obvious: emphasize quirky and lesser-known aspects.
61-
Use Wikipedia as the source of information.
62-
""".formatted(researchSubject.name()), FocusAreas.class);
59+
What are some interesting topics to explore about %s?
60+
Please provide a list of focus areas, each as a separate line.
61+
Go beyond the obvious: emphasize quirky and lesser-known aspects.
62+
Use Wikipedia as the source of information.
63+
""".formatted(researchSubject.name()), FocusAreas.class);
6364
}
6465

6566
@Action
6667
FocusArea findFocusArea(ResearchSubject researchSubject, FocusAreas focusAreas) {
6768
return WaitFor.formSubmission(
6869
"""
69-
Great, there are lots of interesting things to explore about %s.
70-
Choices:
71-
%s
72-
Please select one of the topics above to focus on.
73-
""".formatted(researchSubject.name(),
74-
focusAreas.focusAreas().stream().map(FocusArea::topic)
75-
.collect(Collectors.joining("\n"))),
70+
Great, there are lots of interesting things to explore about %s.
71+
Choices:
72+
%s
73+
Please select one of the topics above to focus on.
74+
""".formatted(researchSubject.name(),
75+
focusAreas.focusAreas().stream().map(FocusArea::topic)
76+
.collect(Collectors.joining("\n"))),
7677
FocusArea.class);
7778
}
7879

7980
@Action
8081
@AchievesGoal(description = "Find information from wikipedia according to the user's request.",
81-
export = @Export(remote = true, name="wikiSearch", startingInputTypes = {ResearchSubject.class})
82+
export = @Export(remote = true, name = "wikiSearch", startingInputTypes = {ResearchSubject.class})
8283
)
8384
ResearchReport performResearch(ResearchSubject researchSubject, FocusArea focusArea, OperationContext context) {
84-
return context.promptRunner()
85+
return context.ai()
8586
.withLlm(llm.withTemperature(.8))
8687
.withToolGroup(CoreToolGroups.WEB)
8788
.createObject("""
88-
Research the following subject on Wikipedia, with the given focus area, and summarize it
89-
in %d words:
90-
Subject: %s
91-
Focus Area: %s
92-
""".formatted(wordCount, researchSubject.name(), focusArea.topic()),
89+
Research the following subject on Wikipedia, with the given focus area, and summarize it
90+
in %d words:
91+
Subject: %s
92+
Focus Area: %s
93+
""".formatted(wordCount, researchSubject.name(), focusArea.topic()),
9394
ResearchReport.class);
9495
}
9596
}

examples-java/src/test/java/com/embabel/example/horoscope/StarNewsFinderTest.java

Lines changed: 30 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -28,46 +28,45 @@
2828

2929
public class StarNewsFinderTest {
3030

31-
@Nested
32-
class Writeup {
31+
@Nested
32+
class Writeup {
3333

34-
@Test
35-
void writeupPromptMustContainKeyData() {
34+
@Test
35+
void writeupPromptMustContainKeyData() {
3636

37-
HoroscopeService horoscopeService = mock(HoroscopeService.class);
38-
StarNewsFinder starNewsFinder = new StarNewsFinder(horoscopeService, 5);
39-
var context = new FakeOperationContext();
40-
var runner = context.getPromptRunner();
41-
context.expectResponse(new com.embabel.example.horoscope.Writeup("Gonna be a good day"));
37+
HoroscopeService horoscopeService = mock(HoroscopeService.class);
38+
StarNewsFinder starNewsFinder = new StarNewsFinder(horoscopeService, 5);
39+
var context = new FakeOperationContext();
40+
context.expectResponse(new com.embabel.example.horoscope.Writeup("Gonna be a good day"));
4241

43-
NewsStory cockatoos = new NewsStory(
44-
"https://fake.com.au",
45-
"Cockatoo behavior",
46-
"Cockatoos are eating cabbages"
47-
);
42+
NewsStory cockatoos = new NewsStory(
43+
"https://fake.com.au",
44+
"Cockatoo behavior",
45+
"Cockatoos are eating cabbages"
46+
);
4847

49-
NewsStory emus = new NewsStory(
50-
"https://morefake.com.au",
51-
"Emu movements",
52-
"Emus are massing"
53-
);
48+
NewsStory emus = new NewsStory(
49+
"https://morefake.com.au",
50+
"Emu movements",
51+
"Emus are massing"
52+
);
5453

55-
StarPerson starPerson = new StarPerson("Lynda", "Scorpio");
56-
RelevantNewsStories relevantNewsStories = new RelevantNewsStories(Arrays.asList(cockatoos, emus));
57-
Horoscope horoscope = new Horoscope("This is a good day for you");
54+
StarPerson starPerson = new StarPerson("Lynda", "Scorpio");
55+
RelevantNewsStories relevantNewsStories = new RelevantNewsStories(Arrays.asList(cockatoos, emus));
56+
Horoscope horoscope = new Horoscope("This is a good day for you");
5857

59-
starNewsFinder.writeup(starPerson, relevantNewsStories, horoscope, context);
58+
starNewsFinder.writeup(starPerson, relevantNewsStories, horoscope, context);
6059

61-
var prompt = context.getLlmInvocations().getFirst().getPrompt();
62-
var toolGroups = context.getLlmInvocations().getFirst().getInteraction().getToolGroups();
60+
var prompt = context.getLlmInvocations().getFirst().getPrompt();
61+
var toolGroups = context.getLlmInvocations().getFirst().getInteraction().getToolGroups();
6362

6463

65-
assertTrue(prompt.contains(starPerson.getName()));
66-
assertTrue(prompt.contains(starPerson.sign()));
67-
assertTrue(prompt.contains(cockatoos.getSummary()));
68-
assertTrue(prompt.contains(emus.getSummary()));
64+
assertTrue(prompt.contains(starPerson.getName()));
65+
assertTrue(prompt.contains(starPerson.sign()));
66+
assertTrue(prompt.contains(cockatoos.getSummary()));
67+
assertTrue(prompt.contains(emus.getSummary()));
6968

70-
assertTrue(toolGroups.isEmpty(), "The LLM should not have been given any tool groups");
69+
assertTrue(toolGroups.isEmpty(), "The LLM should not have been given any tool groups");
70+
}
7171
}
72-
}
7372
}

examples-kotlin/src/main/kotlin/com/embabel/example/factchecker/factChecker.kt

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ import com.embabel.agent.domain.io.UserInput
2626
import com.embabel.agent.domain.library.InternetResource
2727
import com.embabel.agent.domain.library.InternetResources
2828
import com.embabel.common.ai.model.LlmOptions
29-
import com.embabel.common.ai.model.ModelSelectionCriteria
3029
import com.embabel.common.core.types.ZeroToOne
3130
import com.fasterxml.jackson.annotation.JsonPropertyDescription
3231
import org.springframework.boot.context.properties.ConfigurationProperties
@@ -110,7 +109,7 @@ fun factCheckerAgent(
110109
aggregate<UserInput, FactualAssertions, RationalizedFactualAssertions>(
111110
transforms = llms.map { llm ->
112111
{ context ->
113-
context.promptRunner(llm = llm).withToolGroup(CoreToolGroups.WEB).createObject(
112+
context.ai().withLlm(llm).withToolGroup(CoreToolGroups.WEB).createObject(
114113
"""
115114
Given the following content, identify any factual assertions.
116115
Phrase them as standalone assertions.
@@ -124,7 +123,7 @@ fun factCheckerAgent(
124123
}
125124
},
126125
merge = { list, context ->
127-
context.promptRunner().createObject<RationalizedFactualAssertions>(
126+
context.ai().withDefaultLlm().createObject<RationalizedFactualAssertions>(
128127
"""
129128
Given the following factual assertions, merge them into a single list if
130129
any are the same. Condense into one assertion if one assertion negates another.
@@ -139,9 +138,7 @@ fun factCheckerAgent(
139138
}
140139

141140
transformation<RationalizedFactualAssertions, FactCheck> { operationContext ->
142-
val promptRunner = operationContext.promptRunner(
143-
LlmOptions(ModelSelectionCriteria.Auto),
144-
).withToolGroups(
141+
val promptRunner = operationContext.ai().withAutoLlm().withToolGroups(
145142
setOf(CoreToolGroups.WEB, CoreToolGroups.BROWSER_AUTOMATION),
146143
)
147144
val checks = operationContext.input.factualAssertions.parallelMap(operationContext) { assertion ->

0 commit comments

Comments
 (0)