Skip to content

Commit

Permalink
馃悰 fix: fix Perplexity duplicate token
Browse files Browse the repository at this point in the history
  • Loading branch information
arvinxx committed May 9, 2024
1 parent 0e01db0 commit 6695c4b
Show file tree
Hide file tree
Showing 4 changed files with 32 additions and 83 deletions.
7 changes: 5 additions & 2 deletions src/app/api/chat/agentRuntime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,9 +93,12 @@ const getLlmOptionsFromPayload = (provider: string, payload: JWTPayload) => {
return { baseURL };
}
case ModelProvider.Perplexity: {
const { PERPLEXITY_API_KEY } = getServerConfig();
const { PERPLEXITY_API_KEY, PERPLEXITY_PROXY_URL } = getServerConfig();

const apiKey = apiKeyManager.pick(payload?.apiKey || PERPLEXITY_API_KEY);
return { apiKey };
const baseURL = payload?.endpoint || PERPLEXITY_PROXY_URL;

return { apiKey, baseURL };
}
case ModelProvider.Anthropic: {
const { ANTHROPIC_API_KEY, ANTHROPIC_PROXY_URL } = getServerConfig();
Expand Down
2 changes: 2 additions & 0 deletions src/config/server/provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ declare global {
// Perplexity Provider
ENABLED_PERPLEXITY?: string;
PERPLEXITY_API_KEY?: string;
PERPLEXITY_PROXY_URL?: string;

// Anthropic Provider
ENABLED_ANTHROPIC?: string;
Expand Down Expand Up @@ -173,6 +174,7 @@ export const getProviderConfig = () => {

ENABLED_PERPLEXITY: !!PERPLEXITY_API_KEY,
PERPLEXITY_API_KEY,
PERPLEXITY_PROXY_URL: process.env.PERPLEXITY_PROXY_URL,

ENABLED_ANTHROPIC: !!ANTHROPIC_API_KEY,
ANTHROPIC_API_KEY,
Expand Down
4 changes: 2 additions & 2 deletions src/libs/agent-runtime/perplexity/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import OpenAI from 'openai';
import { Mock, afterEach, beforeEach, describe, expect, it, vi } from 'vitest';

import { ChatStreamCallbacks } from '@/libs/agent-runtime';
import { ChatStreamCallbacks, LobeOpenAICompatibleRuntime } from '@/libs/agent-runtime';

import * as debugStreamModule from '../utils/debugStream';
import { LobePerplexityAI } from './index';
Expand All @@ -15,7 +15,7 @@ const invalidErrorType = 'InvalidPerplexityAPIKey';
// Mock the console.error to avoid polluting test output
vi.spyOn(console, 'error').mockImplementation(() => {});

let instance: LobePerplexityAI;
let instance: LobeOpenAICompatibleRuntime;

beforeEach(() => {
instance = new LobePerplexityAI({ apiKey: 'test' });
Expand Down
102 changes: 23 additions & 79 deletions src/libs/agent-runtime/perplexity/index.ts
Original file line number Diff line number Diff line change
@@ -1,85 +1,29 @@
import { OpenAIStream, StreamingTextResponse } from 'ai';
import OpenAI, { ClientOptions } from 'openai';
import OpenAI from 'openai';

import { LobeRuntimeAI } from '../BaseAI';
import { AgentRuntimeErrorType } from '../error';
import { ChatCompetitionOptions, ChatStreamPayload, ModelProvider } from '../types';
import { AgentRuntimeError } from '../utils/createError';
import { debugStream } from '../utils/debugStream';
import { desensitizeUrl } from '../utils/desensitizeUrl';
import { handleOpenAIError } from '../utils/handleOpenAIError';
import { ChatStreamPayload, ModelProvider } from '../types';
import { LobeOpenAICompatibleFactory } from '../utils/openaiCompatibleFactory';

const DEFAULT_BASE_URL = 'https://api.perplexity.ai';

export class LobePerplexityAI implements LobeRuntimeAI {
private client: OpenAI;

baseURL: string;

constructor({ apiKey, baseURL = DEFAULT_BASE_URL, ...res }: ClientOptions) {
if (!apiKey) throw AgentRuntimeError.createError(AgentRuntimeErrorType.InvalidPerplexityAPIKey);

this.client = new OpenAI({ apiKey, baseURL, ...res });
this.baseURL = this.client.baseURL;
}

async chat(payload: ChatStreamPayload, options?: ChatCompetitionOptions) {
try {
export const LobePerplexityAI = LobeOpenAICompatibleFactory({
baseURL: 'https://api.perplexity.ai',
chatCompletion: {
handlePayload: (payload: ChatStreamPayload) => {
// Set a default frequency penalty value greater than 0
const defaultFrequencyPenalty = 0.1;
const chatPayload = {
const defaultFrequencyPenalty = 1;

return {
...payload,
frequency_penalty: payload.frequency_penalty || defaultFrequencyPenalty,
};
const response = await this.client.chat.completions.create(
chatPayload as unknown as OpenAI.ChatCompletionCreateParamsStreaming,
{ signal: options?.signal },
);
const [prod, debug] = response.tee();

if (process.env.DEBUG_PERPLEXITY_CHAT_COMPLETION === '1') {
debugStream(debug.toReadableStream()).catch(console.error);
}

return new StreamingTextResponse(OpenAIStream(prod, options?.callback), {
headers: options?.headers,
});
} catch (error) {
let desensitizedEndpoint = this.baseURL;

if (this.baseURL !== DEFAULT_BASE_URL) {
desensitizedEndpoint = desensitizeUrl(this.baseURL);
}

if ('status' in (error as any)) {
switch ((error as Response).status) {
case 401: {
throw AgentRuntimeError.chat({
endpoint: desensitizedEndpoint,
error: error as any,
errorType: AgentRuntimeErrorType.InvalidPerplexityAPIKey,
provider: ModelProvider.Perplexity,
});
}

default: {
break;
}
}
}

const { errorResult, RuntimeError } = handleOpenAIError(error);

const errorType = RuntimeError || AgentRuntimeErrorType.PerplexityBizError;

throw AgentRuntimeError.chat({
endpoint: desensitizedEndpoint,
error: errorResult,
errorType,
provider: ModelProvider.Perplexity,
});
}
}
}

export default LobePerplexityAI;
stream: true,
} as OpenAI.ChatCompletionCreateParamsStreaming;
},
},
debug: {
chatCompletion: () => process.env.DEBUG_PERPLEXITY_CHAT_COMPLETION === '1',
},
errorType: {
bizError: AgentRuntimeErrorType.PerplexityBizError,
invalidAPIKey: AgentRuntimeErrorType.InvalidPerplexityAPIKey,
},
provider: ModelProvider.Perplexity,
});

0 comments on commit 6695c4b

Please sign in to comment.