Skip to content

Commit 19ac580

Browse files
authored
Merge pull request #16711 from Budibase/feat/update-ai-models
Update our model selection to include GPT-5, and use it as part of the table generation
2 parents 5697865 + 6802b06 commit 19ac580

File tree

20 files changed

+323
-192
lines changed

20 files changed

+323
-192
lines changed

eslint.config.mjs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ export default [
4242
},
4343

4444
parser: babelParser,
45-
ecmaVersion: 2019,
45+
ecmaVersion: 2020,
4646
sourceType: "module",
4747

4848
parserOptions: {

packages/builder/src/pages/builder/portal/settings/ai/constants.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@ import { AIProvider, ProviderConfig } from "@budibase/types"
33
export const Models = [
44
{ label: "GPT 4o Mini", value: "gpt-4o-mini" },
55
{ label: "GPT 4o", value: "gpt-4o" },
6-
{ label: "GPT 4 Turbo", value: "gpt-4-turbo" },
7-
{ label: "GPT 4", value: "gpt-4" },
8-
{ label: "GPT 3.5 Turbo", value: "gpt-3.5-turbo" },
6+
{ label: "GPT 5", value: "gpt-5" },
7+
{ label: "GPT 5 Mini", value: "gpt-5-mini" },
8+
{ label: "GPT 5 Nano", value: "gpt-5-nano" },
99
]
1010

1111
interface AIProviderDetails {

packages/pro

Submodule pro updated from 38f69c9 to 9cf094c

packages/server/package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@
108108
"mysql2": "3.9.8",
109109
"node-fetch": "2.6.7",
110110
"object-sizeof": "2.6.1",
111-
"openai": "4.98.0",
111+
"openai": "5.12.1",
112112
"openapi-types": "9.3.1",
113113
"oracledb": "6.5.1",
114114
"pg": "8.10.0",
@@ -142,9 +142,9 @@
142142
"@types/jest": "29.5.5",
143143
"@types/json-schema": "^7.0.15",
144144
"@types/koa": "2.13.4",
145-
"@types/koa-send": "^4.1.6",
146145
"@types/koa__cors": "5.0.0",
147146
"@types/koa__router": "12.0.4",
147+
"@types/koa-send": "^4.1.6",
148148
"@types/lodash": "4.14.200",
149149
"@types/mssql": "9.1.5",
150150
"@types/node-fetch": "2.6.4",
@@ -175,6 +175,7 @@
175175
"ts-node": "10.8.1",
176176
"tsconfig-paths": "4.0.0",
177177
"typescript": "5.7.2",
178+
"undici": "^5.28.4",
178179
"yargs": "^13.2.4",
179180
"zod": "^3.23.8"
180181
},

packages/server/src/api/controllers/ai/agents.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,13 @@ function addDebugInformation(messages: Message[]) {
2424
let toolDebugInfo = "\n\n**Tool Calls:**\n"
2525

2626
for (const toolCall of message.tool_calls) {
27+
if (toolCall.type !== "function" || !toolCall.function) {
28+
console.warn(
29+
`[OPENAI TOOL WARN] Unsupported tool call type: ${toolCall.type}`
30+
)
31+
continue
32+
}
33+
2734
let toolParams = "{}"
2835
try {
2936
// Try to parse and prettify the JSON arguments

packages/server/src/api/routes/tests/ai.spec.ts

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ function customAIConfig(providerConfig: Partial<ProviderConfig>): SetupFn {
7373
provider: "OpenAI",
7474
name: "OpenAI",
7575
apiKey: "test-key",
76-
defaultModel: "gpt-4o-mini",
76+
defaultModel: "gpt-5-mini",
7777
active: true,
7878
isDefault: true,
7979
...providerConfig,
@@ -109,7 +109,7 @@ const allProviders: TestSetup[] = [
109109
},
110110
{
111111
name: "OpenAI API key with custom config",
112-
setup: customAIConfig({ provider: "OpenAI", defaultModel: "gpt-4o-mini" }),
112+
setup: customAIConfig({ provider: "OpenAI", defaultModel: "gpt-5-mini" }),
113113
mockLLMResponse: mockChatGPTResponse,
114114
},
115115
{
@@ -514,6 +514,9 @@ describe("BudibaseAI", () => {
514514
beforeEach(async () => {
515515
await config.newTenant()
516516
nock.cleanAll()
517+
// Ensure MockAgent is installed for OpenAI interceptors
518+
const { installHttpMocking } = require("../../../tests/jestEnv")
519+
installHttpMocking()
517520
})
518521

519522
const mockAIGenerationStructure = (
@@ -688,7 +691,11 @@ describe("BudibaseAI", () => {
688691
}
689692
mockAIColumnGeneration(generationStructure, aiColumnGeneration)
690693

691-
nock("https://photourl.com").get("/any.png").reply(200).persist()
694+
// Use nock for image downloads since it intercepts before undici
695+
nock("https://photourl.com")
696+
.get("/any.png")
697+
.times(5) // 5 employee photos
698+
.reply(200, Buffer.from("fake image data"))
692699

693700
const dataGeneration: Record<string, Record<string, any>[]> = {
694701
Tickets: [
@@ -845,7 +852,13 @@ describe("BudibaseAI", () => {
845852
}
846853
mockDataGeneration(dataGeneration)
847854

848-
mockProcessAIColumn("Mock LLM Response")
855+
// Set up interceptors for AI column processing
856+
// Tickets: 4 rows × 2 AI columns = 8 calls
857+
// Employees: 5 rows × 1 AI column = 5 calls
858+
// Total: 13 interceptors needed
859+
for (let i = 0; i < 13; i++) {
860+
mockProcessAIColumn("Mock LLM Response")
861+
}
849862

850863
const { createdTables } = await config.api.ai.generateTables({ prompt })
851864
expect(createdTables).toEqual([

packages/server/src/api/routes/tests/datasource.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ describe("/datasources", () => {
7777

7878
describe("dynamic variables", () => {
7979
it("should invalidate changed or removed variables", async () => {
80-
nock("http://www.example.com/")
80+
nock("http://www.example.com")
8181
.get("/")
8282
.reply(200, [{ value: "test" }])
8383
.get("/?test=test")

packages/server/src/api/routes/tests/row.spec.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3645,6 +3645,12 @@ if (descriptions.length) {
36453645
OPENAI_API_KEY: "sk-abcdefghijklmnopqrstuvwxyz1234567890abcd",
36463646
})
36473647

3648+
// Ensure MockAgent is installed for OpenAI interceptors
3649+
const { installHttpMocking } = require("../../../tests/jestEnv")
3650+
installHttpMocking()
3651+
3652+
//We need to supply multiple interceptors.
3653+
mockChatGPTResponse("Mock LLM Response")
36483654
mockChatGPTResponse("Mock LLM Response")
36493655

36503656
table = await config.api.table.save(

packages/server/src/api/routes/tests/search.spec.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1926,6 +1926,15 @@ if (descriptions.length) {
19261926
mocks.licenses.useAICustomConfigs()
19271927

19281928
envCleanup = setEnv({ OPENAI_API_KEY: "mock" })
1929+
1930+
// Ensure MockAgent is installed for OpenAI interceptors
1931+
const {
1932+
installHttpMocking,
1933+
} = require("../../../tests/jestEnv")
1934+
installHttpMocking()
1935+
1936+
// Set up 2 interceptors for the 2 rows that will be processed
1937+
mockChatGPTResponse("Mock LLM Response")
19291938
mockChatGPTResponse("Mock LLM Response")
19301939

19311940
tableOrViewId = await createTableOrView({

packages/server/src/api/routes/tests/viewV2.spec.ts

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -944,7 +944,12 @@ if (descriptions.length) {
944944
OPENAI_API_KEY: "sk-abcdefghijklmnopqrstuvwxyz1234567890abcd",
945945
})
946946

947-
mockChatGPTResponse(prompt => {
947+
// Ensure MockAgent is installed for OpenAI interceptors
948+
const { installHttpMocking } = require("../../../tests/jestEnv")
949+
installHttpMocking()
950+
951+
// Set up 3 interceptors for the 3 animals that will be processed
952+
const responseFunction = (prompt: string) => {
948953
if (prompt.includes("elephant")) {
949954
return "big"
950955
}
@@ -955,7 +960,12 @@ if (descriptions.length) {
955960
return "big"
956961
}
957962
return "unknown"
958-
})
963+
}
964+
965+
// Each row save will trigger AI processing
966+
mockChatGPTResponse(responseFunction)
967+
mockChatGPTResponse(responseFunction)
968+
mockChatGPTResponse(responseFunction)
959969
})
960970

961971
afterAll(() => {

0 commit comments

Comments
 (0)