mirror of
https://github.com/danny-avila/LibreChat.git
synced 2025-12-16 16:30:15 +01:00
📚 feat: Add Source Citations for File Search in Agents (#8652)
* 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>
This commit is contained in:
parent
a955097faf
commit
52e59e40be
36 changed files with 1890 additions and 190 deletions
|
|
@ -1,6 +1,6 @@
|
|||
import React, { ReactNode } from 'react';
|
||||
import * as Ariakit from '@ariakit/react';
|
||||
import { ChevronDown } from 'lucide-react';
|
||||
import { ChevronDown, Paperclip } from 'lucide-react';
|
||||
import { VisuallyHidden } from '@ariakit/react';
|
||||
import { useLocalize } from '~/hooks';
|
||||
import { cn } from '~/utils';
|
||||
|
|
@ -17,6 +17,8 @@ interface SourceHovercardProps {
|
|||
label: string;
|
||||
onMouseEnter?: () => void;
|
||||
onMouseLeave?: () => void;
|
||||
onClick?: (e: React.MouseEvent) => void;
|
||||
isFile?: boolean;
|
||||
children?: ReactNode;
|
||||
}
|
||||
|
||||
|
|
@ -46,6 +48,8 @@ export function SourceHovercard({
|
|||
label,
|
||||
onMouseEnter,
|
||||
onMouseLeave,
|
||||
onClick,
|
||||
isFile = false,
|
||||
children,
|
||||
}: SourceHovercardProps) {
|
||||
const localize = useLocalize();
|
||||
|
|
@ -57,16 +61,27 @@ export function SourceHovercard({
|
|||
<span className="flex items-center">
|
||||
<Ariakit.HovercardAnchor
|
||||
render={
|
||||
<a
|
||||
href={source.link}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="ml-1 inline-block h-5 max-w-36 cursor-pointer items-center overflow-hidden text-ellipsis whitespace-nowrap rounded-xl border border-border-heavy bg-surface-secondary px-2 text-xs font-medium no-underline transition-colors hover:bg-surface-hover dark:border-border-medium dark:hover:bg-surface-tertiary"
|
||||
onMouseEnter={onMouseEnter}
|
||||
onMouseLeave={onMouseLeave}
|
||||
>
|
||||
{label}
|
||||
</a>
|
||||
isFile ? (
|
||||
<button
|
||||
onClick={onClick}
|
||||
className="ml-1 inline-block h-5 max-w-36 cursor-pointer items-center overflow-hidden text-ellipsis whitespace-nowrap rounded-xl border border-border-heavy bg-surface-secondary px-2 text-xs font-medium text-blue-600 no-underline transition-colors hover:bg-surface-hover dark:border-border-medium dark:text-blue-400 dark:hover:bg-surface-tertiary"
|
||||
onMouseEnter={onMouseEnter}
|
||||
onMouseLeave={onMouseLeave}
|
||||
>
|
||||
{label}
|
||||
</button>
|
||||
) : (
|
||||
<a
|
||||
href={source.link}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="ml-1 inline-block h-5 max-w-36 cursor-pointer items-center overflow-hidden text-ellipsis whitespace-nowrap rounded-xl border border-border-heavy bg-surface-secondary px-2 text-xs font-medium no-underline transition-colors hover:bg-surface-hover dark:border-border-medium dark:hover:bg-surface-tertiary"
|
||||
onMouseEnter={onMouseEnter}
|
||||
onMouseLeave={onMouseLeave}
|
||||
>
|
||||
{label}
|
||||
</a>
|
||||
)
|
||||
}
|
||||
/>
|
||||
<Ariakit.HovercardDisclosure className="ml-0.5 rounded-full text-text-primary focus:outline-none focus:ring-2 focus:ring-ring">
|
||||
|
|
@ -84,24 +99,51 @@ export function SourceHovercard({
|
|||
{!children && (
|
||||
<>
|
||||
<span className="mb-2 flex items-center">
|
||||
<FaviconImage domain={domain} className="mr-2" />
|
||||
<a
|
||||
href={source.link}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="line-clamp-2 cursor-pointer overflow-hidden text-sm font-bold text-[#0066cc] hover:underline dark:text-blue-400 md:line-clamp-3"
|
||||
>
|
||||
{source.attribution || domain}
|
||||
</a>
|
||||
{isFile ? (
|
||||
<div className="mr-2 flex h-4 w-4 items-center justify-center">
|
||||
<Paperclip className="h-3 w-3 text-text-secondary" />
|
||||
</div>
|
||||
) : (
|
||||
<FaviconImage domain={domain} className="mr-2" />
|
||||
)}
|
||||
{isFile ? (
|
||||
<button
|
||||
onClick={onClick}
|
||||
className="line-clamp-2 cursor-pointer overflow-hidden text-left text-sm font-bold text-[#0066cc] hover:underline dark:text-blue-400 md:line-clamp-3"
|
||||
>
|
||||
{source.attribution || source.title || localize('com_file_source')}
|
||||
</button>
|
||||
) : (
|
||||
<a
|
||||
href={source.link}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="line-clamp-2 cursor-pointer overflow-hidden text-sm font-bold text-[#0066cc] hover:underline dark:text-blue-400 md:line-clamp-3"
|
||||
>
|
||||
{source.attribution || domain}
|
||||
</a>
|
||||
)}
|
||||
</span>
|
||||
|
||||
<h4 className="mb-1.5 mt-0 text-xs text-text-primary md:text-sm">
|
||||
{source.title || source.link}
|
||||
</h4>
|
||||
{source.snippet && (
|
||||
<span className="my-2 text-ellipsis break-all text-xs text-text-secondary md:text-sm">
|
||||
{source.snippet}
|
||||
</span>
|
||||
{isFile ? (
|
||||
<>
|
||||
{source.snippet && (
|
||||
<span className="my-2 text-ellipsis break-all text-xs text-text-secondary md:text-sm">
|
||||
{source.snippet}
|
||||
</span>
|
||||
)}
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<h4 className="mb-1.5 mt-0 text-xs text-text-primary md:text-sm">
|
||||
{source.title || source.link}
|
||||
</h4>
|
||||
{source.snippet && (
|
||||
<span className="my-2 text-ellipsis break-all text-xs text-text-secondary md:text-sm">
|
||||
{source.snippet}
|
||||
</span>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue