Skip to content

Commit ef39630

Browse files
committed
support variables
1 parent f21edde commit ef39630

File tree

8 files changed

+579
-25
lines changed

8 files changed

+579
-25
lines changed

src/Client.ts

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { ChatCompletionCreateParamsNonStreaming } from 'openai/resources'
22

33
import APIClient from './ApiClient'
4+
import { getMissingPromptVariables, renderPromptWithVariables, validatePromptVariables } from './helpers'
45
import { mapPromptToOpenAIConfig } from './helpers/openAi'
56
import { PromptConfiguration } from './types'
67

@@ -19,13 +20,29 @@ export default class PromptFoundry {
1920
})
2021
}
2122

22-
public async getPrompt({ promptId }: { promptId: string }): Promise<PromptConfiguration> {
23+
public async getRawPrompt({ promptId }: { promptId: string }): Promise<PromptConfiguration> {
2324
return this.client.get<PromptConfiguration>(`/prompts/${promptId}`)
2425
}
2526

26-
public async getOpenAiPrompt({ promptId }: { promptId: string }): Promise<ChatCompletionCreateParamsNonStreaming> {
27-
const result = await this.client.get<PromptConfiguration>(`/prompts/${promptId}`)
27+
public async getPrompt({ promptId, variables }: { promptId: string; variables: Record<string, string> }): Promise<PromptConfiguration> {
28+
const result = await this.getRawPrompt({ promptId })
2829

29-
return mapPromptToOpenAIConfig(result)
30+
if (!validatePromptVariables(result, variables)) {
31+
const missingVariables = getMissingPromptVariables(result, variables)
32+
throw new Error(`Missing variables in prompt: ${missingVariables.join(', ')}`)
33+
}
34+
return renderPromptWithVariables(result, variables)
35+
}
36+
37+
public async getOpenAiPrompt({
38+
promptId,
39+
variables
40+
}: {
41+
promptId: string
42+
variables: Record<string, string>
43+
}): Promise<ChatCompletionCreateParamsNonStreaming> {
44+
const updatedWithVariables = await this.getPrompt({ promptId, variables })
45+
46+
return mapPromptToOpenAIConfig(updatedWithVariables)
3047
}
3148
}

src/__tests__/Client.test.ts

Lines changed: 205 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ describe('client', () => {
1717
})
1818
})
1919
describe('getPrompt', () => {
20-
test('hello world test', async () => {
20+
it('returns prompt', async () => {
2121
const client = new Client({ apiKey: '123' })
2222

2323
const value = {
@@ -53,9 +53,212 @@ describe('client', () => {
5353
// @ts-expect-error - mocking the client's client property
5454
client.client = apiClient
5555

56-
const prompt = await client.getPrompt({ promptId: 'HELLO' })
56+
const prompt = await client.getPrompt({ promptId: 'HELLO', variables: {} })
5757

5858
expect(prompt).toEqual(value)
5959
})
60+
61+
it('should replace variables', async () => {
62+
const client = new Client({ apiKey: '123' })
63+
64+
const value = {
65+
promptId: 'HELLO',
66+
promptParameters: {
67+
frequencyPenalty: 0,
68+
modelName: 'gpt-3.5-turbo',
69+
presencePenalty: 0,
70+
responseFormat: {
71+
type: 'text'
72+
},
73+
temperature: 0.7,
74+
topP: 1
75+
},
76+
promptMessages: [
77+
{
78+
content: 'Hello, world!',
79+
role: 'user'
80+
},
81+
{
82+
content: 'Hi there {{name}}!',
83+
role: 'assistant'
84+
}
85+
]
86+
}
87+
88+
const apiClient: APIClient = {
89+
// @ts-expect-error - mocking the client's client property
90+
axiosInstance: {}, // Mocked as an empty object or with specific mock functions if needed
91+
get: jest.fn().mockResolvedValue(value)
92+
}
93+
94+
// @ts-expect-error - mocking the client's client property
95+
client.client = apiClient
96+
97+
const prompt = await client.getPrompt({ promptId: 'HELLO', variables: { name: 'bob' } })
98+
99+
expect(prompt.promptMessages[1].content).toEqual('Hi there bob!')
100+
})
101+
102+
it('should throw error if missing variables', async () => {
103+
const client = new Client({ apiKey: '123' })
104+
105+
const value = {
106+
promptId: 'HELLO',
107+
promptParameters: {
108+
frequencyPenalty: 0,
109+
modelName: 'gpt-3.5-turbo',
110+
presencePenalty: 0,
111+
responseFormat: {
112+
type: 'text'
113+
},
114+
temperature: 0.7,
115+
topP: 1
116+
},
117+
promptMessages: [
118+
{
119+
content: 'Hello, world!',
120+
role: 'user'
121+
},
122+
{
123+
content: 'Hi there {{name}}!',
124+
role: 'assistant'
125+
}
126+
]
127+
}
128+
129+
const apiClient: APIClient = {
130+
// @ts-expect-error - mocking the client's client property
131+
axiosInstance: {}, // Mocked as an empty object or with specific mock functions if needed
132+
get: jest.fn().mockResolvedValue(value)
133+
}
134+
135+
// @ts-expect-error - mocking the client's client property
136+
client.client = apiClient
137+
138+
await expect(() => client.getPrompt({ promptId: 'HELLO', variables: {} })).rejects.toThrowErrorMatchingSnapshot()
139+
})
140+
})
141+
142+
describe('getOpenAiPrompt', () => {
143+
it('returnsmapped prompt', async () => {
144+
const client = new Client({ apiKey: '123' })
145+
146+
const value = {
147+
promptId: 'HELLO',
148+
promptParameters: {
149+
frequencyPenalty: 0,
150+
modelName: 'gpt-3.5-turbo',
151+
presencePenalty: 0,
152+
responseFormat: {
153+
type: 'text'
154+
},
155+
temperature: 0.7,
156+
topP: 1
157+
},
158+
promptMessages: [
159+
{
160+
content: 'Hello, world!',
161+
role: 'user'
162+
},
163+
{
164+
content: 'Hi there!',
165+
role: 'assistant'
166+
}
167+
]
168+
}
169+
170+
const apiClient: APIClient = {
171+
// @ts-expect-error - mocking the client's client property
172+
axiosInstance: {}, // Mocked as an empty object or with specific mock functions if needed
173+
get: jest.fn().mockResolvedValue(value)
174+
}
175+
176+
// @ts-expect-error - mocking the client's client property
177+
client.client = apiClient
178+
179+
const prompt = await client.getOpenAiPrompt({ promptId: 'HELLO', variables: {} })
180+
181+
expect(prompt).toMatchSnapshot()
182+
})
183+
184+
it('should replace variables', async () => {
185+
const client = new Client({ apiKey: '123' })
186+
187+
const value = {
188+
promptId: 'HELLO',
189+
promptParameters: {
190+
frequencyPenalty: 0,
191+
modelName: 'gpt-3.5-turbo',
192+
presencePenalty: 0,
193+
responseFormat: {
194+
type: 'text'
195+
},
196+
temperature: 0.7,
197+
topP: 1
198+
},
199+
promptMessages: [
200+
{
201+
content: 'Hello, world!',
202+
role: 'user'
203+
},
204+
{
205+
content: 'Hi there {{name}}!',
206+
role: 'assistant'
207+
}
208+
]
209+
}
210+
211+
const apiClient: APIClient = {
212+
// @ts-expect-error - mocking the client's client property
213+
axiosInstance: {}, // Mocked as an empty object or with specific mock functions if needed
214+
get: jest.fn().mockResolvedValue(value)
215+
}
216+
217+
// @ts-expect-error - mocking the client's client property
218+
client.client = apiClient
219+
220+
const prompt = await client.getOpenAiPrompt({ promptId: 'HELLO', variables: { name: 'bob' } })
221+
222+
expect(prompt.messages[1].content).toEqual('Hi there bob!')
223+
})
224+
225+
it('should throw error if missing variables', async () => {
226+
const client = new Client({ apiKey: '123' })
227+
228+
const value = {
229+
promptId: 'HELLO',
230+
promptParameters: {
231+
frequencyPenalty: 0,
232+
modelName: 'gpt-3.5-turbo',
233+
presencePenalty: 0,
234+
responseFormat: {
235+
type: 'text'
236+
},
237+
temperature: 0.7,
238+
topP: 1
239+
},
240+
promptMessages: [
241+
{
242+
content: 'Hello, world!',
243+
role: 'user'
244+
},
245+
{
246+
content: 'Hi there {{name}}!',
247+
role: 'assistant'
248+
}
249+
]
250+
}
251+
252+
const apiClient: APIClient = {
253+
// @ts-expect-error - mocking the client's client property
254+
axiosInstance: {}, // Mocked as an empty object or with specific mock functions if needed
255+
get: jest.fn().mockResolvedValue(value)
256+
}
257+
258+
// @ts-expect-error - mocking the client's client property
259+
client.client = apiClient
260+
261+
await expect(() => client.getOpenAiPrompt({ promptId: 'HELLO', variables: {} })).rejects.toThrowErrorMatchingSnapshot()
262+
})
60263
})
61264
})
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// Jest Snapshot v1, https://goo.gl/fbAQLP
2+
3+
exports[`client getOpenAiPrompt returnsmapped prompt 1`] = `
4+
{
5+
"frequency_penalty": 0,
6+
"max_tokens": undefined,
7+
"messages": [
8+
{
9+
"content": "Hello, world!",
10+
"role": "user",
11+
},
12+
{
13+
"content": "Hi there!",
14+
"role": "assistant",
15+
},
16+
],
17+
"model": "gpt-3.5-turbo",
18+
"presence_penalty": 0,
19+
"response_format": {
20+
"type": "text",
21+
},
22+
"seed": undefined,
23+
"temperature": 0.7,
24+
"top_p": 1,
25+
}
26+
`;
27+
28+
exports[`client getOpenAiPrompt should throw error if missing variables 1`] = `"Missing variables in prompt: name"`;
29+
30+
exports[`client getPrompt should throw error if missing variables 1`] = `"Missing variables in prompt: name"`;

0 commit comments

Comments
 (0)