mirror of
https://gitee.com/wanwujie/deer-flow
synced 2026-04-10 01:04:46 +08:00
Check the output links are hallucinations from AI (#139)
* feat: check output links if a hallucination from AI
This commit is contained in:
50
web/src/components/deer-flow/link.tsx
Normal file
50
web/src/components/deer-flow/link.tsx
Normal file
@@ -0,0 +1,50 @@
|
||||
import { useEffect, useMemo } from "react";
|
||||
import { useToolCalls } from "~/core/store";
|
||||
import { cn } from "~/lib/utils";
|
||||
import { Tooltip } from "./tooltip";
|
||||
|
||||
export const Link = ({
|
||||
href,
|
||||
children,
|
||||
}: {
|
||||
href: string | undefined;
|
||||
children: React.ReactNode;
|
||||
}) => {
|
||||
const toolCalls = useToolCalls();
|
||||
const credibleLinks = useMemo(() => {
|
||||
const links = new Set<string>();
|
||||
(toolCalls || []).forEach((call) => {
|
||||
if (call && call.name === "web_search" && call.result) {
|
||||
const result = JSON.parse(call.result) as Array<{ url: string }>;
|
||||
result.forEach((r) => {
|
||||
links.add(r.url);
|
||||
});
|
||||
}
|
||||
});
|
||||
return links;
|
||||
}, [toolCalls]);
|
||||
const isCredible = useMemo(() => {
|
||||
return href ? credibleLinks.has(href) : true;
|
||||
}, [credibleLinks, href]);
|
||||
|
||||
if (isCredible) {
|
||||
return (
|
||||
<Tooltip title="This link might be a hallucination from AI model and may not be reliable.">
|
||||
<a
|
||||
href={href}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className={cn(isCredible && "after:ml-0.5 after:content-['⚠️']")}
|
||||
>
|
||||
{children}
|
||||
</a>
|
||||
</Tooltip>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<a href={href} target="_blank" rel="noopener noreferrer">
|
||||
{children}
|
||||
</a>
|
||||
);
|
||||
};
|
||||
@@ -18,13 +18,10 @@ import { cn } from "~/lib/utils";
|
||||
|
||||
import Image from "./image";
|
||||
import { Tooltip } from "./tooltip";
|
||||
import { Link } from "./link";
|
||||
|
||||
const components: ReactMarkdownOptions["components"] = {
|
||||
a: ({ href, children }) => (
|
||||
<a href={href} target="_blank" rel="noopener noreferrer">
|
||||
{children}
|
||||
</a>
|
||||
),
|
||||
a: ({ href, children }) => <Link href={href}>{children}</Link>,
|
||||
img: ({ src, alt }) => (
|
||||
<a href={src as string} target="_blank" rel="noopener noreferrer">
|
||||
<Image className="rounded" src={src as string} alt={alt ?? ""} />
|
||||
@@ -52,13 +49,7 @@ export function Markdown({
|
||||
return [rehypeKatex];
|
||||
}, [animated]);
|
||||
return (
|
||||
<div
|
||||
className={cn(
|
||||
className,
|
||||
"prose dark:prose-invert prose-p:my-0 prose-img:mt-0 flex flex-col gap-4",
|
||||
)}
|
||||
style={style}
|
||||
>
|
||||
<div className={cn(className, "prose dark:prose-invert")} style={style}>
|
||||
<ReactMarkdown
|
||||
remarkPlugins={[remarkGfm, remarkMath]}
|
||||
rehypePlugins={rehypePlugins}
|
||||
|
||||
Reference in New Issue
Block a user