Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 12 additions & 12 deletions common/config/rush/pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion examples/cozeloop-ai-node/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
"@types/node": "^20",
"dotenv": "~16.4.7",
"msw": "^2.7.3",
"tsx": "^4.19.3",
"tsx": "^4.20.5",
"typescript": "^5.5.3"
}
}
1 change: 1 addition & 0 deletions examples/cozeloop-ai-node/src/api/api-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,5 @@ export async function run() {
});

assert.strictEqual(resp.code, 0);
process.exit(0);
}
1 change: 1 addition & 0 deletions examples/cozeloop-ai-node/src/auth/oauth-jwt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,5 @@ export async function run() {
const tokenResp = await authFlow.getToken();

assert.ok(tokenResp.access_token);
process.exit(0);
}
1 change: 1 addition & 0 deletions examples/cozeloop-ai-node/src/practice/travel-plan.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ async function run() {
console.info(result);
// The trace reporting is asynchronous and has some latency.
// If **running local files directly**, a short delay is required to ensure successful reporting.
process.exit(0);
}

run();
8 changes: 7 additions & 1 deletion examples/cozeloop-ai-node/src/prompt/index.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
import { run as runMultiPart } from './with-multi-part';
import { run as runWithLabel } from './with-label';
import { run as runWithJinja } from './with-jinja';
import { run as runBasic } from './hub';

export async function run() {
await Promise.all([runBasic(), runWithJinja(), runMultiPart()]);
await Promise.all([
runBasic(),
runWithJinja(),
runMultiPart(),
runWithLabel(),
]);

process.exit(0);
}
76 changes: 76 additions & 0 deletions examples/cozeloop-ai-node/src/prompt/with-label.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import assert from 'node:assert';

import { type PromptVariables, PromptHub } from '@cozeloop/ai';

export async function run() {
const hub = new PromptHub({
/** workspace id, use process.env.COZELOOP_WORKSPACE_ID when unprovided */
// workspaceId: 'your_workspace_id',
apiClient: {
// baseURL: 'api_base_url',
// token: 'your_api_token',
},
});

// 1. getPrompt with label
const key = 'loop';
const version = undefined;
const label = 'beta';
const prompt = await hub.getPrompt(key, version, label);
// {
// workspace_id: '7308703665823416358',
// prompt_key: 'loop',
// version: '0.0.2',
// prompt_template: {
// template_type: 'jinja2',
// messages: [
// {
// role: 'system',
// content: 'You are a helpful bot, the conversation topic is {{var1}}.',
// },
// { role: 'placeholder', content: 'placeholder1' },
// { role: 'user', content: 'My question is {{var2}}' },
// { role: 'placeholder', content: 'placeholder2' },
// { role: 'user', content: '' },
// ],
// variable_defs: [
// { key: 'var1', desc: '', type: 'string' },
// { key: 'var2', desc: '', type: 'string' },
// { desc: '', type: 'multi_part', key: 'img1' },
// { key: 'placeholder1', desc: '', type: 'placeholder' },
// { key: 'placeholder2', desc: '', type: 'placeholder' },
// ],
// },
// llm_config: {
// temperature: 1,
// max_tokens: 4096,
// top_p: 0.7,
// frequency_penalty: 0,
// },
// }

assert.strictEqual(prompt?.prompt_key, key);
assert.strictEqual(prompt.version, '0.0.2');

// 2. formatPrompt with variables
const variables: PromptVariables = {
var1: 'value_of_var1',
var2: 'value_of_var2',
var3: 'value_of_var3',
placeholder1: { role: 'assistant', content: 'user' },
};
const messages = hub.formatPrompt(prompt, variables);
// [
// {
// role: 'system',
// content:
// 'You are a helpful bot, the conversation topic is value_of_var1.',
// },
// { role: 'assistant', content: 'user' },
// { role: 'user', content: 'My question is value_of_var2' },
// { role: 'user', content: '' },
// ]
assert.ok(messages.length);
}

run();
1 change: 1 addition & 0 deletions examples/cozeloop-ai-node/src/tracer/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,5 @@ export async function run() {
runLargeText(),
runTransferBetweenServices(),
]);
process.exit(0);
}
3 changes: 3 additions & 0 deletions packages/cozeloop-ai/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# 🕗 ChangeLog - @cozeloop/ai

## 0.0.8
* PromptHub: get prompt with label

## 0.0.7
* PromptHub: multi-modal variable in template

Expand Down
22 changes: 22 additions & 0 deletions packages/cozeloop-ai/__tests__/__mock__/prompt-hub.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,26 @@ const multipartPrompt = {
},
};

const betaPrompt = {
query: { prompt_key: 'loop', label: 'beta' },
prompt: {
workspace_id: '7308703665823416358',
prompt_key: 'loop',
version: '0.0.2',
prompt_template: {
template_type: 'normal',
messages: [],
variable_defs: [],
},
llm_config: {
temperature: 1,
max_tokens: 4096,
top_p: 0.7,
frequency_penalty: 0,
},
},
};

export function setupPromptHubMock() {
const mockServer = setupServer(
http.post(/\/v1\/loop\/prompts\/mget/, req => {
Expand All @@ -116,6 +136,8 @@ export function setupPromptHubMock() {
return successResp({ items: [normalPrompt] });
case 'multi-part':
return successResp({ items: [multipartPrompt] });
case 'beta-label':
return successResp({ items: [betaPrompt] });
default:
return passthrough();
}
Expand Down
20 changes: 18 additions & 2 deletions packages/cozeloop-ai/__tests__/prompt/hub.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,8 +112,8 @@ describe('Test Prompt Hub', () => {
expect(spy).toHaveBeenCalledTimes(4);

vi.useRealTimers();
expect(cache.get('non_exist_key')).toBeUndefined();
expect(cache.delete('non_exist_key')).toBe(false);
expect(cache.get({ prompt_key: 'non_exist_key' })).toBeUndefined();
expect(cache.delete({ prompt_key: 'non_exist_key' })).toBe(false);

cache.clear();
// @ts-expect-error skip
Expand Down Expand Up @@ -192,4 +192,20 @@ describe('Test Prompt Hub', () => {
],
});
});

it('#5 get prompt with label', async () => {
const hub = new PromptHub({
apiClient: {
headers: { 'x-template-type': 'beta-label' }, // for mock
},
traceable: false,
});

const key = 'loop';
const label = 'beta';
const prompt = await hub.getPrompt(key, undefined, label);

expect(prompt?.prompt_key).toBe(key);
expect(prompt?.version).toBe('0.0.2');
});
});
Loading
Loading