Skip to content

Commit

Permalink
Merge branch 'main' into fix/max-completion-tokens
Browse files Browse the repository at this point in the history
  • Loading branch information
VisargD authored Sep 27, 2024
2 parents 95fedc7 + f3ed2b1 commit 3b1c139
Show file tree
Hide file tree
Showing 10 changed files with 1,325 additions and 9 deletions.
1,202 changes: 1,202 additions & 0 deletions cookbook/use-cases/Contextual Embeddings Guide Anthropic, Cohere, Voyage.ipynb

Large diffs are not rendered by default.

49 changes: 49 additions & 0 deletions plugins/default/default.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { handler as sentenceCountHandler } from './sentenceCount';
import { handler as webhookHandler } from './webhook';
import { handler as logHandler } from './log';
import { handler as allUppercaseHandler } from './alluppercase';
import { handler as endsWithHandler } from './endsWith';

import { z } from 'zod';
import { PluginContext, PluginParameters } from '../types';
Expand Down Expand Up @@ -705,3 +706,51 @@ describe('allUppercase handler', () => {
expect(result.verdict).toBe(false);
});
});
describe('endsWith handler', () => {
it('should return true verdict if response ends with provided suffix', async () => {
const eventType = 'afterRequestHook';
const context: PluginContext = {
response: {
text: 'This is a sentence that ends with the expected word i.e. HarryPortkey.',
},
};
const parameters: PluginParameters = {
suffix: 'HarryPortkey',
};
const result = await endsWithHandler(context, parameters, eventType);
expect(result.error).toBe(null);
expect(result.verdict).toBe(true);
});
it('should return false verdict if response not ending with provided suffix', async () => {
const context: PluginContext = {
response: {
text: 'This is a sentence ending with wrong word i.e. MalfoyPortkey.',
},
};
const eventType = 'afterRequestHook';

const parameters: PluginParameters = {
suffix: 'HarryPortkey',
};

const result = await endsWithHandler(context, parameters, eventType);
expect(result.error).toBe(null);
expect(result.verdict).toBe(false);
});

it('should return error for missing suffix in parameters', async () => {
const context: PluginContext = {
response: { text: 'This is a sentence which ends with Portkey.' },
};
const eventType = 'afterRequestHook';

const parameters: PluginParameters = {};

const result = await endsWithHandler(context, parameters, eventType);

expect(result.error).toBeInstanceOf(Error);
expect(result.error?.message).toBe('Missing suffix or text');
expect(result.verdict).toBe(false);
expect(result.data).toBe(null);
});
});
32 changes: 32 additions & 0 deletions plugins/default/endsWith.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import {
HookEventType,
PluginContext,
PluginHandler,
PluginParameters,
} from '../types';
import { getText } from '../utils';

export const handler: PluginHandler = async (
context: PluginContext,
parameters: PluginParameters,
eventType: HookEventType
) => {
let error = null;
let verdict = false;
let data = null;

try {
const suffix = parameters.suffix;
let text = getText(context, eventType);

if (suffix !== undefined && '' !== suffix && text.length >= 0) {
verdict = text.endsWith(suffix) || text.endsWith(`${suffix}.`);
} else {
error = error || new Error('Missing suffix or text');
}
} catch (e) {
error = e as Error;
}

return { error, verdict, data };
};
15 changes: 11 additions & 4 deletions plugins/default/webhook.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,26 @@
import { PluginContext, PluginHandler, PluginParameters } from '../types';
import { post } from '../utils';

function parseHeaders(headers: unknown): Record<string, string> {
if (typeof headers === 'object' && headers !== null) {
return headers as Record<string, string>;
}
if (typeof headers === 'string') {
return JSON.parse(headers);
}
return {};
}

