Files
supabase/packages/ai-commands/test/extensions.ts
Greg RichardsonandIvan Vasilov 801ad65603 RLS AI improvements (#26895)
* chore: libpg-query types

* feat: improved rls ai tests

* feat: simplify assertitions for sql expressions

* refactor: split ai logic into separate files

* feat(rls-ai): test select, insert, update, delete policies

* feat: adds withMetadata wrapper for failed tests

* chore: remove custom libpg-query types

* feat(rls-ai): make tests concurrent

* fix(rls-ai): rules for 'using' and 'with check'

* feat(rls-ai): discourages restrictive policies

* feat(ai): makes withMetadata util sync or async

* refactor(ai): moves withMetadata to generic test utils

* feat(rls-ai): test joined table

* feat(rls-ai): test mfa

* chore(ai): make all tests concurrent

* fix(ai): chatSql function rename in studio

* refactor(ai): isolate logic into separate files

* chore(ai): remove trailing comma in tsconfig

* chore(ai): remove unused dep

* Reset some of the package versions to the versions from master.

* chore(ai): remove unused imports

---------

Co-authored-by: Ivan Vasilov <vasilov.ivan@gmail.com>
2024-06-05 14:33:56 +02:00

73 lines
2.0 KiB
TypeScript

import { expect } from '@jest/globals'
import { codeBlock } from 'common-tags'
import OpenAI from 'openai'
const openAiKey = process.env.OPENAI_API_KEY
const openai = new OpenAI({ apiKey: openAiKey })
expect.extend({
async toMatchCriteria(received: string, criteria: string) {
const model = 'gpt-4o-2024-05-13'
const completionResponse = await openai.chat.completions.create({
model,
messages: [
{
role: 'system',
content: codeBlock`
You are a test runner. Your job is to evaluate whether 'Received' adheres to the test 'Criteria'.
You must output JSON, specifically an object containing a "pass" boolean and "reason" string:
- \`{ "pass": true, "reason": "<reason>" }\` if 'Received' adheres to the test 'Criteria'
- \`{ "pass": false, "reason": "<reason>" }\` if 'Received' does not adhere to the test 'Criteria'
The "reason" must explain exactly which part of 'Received' did or did not pass the test 'Criteria'.
`,
},
{
role: 'user',
content: codeBlock`
Received:
${received}
Criteria:
${criteria}
`,
},
],
max_tokens: 256,
temperature: 0,
response_format: {
type: 'json_object',
},
stream: false,
})
const [choice] = completionResponse.choices
if (!choice.message.content) {
throw new Error('LLM evaluator returned invalid response')
}
const { pass, reason }: { pass?: boolean; reason?: string } = JSON.parse(choice.message.content)
if (pass === undefined) {
throw new Error('LLM evaluator returned invalid response')
}
return {
message: () =>
codeBlock`
${this.utils.matcherHint('toMatchCriteria', received, criteria, {
comment: `evaluated by LLM '${model}'`,
isNot: this.isNot,
promise: this.promise,
})}
${reason}
`,
pass,
}
},
})