Citelab / htmls /pipeline copy.html
SHEN1017's picture
Upload 97 files
96b6673 verified
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Pipeline Graph</title>
<script src="https://d3js.org/d3.v7.min.js"></script>
<style>
* {
font-family: Arial, sans-serif;
}
.container {
width: 95%;
height: 40vh;
margin: 20px auto; /* 新增居中 */
position: relative; /* 新增定位 */
}
.title {
font: 24px/1.5 'Arial', sans-serif;
color: #6b7b8c;
text-align: center;
padding: 12px 0;
}
.node rect {
rx: 8px;
ry: 8px;
stroke-width: 1.5;
}
.node text {
font: 12px sans-serif;
pointer-events: none;
text-anchor: middle;
dominant-baseline: central;
}
.link {
fill: none;
stroke-width: 2;
stroke-opacity: 0.6;
}
.tooltip {
position: absolute;
padding: 8px;
background: #fff9ec;
border: 1px solid #ffd8a8;
border-radius: 4px;
box-shadow: 3px 3px 10px rgba(0,0,0,0.1);
font: 12px/1.5 sans-serif;
color: #66512c;
}
.lower-container {
width: 95%;
height: 45vh;
margin: 20px auto;
display: flex;
gap: 20px;
}
.doc-panel, .info-panel {
height: 50vh;
flex: 1;
background: #f8f9fa;
border: 2px solid #B5C4B8;
border-radius: 12px;
padding: 15px;
}
#doc-list {
max-height: 95%;
overflow-y: auto;
}
.qa-box {
border-top: 2px solid #ecf0f1;
padding-top: 15px;
padding-bottom: 15px;
margin-bottom: 15px;
max-height: 30%;
overflow-y: auto;
}
.qa-question {
color: #2c3e50;
font-weight: 600;
margin-bottom: 12px;
max-height: 10%;
overflow-y: auto;
}
.qa-answer {
color: #34495e;
line-height: 1.6;
}
/* 在现有样式中添加 */
#output-box {
border-top: 2px solid #ecf0f1;
padding-top: 15px;
max-height: 50%;
overflow-y: auto;
}
/* 文档项样式 */
.doc-item {
border: 1px solid #B5C4B8;
border-radius: 8px;
padding: 12px;
margin-bottom: 10px;
background: #fff;
box-shadow: 0 2px 6px rgba(175, 189, 188, 0.1);
}
.color-display {
display: flex;
align-items: center;
gap: 8px;
margin-left: 20px;
}
.color-box {
width: 24px;
height: 24px;
border: 1px solid #ddd;
border-radius: 4px;
}
.value-display {
font-size: 0.9em;
min-width: 120px;
color: #666;
}
/* 答案分句样式 */
.sentence-box {
border: 1px solid #e0e7e9;
border-radius: 6px;
padding: 10px;
margin: 8px 0;
background: #f8fafb;
line-height: 1.5;
}
.output-line:hover {
background: #f0f0f0;
}
/* 输出结果样式调整 */
.output-line {
border-left: 3px solid #B5C4B8;
margin: 6px 0;
cursor: pointer;
padding: 8px 12px;
background: #fdfdfd;
border-radius: 4px;
}
</style>
</head>
<body>
<div id="graph-container" class="container"></div>
<div id="tooltip" class="tooltip" style="opacity:0"></div>
<!-- 原有上半部分代码保持不变... -->
<div class="lower-container">
<!-- 左半部文档列表 -->
<div class="doc-panel">
<div class="panel-title"> Documents</div>
<div id="doc-list" class="doc-list"></div>
</div>
<!-- 右半部信息面板 -->
<div class="info-panel">
<!-- 问题回答区域 -->
<div class="qa-box">
<div id="current-question" class="qa-question"></div>
<div id="current-answer" class="qa-answer"></div>
</div>
<!-- 控制面板 -->
<div class="control-box">
<label>Show Result:
<select id="result-select" onchange="updateResult(this.value)">
<option value="0">Result 1</option><option value="1">Result 2</option>
</select>
</label>
<label style="margin-left:20px">Granularity:
<select id="granularity">
<option>Document-level</option>
<option>Span-level</option>
<option>Word-level</option>
</select>
</label>
<div class="color-display">
<div class="color-box"></div>
<div class="value-display">Click document to show value</div>
</div>
</div>
<!-- 输出结果 -->
<div id="output-box" class="output-box"></div>
</div>
</div>
<script>
const nodes = [{"id": "input", "type": "input", "params": {}}, {"id": "output", "type": "output", "params": {}}, {"id": "gpt-3.5-turbo-[1]", "type": "Generator", "params": {"type": "Generator"}}, {"id": "verifier-[4]", "type": "verifier", "params": {"type": "verifier"}}, {"id": "gpt-3.5-turbo-[5]", "type": "Generator", "params": {"type": "Generator"}}, {"id": "retriever-[6]", "type": "retriever", "params": {"type": "retriever"}}, {"id": "gpt-3.5-turbo-[2]", "type": "Generator", "params": {"type": "Generator"}}, {"id": "simplifier-[3]", "type": "simplifier", "params": {"type": "simplifier"}}];
const edges = [{"source": "input", "target": "gpt-3.5-turbo-[1]", "weight": 0}, {"source": "gpt-3.5-turbo-[2]", "target": "verifier-[4]", "weight": 0}, {"source": "retriever-[6]", "target": "gpt-3.5-turbo-[2]", "weight": 0}, {"source": "gpt-3.5-turbo-[5]", "target": "retriever-[6]", "weight": 0}, {"source": "verifier-[4]", "target": "gpt-3.5-turbo-[5]", "weight": -1}, {"source": "verifier-[4]", "target": "simplifier-[3]", "weight": 1}, {"source": "simplifier-[3]", "target": "output", "weight": 0}, {"source": "gpt-3.5-turbo-[1]", "target": "verifier-[4]", "weight": 0}];
const colors = ['#B5C4B8', '#D3C0B6', '#A9B7C4', '#C4A9B7', '#B7C4A9'];
const container = d3.select("#graph-container");
const width = container.node().offsetWidth;
const height = container.node().offsetHeight;
let currentGranularity = "Document-level"; // 添加在script顶部变量声明处
// 在script顶部添加
let currentSentenceIndex = null;
let currentDocValues = [];
const svg = container.append("svg")
.attr("width", width)
.attr("height", height);
svg.append("defs").append("marker")
.attr("id", "arrow")
.attr("viewBox", "0 -5 10 10")
.attr("refX", 32)
.attr("markerWidth", 8)
.attr("markerHeight", 8)
.attr("orient", "auto")
.append("path")
.attr("d", "M0,-4L8,0L0,4")
.attr("fill", "#7E8A97");
svg.append("rect")
.attr("width", width-2)
.attr("height", height-2)
.attr("x", 1)
.attr("y", 1)
.attr("rx", 12)
.attr("ry", 12)
.attr("fill", "none")
.attr("stroke", "#B5C4B8")
.attr("stroke-width", 2)
.lower();
const simulation = d3.forceSimulation(nodes)
.force("link", d3.forceLink(edges).id(d => d.id).distance(120))
.force("charge", d3.forceManyBody().strength(-400))
.force("collide", d3.forceCollide().radius(42))
.force("x", d3.forceX()
.x(d => {
if (d.id === 'input') return width * 0.1;
if (d.id === 'output') return width * 0.9;
return width / 2;
})
.strength(0.1))
.force("y", d3.forceY(height/2).strength(0.05))
.force("center", null);
const link = svg.selectAll(".link")
.data(edges)
.enter().append("line")
.attr("class", "link")
.attr("stroke", d => d.weight === 1 ? "green" : d.weight === -1 ? "red" : "black")
.attr("marker-end", "url(#arrow)")
.style("stroke-dasharray", d => d.weight === 0 ? "4 4" : null);
const node = svg.selectAll(".node")
.data(nodes)
.enter().append("g")
.attr("class", "node")
.call(d3.drag()
.on("start", dragstart)
.on("drag", dragging)
.on("end", dragend))
.on("mouseover", showTooltip)
.on("mouseout", hideTooltip);
node.append("rect")
.attr("width", 80)
.attr("height", 36)
.attr("x", -40)
.attr("y", -18)
.attr("fill", d => colors[d.type.length % colors.length])
.attr("stroke", "#7E8A97");
node.append("text")
.text(d => d.type)
.attr("dy", 0);
simulation.on("tick", () => {
link.attr("x1", d => d.source.x)
.attr("y1", d => d.source.y)
.attr("x2", d => d.target.x)
.attr("y2", d => d.target.y);
node.attr("transform", d => `translate(${d.x},${d.y})`);
});
const tooltip = d3.select("#tooltip");
function showTooltip(event, d) {
tooltip.transition().style("opacity", 0.9);
const params = Object.entries(d.params)
.filter(([k]) => k !== 'type')
.map(([k,v]) => `${k}: ${v}`)
.join('<br/>');
tooltip.html(`<strong>${d.type}</strong><br/>${params}`)
.style("left", (event.pageX + 15) + "px")
.style("top", (event.pageY - 15) + "px");
}
function hideTooltip() { tooltip.transition().style("opacity", 0); }
function formatDocumentText(d) {
const match = d.match(/\[([\d]+)\]\(Title:(.*?)\)(.*)/);
if (match) {
const number = match[1];
const title = match[2];
const content = match[3];
return `[${number}] <strong>${title}</strong>: ${content}`;
}
return d;
}
function dragstart(event, d) {
if (!event.active) simulation.alphaTarget(0.3).restart();
d.fx = d.x;
d.fy = d.y;
}
function dragging(event, d) {
d.fx = event.x;
d.fy = event.y;
}
function dragend(event, d) {
if (!event.active) simulation.alphaTarget(0);
d.fx = null;
d.fy = null;
}
let allResults;
fetch('res_attr.json')
.then(response => response.json())
.then(data => {
allResults = data;
updateResult(0);
})
.catch(error => {
console.error('Error loading JSON file:', error);
});
function highlightDocsBySentence(sentenceIndex) {
const currentResult = allResults[document.getElementById("result-select").value];
currentDocValues = currentResult.doc_level[sentenceIndex];
currentSentenceIndex = sentenceIndex;
const docValues = currentResult.doc_level[sentenceIndex];
// 归一化处理
const maxVal = Math.max(...docValues);
const minVal = Math.min(...docValues);
const range = maxVal - minVal || 1; // 防止除零
d3.selectAll(".doc-item")
.style("background", (d, j) => {
const normalized = (docValues[j] - minVal) / range;
return getColor(normalized);
});
}
function updateResult(selectedIndex) {
const result = allResults[selectedIndex];
// 在updateResult函数开始添加
currentSentenceIndex = null;
currentDocValues = [];
d3.select(".color-box")
.style("background", "none")
.style("border-color", "#ddd");
d3.select(".value-display")
.text("Click document to show value")
.style("color", "#666");
// 修改updateResult函数中的doc-list部分
const docList = d3.select("#doc-list")
.html("")
.selectAll(".doc-item")
.data(result.doc_cache.map((d, j) => ({
text: d,
index: j
}))) // 绑定文档索引
.enter()
.append("div")
.classed("doc-item", true)
.html(d => `
<div class="doc-content">${formatDocumentText(d.text)}</div>
`)
.on("click", function(event, d) {
if (currentGranularity === "Document-level" && currentSentenceIndex !== null) {
const rawValue = currentDocValues[d.index];
const normalized = (rawValue - Math.min(...currentDocValues)) /
(Math.max(...currentDocValues) - Math.min(...currentDocValues) || 1);
d3.select(".color-box")
.style("background", getColor(normalized))
.style("border-color", "#999");
d3.select(".value-display")
.text(`Value: ${rawValue.toFixed(4)}`)
.style("color", "#333");
}
});
d3.select("#current-question").html(`❓ ${result.data.question}`);
d3.select("#current-answer").html(`📖 ${result.data.answer}`);
d3.select("#output-box")
.html("")
.selectAll(".output-line")
.data(result.output.map((d, i) => ({ text: d, index: i }))) // 这里添加映射
.enter()
.append("div")
.classed("output-line", true)
.html(d => `
<div class="output-text">${d.text}</div>
`)
.on("click", function(event, d) {
if (currentGranularity === "Document-level") {
highlightDocsBySentence(d.index); // 直接使用d.index
}
});
}
// 在updateResult函数之后添加
d3.select("#granularity").on("change", function() {
currentGranularity = this.value;
clearDocHighlights(); // 切换粒度时清除高亮
currentSentenceIndex = null;
currentDocValues = [];
});
// 清除高亮的函数
function clearDocHighlights() {
d3.selectAll(".doc-item").style("background", "none");
}
// 颜色映射函数(归一化到红色系)
function getColor(value) {
const alpha = value * 0.8 + 0.2; // 保证最小可见度
return `rgba(255,50,50,${alpha})`;
}
</script>
</body>
</html>