export const handler: PluginHandler = async (
context: PluginContext,
parameters: PluginParameters
) => {
let error = null;
let verdict = false;
let data = null;

try {
let url = parameters.webhookURL;
let headers: Record<string, string> = parameters?.headers
? JSON.parse(parameters.headers)
: {};
const headers = parseHeaders(parameters.headers);
({ verdict, data } = await post(url, context, { headers }, 3000));
} catch (e: any) {
delete e.stack;
Expand Down
2 changes: 2 additions & 0 deletions src/handlers/handlerUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1120,6 +1120,8 @@ export function constructConfigFromRequestHeaders(
anthropicConfig),
...(requestHeaders[`x-${POWERED_BY}-provider`] === HUGGING_FACE &&
huggingfaceConfig),
mistralFimCompletion:
requestHeaders[`x-${POWERED_BY}-mistral-fim-completion`],
};
}

Expand Down
7 changes: 7 additions & 0 deletions src/providers/azure-openai/chatComplete.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,13 @@ export const AzureOpenAIChatCompleteConfig: ProviderConfig = {
param: 'n',
default: 1,
},
logprobs: {
param: 'logprobs',
default: false,
},
top_logprobs: {
param: 'top_logprobs',
},
stream: {
param: 'stream',
default: false,
Expand Down
4 changes: 2 additions & 2 deletions src/providers/bedrock/chatComplete.ts
Original file line number Diff line number Diff line change
Expand Up @@ -383,7 +383,7 @@ export const BedrockLLamaChatCompleteConfig: ProviderConfig = {
let messages: Message[] = params.messages;
messages.forEach((msg, index) => {
if (index === 0 && msg.role === 'system') {
prompt += `system: ${messages}\n`;
prompt += `system: ${msg.content}\n`;
} else if (msg.role == 'user') {
prompt += `user: ${msg.content}\n`;
} else if (msg.role == 'assistant') {
Expand Down Expand Up @@ -433,7 +433,7 @@ export const BedrockMistralChatCompleteConfig: ProviderConfig = {
let messages: Message[] = params.messages;
messages.forEach((msg, index) => {
if (index === 0 && msg.role === 'system') {
prompt += `system: ${messages}\n`;
prompt += `system: ${msg.content}\n`;
} else if (msg.role == 'user') {
prompt += `user: ${msg.content}\n`;
} else if (msg.role == 'assistant') {
Expand Down
10 changes: 8 additions & 2 deletions src/providers/mistral-ai/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,18 @@ const MistralAIAPIConfig: ProviderAPIConfig = {
headers: ({ providerOptions }) => {
return { Authorization: `Bearer ${providerOptions.apiKey}` };
},
getEndpoint: ({ fn }) => {
switch (fn) {
getEndpoint: ({ fn, providerOptions }) => {
let mappedfn = fn;
if (providerOptions.mistralFimCompletion === 'true') {
mappedfn = 'fimComplete';
}
switch (mappedfn) {
case 'chatComplete':
return '/chat/completions';
case 'embed':
return '/embeddings';
case 'fimComplete':
return '/fim/completions';
default:
return '';
}
Expand Down
10 changes: 10 additions & 0 deletions src/providers/mistral-ai/chatComplete.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,16 @@ export const MistralAIChatCompleteConfig: ProviderConfig = {
param: 'safe_prompt',
default: false,
},
prompt: {
param: 'prompt',
required: false,
default: '',
},
suffix: {
param: 'suffix',
required: false,
default: '',
},
};

interface MistralAIChatCompleteResponse extends ChatCompletionResponse {
Expand Down
3 changes: 2 additions & 1 deletion src/types/requestBody.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,8 @@ export interface Options {

/** The parameter to determine if extra non-openai compliant fields should be returned in response */
strictOpenAiCompliance?: boolean;

/** Parameter to determine if fim/completions endpoint is to be used */
mistralFimCompletion?: String;
/** Anthropic specific headers */
anthropicBeta?: string;
anthropicVersion?: string;
Expand Down

0 comments on commit 3b1c139

Please sign in to comment.