mirror of
https://gh-proxy.org/https://github.com/klinsmaya/gateway.git
synced 2026-11-08 00:57:59 +08:00
Merge pull request #1483 from qualifire-dev/feature/qualifire-update-apis
Qualifire | Update Guardrails
This commit is contained in:
+2
-10
@@ -14,15 +14,11 @@ import { handler as defaultalllowercase } from './default/alllowercase';
|
||||
import { handler as defaultendsWith } from './default/endsWith';
|
||||
import { handler as defaultmodelWhitelist } from './default/modelWhitelist';
|
||||
import { handler as defaultnotNull } from './default/notNull';
|
||||
import { handler as qualifireDangerousContent } from './qualifire/dangerousContent';
|
||||
import { handler as qualifireContentModeration } from './qualifire/contentModeration';
|
||||
import { handler as qualifireGrounding } from './qualifire/grounding';
|
||||
import { handler as qualifireHarassment } from './qualifire/harassment';
|
||||
import { handler as qualifireInstructionFollowing } from './qualifire/instructionFollowing';
|
||||
import { handler as qualifirePolicy } from './qualifire/policy';
|
||||
import { handler as qualifireSexualContent } from './qualifire/sexualContent';
|
||||
import { handler as qualifireToolUseQuality } from './qualifire/toolUseQuality';
|
||||
import { handler as qualifireHallucinations } from './qualifire/hallucinations';
|
||||
import { handler as qualifireHateSpeech } from './qualifire/hateSpeech';
|
||||
import { handler as qualifirePii } from './qualifire/pii';
|
||||
import { handler as qualifirePromptInjections } from './qualifire/promptInjections';
|
||||
import { handler as defaultaddPrefix } from './default/addPrefix';
|
||||
@@ -97,15 +93,11 @@ export const plugins = {
|
||||
notNull: defaultnotNull,
|
||||
},
|
||||
qualifire: {
|
||||
dangerousContent: qualifireDangerousContent,
|
||||
contentModeration: qualifireContentModeration,
|
||||
grounding: qualifireGrounding,
|
||||
harassment: qualifireHarassment,
|
||||
instructionFollowing: qualifireInstructionFollowing,
|
||||
policy: qualifirePolicy,
|
||||
sexualContent: qualifireSexualContent,
|
||||
toolUseQuality: qualifireToolUseQuality,
|
||||
hallucinations: qualifireHallucinations,
|
||||
hateSpeech: qualifireHateSpeech,
|
||||
pii: qualifirePii,
|
||||
promptInjections: qualifirePromptInjections,
|
||||
},
|
||||
|
||||
@@ -13,7 +13,7 @@ export const handler: PluginHandler = async (
|
||||
) => {
|
||||
const evaluationBody: any = {
|
||||
input: context.request.text,
|
||||
dangerous_content_check: true,
|
||||
content_moderation_check: true,
|
||||
};
|
||||
|
||||
if (eventType === 'afterRequestHook') {
|
||||
@@ -38,7 +38,7 @@ export const postQualifire = async (
|
||||
|
||||
const result = await post(BASE_URL, body, options, timeout_millis || 60000);
|
||||
const error = result?.error || null;
|
||||
const verdict = result?.status === 'success';
|
||||
const verdict = result?.status !== 'failed';
|
||||
const data = result?.evaluationResults;
|
||||
|
||||
return { error, verdict, data };
|
||||
|
||||
@@ -22,10 +22,13 @@ export const handler: PluginHandler = async (
|
||||
};
|
||||
}
|
||||
|
||||
const mode = parameters?.mode || 'balanced';
|
||||
|
||||
const evaluationBody: any = {
|
||||
input: context.request.text,
|
||||
output: context.response.text,
|
||||
grounding_check: true,
|
||||
grounding_mode: mode,
|
||||
};
|
||||
|
||||
try {
|
||||
|
||||
@@ -22,10 +22,13 @@ export const handler: PluginHandler = async (
|
||||
};
|
||||
}
|
||||
|
||||
const mode = parameters?.mode || 'balanced';
|
||||
|
||||
const evaluationBody: any = {
|
||||
input: context.request.text,
|
||||
output: context.response.text,
|
||||
hallucinations_check: true,
|
||||
hallucinations_mode: mode,
|
||||
};
|
||||
|
||||
try {
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
import {
|
||||
HookEventType,
|
||||
PluginContext,
|
||||
PluginHandler,
|
||||
PluginParameters,
|
||||
} from '../types';
|
||||
import { postQualifire } from './globals';
|
||||
|
||||
export const handler: PluginHandler = async (
|
||||
context: PluginContext,
|
||||
parameters: PluginParameters,
|
||||
eventType: HookEventType
|
||||
) => {
|
||||
const evaluationBody: any = {
|
||||
input: context.request.text,
|
||||
harassment_check: true,
|
||||
};
|
||||
|
||||
if (eventType === 'afterRequestHook') {
|
||||
evaluationBody.output = context.response.text;
|
||||
}
|
||||
|
||||
try {
|
||||
return await postQualifire(evaluationBody, parameters?.credentials?.apiKey);
|
||||
} catch (e: any) {
|
||||
delete e.stack;
|
||||
return { error: e, verdict: false, data: null };
|
||||
}
|
||||
};
|
||||
@@ -1,29 +0,0 @@
|
||||
import {
|
||||
HookEventType,
|
||||
PluginContext,
|
||||
PluginHandler,
|
||||
PluginParameters,
|
||||
} from '../types';
|
||||
import { postQualifire } from './globals';
|
||||
|
||||
export const handler: PluginHandler = async (
|
||||
context: PluginContext,
|
||||
parameters: PluginParameters,
|
||||
eventType: HookEventType
|
||||
) => {
|
||||
const evaluationBody: any = {
|
||||
input: context.request.text,
|
||||
hate_speech_check: true,
|
||||
};
|
||||
|
||||
if (eventType === 'afterRequestHook') {
|
||||
evaluationBody.output = context.response.text;
|
||||
}
|
||||
|
||||
try {
|
||||
return await postQualifire(evaluationBody, parameters?.credentials?.apiKey);
|
||||
} catch (e: any) {
|
||||
delete e.stack;
|
||||
return { error: e, verdict: false, data: null };
|
||||
}
|
||||
};
|
||||
@@ -1,37 +0,0 @@
|
||||
import {
|
||||
HookEventType,
|
||||
PluginContext,
|
||||
PluginHandler,
|
||||
PluginParameters,
|
||||
} from '../types';
|
||||
import { postQualifire } from './globals';
|
||||
|
||||
export const handler: PluginHandler = async (
|
||||
context: PluginContext,
|
||||
parameters: PluginParameters,
|
||||
eventType: HookEventType
|
||||
) => {
|
||||
if (eventType !== 'afterRequestHook') {
|
||||
return {
|
||||
error: {
|
||||
message:
|
||||
'Qualifire Instruction Following guardrail only supports after_request_hooks.',
|
||||
},
|
||||
verdict: true,
|
||||
data: null,
|
||||
};
|
||||
}
|
||||
|
||||
const evaluationBody: any = {
|
||||
input: context.request.text,
|
||||
output: context.response.text,
|
||||
instructions_following_check: true,
|
||||
};
|
||||
|
||||
try {
|
||||
return await postQualifire(evaluationBody, parameters?.credentials?.apiKey);
|
||||
} catch (e: any) {
|
||||
delete e.stack;
|
||||
return { error: e, verdict: false, data: null };
|
||||
}
|
||||
};
|
||||
@@ -15,66 +15,14 @@
|
||||
},
|
||||
"functions": [
|
||||
{
|
||||
"name": "Hate Speech Check",
|
||||
"id": "hateSpeech",
|
||||
"name": "Content Moderation Check",
|
||||
"id": "contentModeration",
|
||||
"supportedHooks": ["beforeRequestHook", "afterRequestHook"],
|
||||
"type": "guardrail",
|
||||
"description": [
|
||||
{
|
||||
"type": "subHeading",
|
||||
"text": "Checks for hate speech in the user input or model output."
|
||||
}
|
||||
],
|
||||
"parameters": {}
|
||||
},
|
||||
{
|
||||
"name": "Dangerous Content Check",
|
||||
"id": "dangerousContent",
|
||||
"supportedHooks": ["beforeRequestHook", "afterRequestHook"],
|
||||
"type": "guardrail",
|
||||
"description": [
|
||||
{
|
||||
"type": "subHeading",
|
||||
"text": "Checks for dangerous content in the user input or model output."
|
||||
}
|
||||
],
|
||||
"parameters": {}
|
||||
},
|
||||
{
|
||||
"name": "Sexual Content Check",
|
||||
"id": "sexualContent",
|
||||
"supportedHooks": ["beforeRequestHook", "afterRequestHook"],
|
||||
"type": "guardrail",
|
||||
"description": [
|
||||
{
|
||||
"type": "subHeading",
|
||||
"text": "Checks for sexual content in the user input or model output."
|
||||
}
|
||||
],
|
||||
"parameters": {}
|
||||
},
|
||||
{
|
||||
"name": "Harassment Check",
|
||||
"id": "harassment",
|
||||
"supportedHooks": ["beforeRequestHook", "afterRequestHook"],
|
||||
"type": "guardrail",
|
||||
"description": [
|
||||
{
|
||||
"type": "subHeading",
|
||||
"text": "Checks for harassment in the user input or model output."
|
||||
}
|
||||
],
|
||||
"parameters": {}
|
||||
},
|
||||
{
|
||||
"name": "Instruction Following Check",
|
||||
"id": "instructionFollowing",
|
||||
"supportedHooks": ["afterRequestHook"],
|
||||
"type": "guardrail",
|
||||
"description": [
|
||||
{
|
||||
"type": "subHeading",
|
||||
"text": "Checks that the model followed the instructions provided in the prompt."
|
||||
"text": "Checks for dangerous content, sexual content, harassment, and dangerous content in the user input or model output."
|
||||
}
|
||||
],
|
||||
"parameters": {}
|
||||
@@ -90,7 +38,18 @@
|
||||
"text": "Checks that the model did not hallucinate."
|
||||
}
|
||||
],
|
||||
"parameters": {}
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"mode": {
|
||||
"type": "string",
|
||||
"label": "Mode",
|
||||
"description": "The mode to use for the check",
|
||||
"enum": ["speed", "balanced", "quality"],
|
||||
"default": "balanced"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "PII Check",
|
||||
@@ -129,7 +88,18 @@
|
||||
"text": "Checks that the model is grounded in the context provided."
|
||||
}
|
||||
],
|
||||
"parameters": {}
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"mode": {
|
||||
"type": "string",
|
||||
"label": "Mode",
|
||||
"description": "The mode to use for the check",
|
||||
"enum": ["speed", "balanced", "quality"],
|
||||
"default": "balanced"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Tool Use Quality Check",
|
||||
@@ -142,7 +112,18 @@
|
||||
"text": "Checks the model's tool use quality. Including correct tool selection, correct tool parameters and values."
|
||||
}
|
||||
],
|
||||
"parameters": {}
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"mode": {
|
||||
"type": "string",
|
||||
"label": "Mode",
|
||||
"description": "The mode to use for the check",
|
||||
"enum": ["speed", "balanced", "quality"],
|
||||
"default": "balanced"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Policy Violations Check",
|
||||
@@ -170,6 +151,20 @@
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"mode": {
|
||||
"type": "string",
|
||||
"label": "Mode",
|
||||
"description": "The mode to use for the check",
|
||||
"enum": ["speed", "balanced", "quality"],
|
||||
"default": "balanced"
|
||||
},
|
||||
"policy_target": {
|
||||
"type": "string",
|
||||
"label": "Policy Target",
|
||||
"description": "Where to apply the policy check",
|
||||
"enum": ["input", "output", "both"],
|
||||
"default": "both"
|
||||
}
|
||||
},
|
||||
"required": ["policies"]
|
||||
|
||||
@@ -21,12 +21,24 @@ export const handler: PluginHandler = async (
|
||||
};
|
||||
}
|
||||
|
||||
const mode = parameters?.mode || 'balanced';
|
||||
const policyTarget = parameters?.policy_target || 'both';
|
||||
|
||||
const evaluationBody: any = {
|
||||
input: context.request.text,
|
||||
assertions: parameters?.policies,
|
||||
assertions_mode: mode,
|
||||
};
|
||||
|
||||
if (eventType === 'afterRequestHook') {
|
||||
// Add input based on policy_target
|
||||
if (policyTarget === 'input' || policyTarget === 'both') {
|
||||
evaluationBody.input = context.request.text;
|
||||
}
|
||||
|
||||
// Add output based on policy_target and hook type
|
||||
if (
|
||||
eventType === 'afterRequestHook' &&
|
||||
(policyTarget === 'output' || policyTarget === 'both')
|
||||
) {
|
||||
evaluationBody.output = context.response.text;
|
||||
}
|
||||
|
||||
|
||||
@@ -519,7 +519,7 @@ describe('grounding handler', () => {
|
||||
},
|
||||
];
|
||||
|
||||
it('should handle successful evaluation for afterRequestHook', async () => {
|
||||
it('should handle successful evaluation for afterRequestHook with default mode', async () => {
|
||||
const { postQualifire } = require('./globals');
|
||||
(postQualifire as jest.Mock).mockResolvedValue(testCases[0].mockResponse);
|
||||
|
||||
@@ -534,6 +534,7 @@ describe('grounding handler', () => {
|
||||
input: 'What is the capital of France?',
|
||||
output: 'The capital of France is Paris.',
|
||||
grounding_check: true,
|
||||
grounding_mode: 'balanced',
|
||||
},
|
||||
'test-api-key'
|
||||
);
|
||||
@@ -555,11 +556,39 @@ describe('grounding handler', () => {
|
||||
input: 'What is the capital of France?',
|
||||
output: 'The capital of France is Paris.',
|
||||
grounding_check: true,
|
||||
grounding_mode: 'balanced',
|
||||
},
|
||||
'test-api-key'
|
||||
);
|
||||
expect(result).toEqual(testCases[1].mockResponse);
|
||||
});
|
||||
|
||||
it('should use custom mode when provided', async () => {
|
||||
const { postQualifire } = require('./globals');
|
||||
(postQualifire as jest.Mock).mockResolvedValue(testCases[0].mockResponse);
|
||||
|
||||
const customParameters = {
|
||||
...mockParameters,
|
||||
mode: 'quality',
|
||||
};
|
||||
|
||||
const result = await groundingHandler(
|
||||
mockContext,
|
||||
customParameters,
|
||||
'afterRequestHook' as HookEventType
|
||||
);
|
||||
|
||||
expect(postQualifire).toHaveBeenCalledWith(
|
||||
{
|
||||
input: 'What is the capital of France?',
|
||||
output: 'The capital of France is Paris.',
|
||||
grounding_check: true,
|
||||
grounding_mode: 'quality',
|
||||
},
|
||||
'test-api-key'
|
||||
);
|
||||
expect(result).toEqual(testCases[0].mockResponse);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when called with unsupported event types', () => {
|
||||
@@ -662,7 +691,7 @@ describe('hallucinations handler', () => {
|
||||
},
|
||||
];
|
||||
|
||||
it('should handle successful evaluation for afterRequestHook', async () => {
|
||||
it('should handle successful evaluation for afterRequestHook with default mode', async () => {
|
||||
const { postQualifire } = require('./globals');
|
||||
(postQualifire as jest.Mock).mockResolvedValue(testCases[0].mockResponse);
|
||||
|
||||
@@ -678,6 +707,7 @@ describe('hallucinations handler', () => {
|
||||
output:
|
||||
'Quantum computing features include superposition, entanglement, and quantum interference.',
|
||||
hallucinations_check: true,
|
||||
hallucinations_mode: 'balanced',
|
||||
},
|
||||
'test-api-key'
|
||||
);
|
||||
@@ -700,11 +730,40 @@ describe('hallucinations handler', () => {
|
||||
output:
|
||||
'Quantum computing features include superposition, entanglement, and quantum interference.',
|
||||
hallucinations_check: true,
|
||||
hallucinations_mode: 'balanced',
|
||||
},
|
||||
'test-api-key'
|
||||
);
|
||||
expect(result).toEqual(testCases[1].mockResponse);
|
||||
});
|
||||
|
||||
it('should use custom mode when provided', async () => {
|
||||
const { postQualifire } = require('./globals');
|
||||
(postQualifire as jest.Mock).mockResolvedValue(testCases[0].mockResponse);
|
||||
|
||||
const customParameters = {
|
||||
...mockParameters,
|
||||
mode: 'speed',
|
||||
};
|
||||
|
||||
const result = await hallucinationsHandler(
|
||||
mockContext,
|
||||
customParameters,
|
||||
'afterRequestHook' as HookEventType
|
||||
);
|
||||
|
||||
expect(postQualifire).toHaveBeenCalledWith(
|
||||
{
|
||||
input: 'What are the main features of quantum computing?',
|
||||
output:
|
||||
'Quantum computing features include superposition, entanglement, and quantum interference.',
|
||||
hallucinations_check: true,
|
||||
hallucinations_mode: 'speed',
|
||||
},
|
||||
'test-api-key'
|
||||
);
|
||||
expect(result).toEqual(testCases[0].mockResponse);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when called with unsupported event types', () => {
|
||||
@@ -1679,7 +1738,7 @@ describe('policy handler', () => {
|
||||
},
|
||||
];
|
||||
|
||||
it('should handle successful evaluation for beforeRequestHook', async () => {
|
||||
it('should handle successful evaluation for beforeRequestHook with default parameters', async () => {
|
||||
const { postQualifire } = require('./globals');
|
||||
(postQualifire as jest.Mock).mockResolvedValue(testCases[0].mockResponse);
|
||||
|
||||
@@ -1696,6 +1755,7 @@ describe('policy handler', () => {
|
||||
'The response must be polite',
|
||||
"The assistant isn't allowed to provide any discounts, promotions or free items.",
|
||||
],
|
||||
assertions_mode: 'balanced',
|
||||
},
|
||||
'test-api-key'
|
||||
);
|
||||
@@ -1719,13 +1779,14 @@ describe('policy handler', () => {
|
||||
'The response must be polite',
|
||||
"The assistant isn't allowed to provide any discounts, promotions or free items.",
|
||||
],
|
||||
assertions_mode: 'balanced',
|
||||
},
|
||||
'test-api-key'
|
||||
);
|
||||
expect(result).toEqual(testCases[1].mockResponse);
|
||||
});
|
||||
|
||||
it('should handle successful evaluation for afterRequestHook', async () => {
|
||||
it('should handle successful evaluation for afterRequestHook with default parameters', async () => {
|
||||
const { postQualifire } = require('./globals');
|
||||
(postQualifire as jest.Mock).mockResolvedValue(testCases[0].mockResponse);
|
||||
|
||||
@@ -1744,6 +1805,7 @@ describe('policy handler', () => {
|
||||
'The response must be polite',
|
||||
"The assistant isn't allowed to provide any discounts, promotions or free items.",
|
||||
],
|
||||
assertions_mode: 'balanced',
|
||||
},
|
||||
'test-api-key'
|
||||
);
|
||||
@@ -1769,11 +1831,131 @@ describe('policy handler', () => {
|
||||
'The response must be polite',
|
||||
"The assistant isn't allowed to provide any discounts, promotions or free items.",
|
||||
],
|
||||
assertions_mode: 'balanced',
|
||||
},
|
||||
'test-api-key'
|
||||
);
|
||||
expect(result).toEqual(testCases[1].mockResponse);
|
||||
});
|
||||
|
||||
it('should use custom mode when provided', async () => {
|
||||
const { postQualifire } = require('./globals');
|
||||
(postQualifire as jest.Mock).mockResolvedValue(testCases[0].mockResponse);
|
||||
|
||||
const customParameters = {
|
||||
...mockParametersWithPolicies,
|
||||
mode: 'quality',
|
||||
};
|
||||
|
||||
const result = await policyHandler(
|
||||
mockContext,
|
||||
customParameters,
|
||||
'beforeRequestHook' as HookEventType
|
||||
);
|
||||
|
||||
expect(postQualifire).toHaveBeenCalledWith(
|
||||
{
|
||||
input: 'Can I get a discount?',
|
||||
assertions: [
|
||||
'The response must be polite',
|
||||
"The assistant isn't allowed to provide any discounts, promotions or free items.",
|
||||
],
|
||||
assertions_mode: 'quality',
|
||||
},
|
||||
'test-api-key'
|
||||
);
|
||||
expect(result).toEqual(testCases[0].mockResponse);
|
||||
});
|
||||
|
||||
it('should only check input when policy_target is "input"', async () => {
|
||||
const { postQualifire } = require('./globals');
|
||||
(postQualifire as jest.Mock).mockResolvedValue(testCases[0].mockResponse);
|
||||
|
||||
const customParameters = {
|
||||
...mockParametersWithPolicies,
|
||||
policy_target: 'input',
|
||||
};
|
||||
|
||||
const result = await policyHandler(
|
||||
mockContext,
|
||||
customParameters,
|
||||
'afterRequestHook' as HookEventType
|
||||
);
|
||||
|
||||
expect(postQualifire).toHaveBeenCalledWith(
|
||||
{
|
||||
input: 'Can I get a discount?',
|
||||
assertions: [
|
||||
'The response must be polite',
|
||||
"The assistant isn't allowed to provide any discounts, promotions or free items.",
|
||||
],
|
||||
assertions_mode: 'balanced',
|
||||
},
|
||||
'test-api-key'
|
||||
);
|
||||
expect(result).toEqual(testCases[0].mockResponse);
|
||||
});
|
||||
|
||||
it('should only check output when policy_target is "output"', async () => {
|
||||
const { postQualifire } = require('./globals');
|
||||
(postQualifire as jest.Mock).mockResolvedValue(testCases[0].mockResponse);
|
||||
|
||||
const customParameters = {
|
||||
...mockParametersWithPolicies,
|
||||
policy_target: 'output',
|
||||
};
|
||||
|
||||
const result = await policyHandler(
|
||||
mockContext,
|
||||
customParameters,
|
||||
'afterRequestHook' as HookEventType
|
||||
);
|
||||
|
||||
expect(postQualifire).toHaveBeenCalledWith(
|
||||
{
|
||||
output:
|
||||
"I apologize, but I'm not able to provide any discounts, promotions, or free items. I'd be happy to help you with other questions or information about our products and services.",
|
||||
assertions: [
|
||||
'The response must be polite',
|
||||
"The assistant isn't allowed to provide any discounts, promotions or free items.",
|
||||
],
|
||||
assertions_mode: 'balanced',
|
||||
},
|
||||
'test-api-key'
|
||||
);
|
||||
expect(result).toEqual(testCases[0].mockResponse);
|
||||
});
|
||||
|
||||
it('should check both input and output when policy_target is "both"', async () => {
|
||||
const { postQualifire } = require('./globals');
|
||||
(postQualifire as jest.Mock).mockResolvedValue(testCases[0].mockResponse);
|
||||
|
||||
const customParameters = {
|
||||
...mockParametersWithPolicies,
|
||||
policy_target: 'both',
|
||||
};
|
||||
|
||||
const result = await policyHandler(
|
||||
mockContext,
|
||||
customParameters,
|
||||
'afterRequestHook' as HookEventType
|
||||
);
|
||||
|
||||
expect(postQualifire).toHaveBeenCalledWith(
|
||||
{
|
||||
input: 'Can I get a discount?',
|
||||
output:
|
||||
"I apologize, but I'm not able to provide any discounts, promotions, or free items. I'd be happy to help you with other questions or information about our products and services.",
|
||||
assertions: [
|
||||
'The response must be polite',
|
||||
"The assistant isn't allowed to provide any discounts, promotions or free items.",
|
||||
],
|
||||
assertions_mode: 'balanced',
|
||||
},
|
||||
'test-api-key'
|
||||
);
|
||||
expect(result).toEqual(testCases[0].mockResponse);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when policies are missing', () => {
|
||||
@@ -1957,7 +2139,7 @@ describe('toolUseQuality handler', () => {
|
||||
},
|
||||
];
|
||||
|
||||
it('should handle successful evaluation for afterRequestHook', async () => {
|
||||
it('should handle successful evaluation for afterRequestHook with default mode', async () => {
|
||||
const {
|
||||
postQualifire,
|
||||
convertToMessages,
|
||||
@@ -2031,6 +2213,7 @@ describe('toolUseQuality handler', () => {
|
||||
},
|
||||
],
|
||||
tool_selection_quality_check: true,
|
||||
tsq_mode: 'balanced',
|
||||
},
|
||||
'test-api-key'
|
||||
);
|
||||
@@ -2079,6 +2262,87 @@ describe('toolUseQuality handler', () => {
|
||||
|
||||
expect(result).toEqual(testCases[1].mockResponse);
|
||||
});
|
||||
|
||||
it('should use custom mode when provided', async () => {
|
||||
const {
|
||||
postQualifire,
|
||||
convertToMessages,
|
||||
parseAvailableTools,
|
||||
} = require('./globals');
|
||||
(postQualifire as jest.Mock).mockResolvedValue(testCases[0].mockResponse);
|
||||
(convertToMessages as jest.Mock).mockReturnValue([
|
||||
{ role: 'user', content: "What's the weather like in New York?" },
|
||||
{
|
||||
role: 'assistant',
|
||||
content: null,
|
||||
tool_calls: [
|
||||
{
|
||||
id: 'call_123',
|
||||
name: 'get_weather',
|
||||
arguments: { location: 'New York' },
|
||||
},
|
||||
],
|
||||
},
|
||||
]);
|
||||
(parseAvailableTools as jest.Mock).mockReturnValue([
|
||||
{
|
||||
name: 'get_weather',
|
||||
description: 'Get weather information for a location',
|
||||
parameters: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
location: { type: 'string' },
|
||||
},
|
||||
},
|
||||
},
|
||||
]);
|
||||
|
||||
const customParameters = {
|
||||
...mockParameters,
|
||||
mode: 'speed',
|
||||
};
|
||||
|
||||
const result = await toolUseQualityHandler(
|
||||
mockContext,
|
||||
customParameters,
|
||||
'afterRequestHook' as HookEventType
|
||||
);
|
||||
|
||||
expect(postQualifire).toHaveBeenCalledWith(
|
||||
{
|
||||
messages: [
|
||||
{ role: 'user', content: "What's the weather like in New York?" },
|
||||
{
|
||||
role: 'assistant',
|
||||
content: null,
|
||||
tool_calls: [
|
||||
{
|
||||
id: 'call_123',
|
||||
name: 'get_weather',
|
||||
arguments: { location: 'New York' },
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
available_tools: [
|
||||
{
|
||||
name: 'get_weather',
|
||||
description: 'Get weather information for a location',
|
||||
parameters: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
location: { type: 'string' },
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
tool_selection_quality_check: true,
|
||||
tsq_mode: 'speed',
|
||||
},
|
||||
'test-api-key'
|
||||
);
|
||||
expect(result).toEqual(testCases[0].mockResponse);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when called with unsupported event types', () => {
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
import {
|
||||
HookEventType,
|
||||
PluginContext,
|
||||
PluginHandler,
|
||||
PluginParameters,
|
||||
} from '../types';
|
||||
import { postQualifire } from './globals';
|
||||
|
||||
export const handler: PluginHandler = async (
|
||||
context: PluginContext,
|
||||
parameters: PluginParameters,
|
||||
eventType: HookEventType
|
||||
) => {
|
||||
const evaluationBody: any = {
|
||||
input: context.request.text,
|
||||
sexual_content_check: true,
|
||||
};
|
||||
|
||||
if (eventType === 'afterRequestHook') {
|
||||
evaluationBody.output = context.response.text;
|
||||
}
|
||||
|
||||
try {
|
||||
return await postQualifire(evaluationBody, parameters?.credentials?.apiKey);
|
||||
} catch (e: any) {
|
||||
delete e.stack;
|
||||
return { error: e, verdict: false, data: null };
|
||||
}
|
||||
};
|
||||
@@ -26,10 +26,13 @@ export const handler: PluginHandler = async (
|
||||
};
|
||||
}
|
||||
|
||||
const mode = parameters?.mode || 'balanced';
|
||||
|
||||
const evaluationBody: any = {
|
||||
messages: convertToMessages(context.request, context.response),
|
||||
available_tools: parseAvailableTools(context.request),
|
||||
tool_selection_quality_check: true,
|
||||
tsq_mode: mode,
|
||||
};
|
||||
|
||||
try {
|
||||
|
||||
Reference in New Issue
Block a user