fix: 匹配markdown

This commit is contained in:
imeepos
2025-07-22 15:57:36 +08:00
parent f92d9a7c39
commit 725514af2d
5 changed files with 507 additions and 61 deletions

View File

@@ -60,6 +60,10 @@ export const EnhancedMarkdownRenderer: React.FC<EnhancedMarkdownRendererProps> =
try {
// 解析Markdown
const result = await markdownService.parseMarkdown(content);
console.log({
content: content.length,
result: result.source_text.length
})
setParseResult(result);
// 验证文档结构
@@ -89,16 +93,90 @@ export const EnhancedMarkdownRenderer: React.FC<EnhancedMarkdownRendererProps> =
}
}, [parseContent, enableRealTimeParsing]);
// 渲染单个Markdown节点
const renderNode = useCallback((node: MarkdownNode, depth: number = 0): React.ReactNode => {
const key = `${node.range?.start?.line || 0}-${node.range?.start?.column || 0}-${depth}`;
// 分析节点与引用资源的关联
const analyzeNodeGrounding = useCallback((node: MarkdownNode) => {
if (!groundingMetadata?.grounding_supports || !parseResult) {
return null;
}
// 计算节点在原始文本中的字符偏移位置
const nodeStartOffset = node.range?.start?.offset || 0;
const nodeEndOffset = node.range?.end?.offset || 0;
// 查找与当前节点位置重叠的grounding支持信息
const relatedSupports = groundingMetadata.grounding_supports.filter(support => {
// 这里是字符串二进制的offset
const segmentStart = support.segment.startIndex;
const segmentEnd = support.segment.endIndex;
const hasOverlap = (nodeEndOffset <= segmentEnd && nodeStartOffset >= segmentStart);
// 检查节点范围与grounding片段是否有重叠
return hasOverlap;
});
if (relatedSupports.length > 0) {
// 获取相关的来源信息
const relatedSources = relatedSupports.flatMap(support =>
support.groundingChunkIndices.map(index => groundingMetadata.sources[index])
).filter(Boolean);
const analysisResult = {
node: {
type: node.node_type,
content: node.content.substring(0, 100) + (node.content.length > 100 ? '...' : ''),
position: {
start: nodeStartOffset,
end: nodeEndOffset,
line: node.range?.start?.line,
column: node.range?.start?.column
}
},
groundingInfo: {
supportCount: relatedSupports.length,
sourceCount: relatedSources.length,
sources: relatedSources.map(source => ({
title: source.title,
uri: source.uri,
snippet: source.content?.snippet || 'No snippet available'
})),
segments: relatedSupports.map(support => ({
start: support.segment.startIndex,
end: support.segment.endIndex,
chunkIndices: support.groundingChunkIndices
}))
}
};
console.log('🔗 节点引用分析:', analysisResult);
return analysisResult;
}
return null;
}, [groundingMetadata, parseResult]);
// 渲染单个Markdown节点
const renderNode = useCallback((node: MarkdownNode, depth: number = 0, index: number = 0): React.ReactNode => {
const key = `${node.range?.start?.line || 0}-${node.range?.start?.column || 0}-${node.range?.start?.offset || 0}-${depth}-${index}`;
// 分析当前节点的引用关联
const groundingAnalysis = analyzeNodeGrounding(node);
// 创建引用指示器组件
const GroundingIndicator = groundingAnalysis ? (
<span
className="inline-flex items-center ml-1 px-1 py-0.5 text-xs bg-blue-100 text-blue-700 rounded cursor-help"
title={`引用了 ${groundingAnalysis.groundingInfo.sourceCount} 个来源`}
onClick={() => {
console.log('📚 点击查看引用详情:', groundingAnalysis);
// 这里可以添加弹窗或侧边栏显示详细引用信息
}}
>
📚 {groundingAnalysis.groundingInfo.sourceCount}
</span>
) : null;
// 尝试使用 groundingMetadata 解析出来 当前节点引用的那部分资源 然后打印
switch (node.node_type) {
case MarkdownNodeType.Document:
return (
<div key={key} className="markdown-document">
{node.children.map((child) => renderNode(child, depth + 1))}
{node.children.map((child, childIndex) => renderNode(child, depth + 1, childIndex))}
</div>
);
@@ -113,16 +191,18 @@ export const EnhancedMarkdownRenderer: React.FC<EnhancedMarkdownRendererProps> =
5: 'font-medium mb-1 text-sm',
6: 'font-medium mb-1 text-xs'
};
return (+
return (
<HeadingTag key={key} className={headingClasses[level as keyof typeof headingClasses] || headingClasses[3]}>
{node.children.map((child) => renderNode(child, depth + 1))}
{node.children.map((child, childIndex) => renderNode(child, depth + 1, childIndex))}
{GroundingIndicator}
</HeadingTag>
);
case MarkdownNodeType.Paragraph:
return (
<p key={key} className="mb-2">
{node.children.map((child) => renderNode(child, depth + 1))}
{node.children.map((child, childIndex) => renderNode(child, depth + 1, childIndex))}
{GroundingIndicator}
</p>
);
@@ -132,14 +212,14 @@ export const EnhancedMarkdownRenderer: React.FC<EnhancedMarkdownRendererProps> =
const listClass = isOrdered ? 'list-decimal ml-4 mb-2' : 'list-disc ml-4 mb-2';
return (
<ListTag key={key} className={listClass}>
{node.children.map((child) => renderNode(child, depth + 1))}
{node.children.map((child, childIndex) => renderNode(child, depth + 1, childIndex))}
</ListTag>
);
case MarkdownNodeType.ListItem:
return (
<li key={key} className="mb-1">
{node.children.map((child) => renderNode(child, depth + 1))}
{node.children.map((child, childIndex) => renderNode(child, depth + 1, childIndex))}
</li>
);
@@ -172,7 +252,7 @@ export const EnhancedMarkdownRenderer: React.FC<EnhancedMarkdownRendererProps> =
target="_blank"
rel="noopener noreferrer"
>
{node.children.map((child) => renderNode(child, depth + 1))}
{node.children.map((child, childIndex) => renderNode(child, depth + 1, childIndex))}
</a>
);
@@ -191,21 +271,21 @@ export const EnhancedMarkdownRenderer: React.FC<EnhancedMarkdownRendererProps> =
case MarkdownNodeType.Strong:
return (
<strong key={key}>
{node.children.map((child) => renderNode(child, depth + 1))}
{node.children.map((child, childIndex) => renderNode(child, depth + 1, childIndex))}
</strong>
);
case MarkdownNodeType.Emphasis:
return (
<em key={key}>
{node.children.map((child) => renderNode(child, depth + 1))}
{node.children.map((child, childIndex) => renderNode(child, depth + 1, childIndex))}
</em>
);
case MarkdownNodeType.Blockquote:
return (
<blockquote key={key} className="border-l-4 border-gray-300 pl-4 italic text-gray-600 mb-2">
{node.children.map((child) => renderNode(child, depth + 1))}
{node.children.map((child, childIndex) => renderNode(child, depth + 1, childIndex))}
</blockquote>
);
@@ -218,11 +298,12 @@ export const EnhancedMarkdownRenderer: React.FC<EnhancedMarkdownRendererProps> =
default:
return (
<div key={key} className="unknown-node">
{node.children.map((child) => renderNode(child, depth + 1))}
{node.children.map((child, childIndex) => renderNode(child, depth + 1, childIndex))}
</div>
);
}
}, []);
}, [analyzeNodeGrounding]);
return (
<div className={`enhanced-markdown-renderer ${className}`}>