mirror of
https://github.com/danny-avila/LibreChat.git
synced 2025-12-17 08:50:15 +01:00
* feat: Source Citations for file_search in Agents * Fix: Added citation limits and relevance score to app service. Removed duplicate tests * ✨ feat: implement Role-level toggle to optionally disable file Source Citation in Agents * 🐛 fix: update mock for librechat-data-provider to include PermissionTypes and SystemRoles --------- Co-authored-by: “Praneeth <praneeth.goparaju@slalom.com>
106 lines
2.7 KiB
TypeScript
106 lines
2.7 KiB
TypeScript
import { createContext, useContext } from 'react';
|
|
import type { SearchRefType, ValidSource, ResultReference } from 'librechat-data-provider';
|
|
import type * as t from './types';
|
|
import { useSearchContext } from '~/Providers';
|
|
|
|
export interface CitationContextType {
|
|
hoveredCitationId: string | null;
|
|
setHoveredCitationId: (id: string | null) => void;
|
|
}
|
|
|
|
export const CitationContext = createContext<CitationContextType>({
|
|
hoveredCitationId: null,
|
|
setHoveredCitationId: () => {},
|
|
});
|
|
|
|
export function useHighlightState(citationId: string | undefined) {
|
|
const { hoveredCitationId } = useContext(CitationContext);
|
|
return citationId && hoveredCitationId === citationId;
|
|
}
|
|
|
|
export type CitationSource = (ValidSource | ResultReference) & {
|
|
turn: number;
|
|
refType: string | SearchRefType;
|
|
index: number;
|
|
};
|
|
|
|
const refTypeMap: Record<string | SearchRefType, string> = {
|
|
search: 'organic',
|
|
ref: 'references',
|
|
news: 'topStories',
|
|
file: 'references',
|
|
};
|
|
|
|
export function useCitation({
|
|
turn,
|
|
index,
|
|
refType: _refType,
|
|
}: {
|
|
turn: number;
|
|
index: number;
|
|
refType?: SearchRefType | string;
|
|
}): (t.Citation & t.Reference) | undefined {
|
|
const { searchResults } = useSearchContext();
|
|
if (!_refType) {
|
|
return undefined;
|
|
}
|
|
const refType = refTypeMap[_refType.toLowerCase()]
|
|
? refTypeMap[_refType.toLowerCase()]
|
|
: _refType;
|
|
|
|
if (!searchResults || !searchResults[turn] || !searchResults[turn][refType]) {
|
|
return undefined;
|
|
}
|
|
|
|
const source: CitationSource = searchResults[turn][refType][index];
|
|
|
|
if (!source) {
|
|
return undefined;
|
|
}
|
|
|
|
return {
|
|
...source,
|
|
turn,
|
|
refType: _refType.toLowerCase(),
|
|
index,
|
|
link: source.link ?? '',
|
|
title: source.title ?? '',
|
|
snippet: source['snippet'] ?? '',
|
|
attribution: source.attribution ?? '',
|
|
};
|
|
}
|
|
|
|
export function useCompositeCitations(
|
|
citations: Array<{ turn: number; refType: SearchRefType | string; index: number }>,
|
|
): Array<t.Citation & t.Reference> {
|
|
const { searchResults } = useSearchContext();
|
|
|
|
const result: Array<t.Citation & t.Reference> = [];
|
|
|
|
for (const { turn, refType: _refType, index } of citations) {
|
|
const refType = refTypeMap[_refType.toLowerCase()]
|
|
? refTypeMap[_refType.toLowerCase()]
|
|
: _refType;
|
|
|
|
if (!searchResults || !searchResults[turn] || !searchResults[turn][refType]) {
|
|
continue;
|
|
}
|
|
const source: CitationSource = searchResults[turn][refType][index];
|
|
if (!source) {
|
|
continue;
|
|
}
|
|
|
|
result.push({
|
|
...source,
|
|
turn,
|
|
refType: _refType.toLowerCase(),
|
|
index,
|
|
link: source.link ?? '',
|
|
title: source.title ?? '',
|
|
snippet: source['snippet'] ?? '',
|
|
attribution: source.attribution ?? '',
|
|
});
|
|
}
|
|
|
|
return result;
|
|
}
|