Skip to content
Open
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
4 changes: 2 additions & 2 deletions package-lock.json

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

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@librechat/agents",
"version": "3.1.78",
"version": "3.1.79",
"main": "./dist/cjs/main.cjs",
"module": "./dist/esm/main.mjs",
"types": "./dist/types/index.d.ts",
Expand Down
78 changes: 78 additions & 0 deletions src/tools/search/cohere-reranker.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import { CohereReranker } from './rerankers';
import { createDefaultLogger } from './utils';

describe('CohereReranker', () => {
const mockLogger = createDefaultLogger();

describe('constructor', () => {
it('should use default API URL when no apiUrl is provided', () => {
const originalEnv = process.env.COHERE_API_URL;
delete process.env.COHERE_API_URL;

const reranker = new CohereReranker({
apiKey: 'test-key',
logger: mockLogger,
});

// Access private property for testing
const apiUrl = (reranker as unknown as { apiUrl: string }).apiUrl;
expect(apiUrl).toBe('https://api.cohere.com/v2/rerank');

if (originalEnv) {
process.env.COHERE_API_URL = originalEnv;
}
});

it('should use custom API URL when provided', () => {
const customUrl = 'https://my-azure.endpoint.com/v1/rerank';
const reranker = new CohereReranker({
apiKey: 'test-key',
apiUrl: customUrl,
logger: mockLogger,
});

const apiUrl = (reranker as unknown as { apiUrl: string }).apiUrl;
expect(apiUrl).toBe(customUrl);
});

it('should use environment variable COHERE_API_URL when available', () => {
const originalEnv = process.env.COHERE_API_URL;
process.env.COHERE_API_URL = 'https://env-cohere.example.com/v2/rerank';

const reranker = new CohereReranker({
apiKey: 'test-key',
logger: mockLogger,
});

const apiUrl = (reranker as unknown as { apiUrl: string }).apiUrl;
expect(apiUrl).toBe('https://env-cohere.example.com/v2/rerank');

if (originalEnv) {
process.env.COHERE_API_URL = originalEnv;
} else {
delete process.env.COHERE_API_URL;
}
});

it('should prioritize explicit apiUrl over environment variable', () => {
const originalEnv = process.env.COHERE_API_URL;
process.env.COHERE_API_URL = 'https://env-cohere.example.com/v2/rerank';

const customUrl = 'https://explicit-cohere.example.com/v2/rerank';
const reranker = new CohereReranker({
apiKey: 'test-key',
apiUrl: customUrl,
logger: mockLogger,
});

const apiUrl = (reranker as unknown as { apiUrl: string }).apiUrl;
expect(apiUrl).toBe(customUrl);

if (originalEnv) {
process.env.COHERE_API_URL = originalEnv;
} else {
delete process.env.COHERE_API_URL;
}
});
});
});
38 changes: 32 additions & 6 deletions src/tools/search/rerankers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,9 @@ export class JinaReranker extends BaseReranker {
documents: string[],
topK: number = 5
): Promise<t.Highlight[]> {
this.logger.debug(`Reranking ${documents.length} chunks with Jina using API URL: ${this.apiUrl}`);
this.logger.debug(
`Reranking ${documents.length} chunks with Jina using API URL: ${this.apiUrl}`
);

try {
if (this.apiKey == null || this.apiKey === '') {
Expand Down Expand Up @@ -115,23 +117,30 @@ export class JinaReranker extends BaseReranker {
}

export class CohereReranker extends BaseReranker {
private apiUrl: string;

constructor({
apiKey = process.env.COHERE_API_KEY,
apiUrl = process.env.COHERE_API_URL || 'https://api.cohere.com/v2/rerank',
logger,
}: {
apiKey?: string;
apiUrl?: string;
logger?: t.Logger;
}) {
super(logger);
this.apiKey = apiKey;
this.apiUrl = apiUrl;
}

async rerank(
query: string,
documents: string[],
topK: number = 5
): Promise<t.Highlight[]> {
this.logger.debug(`Reranking ${documents.length} chunks with Cohere`);
this.logger.debug(
`Reranking ${documents.length} chunks with Cohere using API URL: ${this.apiUrl}`
);

try {
if (this.apiKey == null || this.apiKey === '') {
Expand All @@ -147,7 +156,7 @@ export class CohereReranker extends BaseReranker {
};

const response = await axios.post<t.CohereRerankerResponse | undefined>(
'https://api.cohere.com/v2/rerank',
this.apiUrl,
requestData,
{
headers: {
Expand Down Expand Up @@ -208,19 +217,32 @@ export const createReranker = (config: {
jinaApiKey?: string;
jinaApiUrl?: string;
cohereApiKey?: string;
cohereApiUrl?: string;
logger?: t.Logger;
}): BaseReranker | undefined => {
const { rerankerType, jinaApiKey, jinaApiUrl, cohereApiKey, logger } = config;
const {
rerankerType,
jinaApiKey,
jinaApiUrl,
cohereApiKey,
cohereApiUrl,
logger,
} = config;

// Create a default logger if none is provided
const defaultLogger = logger || createDefaultLogger();

switch (rerankerType.toLowerCase()) {
case 'jina':
return new JinaReranker({ apiKey: jinaApiKey, apiUrl: jinaApiUrl, logger: defaultLogger });
return new JinaReranker({
apiKey: jinaApiKey,
apiUrl: jinaApiUrl,
logger: defaultLogger,
});
case 'cohere':
return new CohereReranker({
apiKey: cohereApiKey,
apiUrl: cohereApiUrl,
logger: defaultLogger,
});
case 'infinity':
Expand All @@ -232,7 +254,11 @@ export const createReranker = (config: {
defaultLogger.warn(
`Unknown reranker type: ${rerankerType}. Defaulting to InfinityReranker.`
);
return new JinaReranker({ apiKey: jinaApiKey, apiUrl: jinaApiUrl, logger: defaultLogger });
return new JinaReranker({
apiKey: jinaApiKey,
apiUrl: jinaApiUrl,
logger: defaultLogger,
});
}
};

Expand Down
2 changes: 2 additions & 0 deletions src/tools/search/tool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -354,6 +354,7 @@ export const createSearchTool = (
jinaApiKey,
jinaApiUrl,
cohereApiKey,
cohereApiUrl,
onSearchResults: _onSearchResults,
onGetHighlights,
} = config;
Expand Down Expand Up @@ -433,6 +434,7 @@ export const createSearchTool = (
jinaApiKey,
jinaApiUrl,
cohereApiKey,
cohereApiUrl,
logger,
});

Expand Down
1 change: 1 addition & 0 deletions src/tools/search/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,7 @@ export interface SearchToolConfig
jinaApiKey?: string;
jinaApiUrl?: string;
cohereApiKey?: string;
cohereApiUrl?: string;
rerankerType?: RerankerType;
scraperProvider?: ScraperProvider;
scraperTimeout?: number;
Expand Down