Browse Source

临时提交

main
pd 4 days ago
parent
commit
34dbaa9aa7
  1. 250
      deepsearcher/backend/templates/index.html

250
deepsearcher/backend/templates/index.html

@ -1,9 +1,17 @@
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<head>
<meta charset="UTF-8" />
<meta
name="viewport"
content="width=device-width, initial-scale=1.0"
/>
<title>DeepSearcher - 智能搜索系统</title>
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
<link
rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/github-markdown-css@5.1.0/github-markdown-light.css"
/>
<style>
:root {
--primary-color: #4f46e5;
@ -81,7 +89,9 @@
font-weight: 500;
}
input, textarea, select {
input,
textarea,
select {
width: 100%;
padding: 10px 12px;
border: 1px solid var(--border-color);
@ -90,7 +100,9 @@
transition: border-color 0.15s;
}
input:focus, textarea:focus, select:focus {
input:focus,
textarea:focus,
select:focus {
outline: none;
border-color: var(--primary-color);
box-shadow: 0 0 0 3px rgba(79, 70, 229, 0.1);
@ -185,8 +197,12 @@
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
.loading .loading-spinner {
@ -286,12 +302,14 @@
}
}
</style>
</head>
<body>
</head>
<body>
<div class="container">
<header>
<h1>DeepSearcher 智能搜索系统</h1>
<p class="app-description">基于大型语言模型和向量数据库的企业知识管理系统,支持私有数据搜索和在线内容整合,提供准确答案和综合报告。</p>
<p class="app-description">
基于大型语言模型和向量数据库的企业知识管理系统,支持私有数据搜索和在线内容整合,提供准确答案和综合报告。
</p>
</header>
<main>
@ -299,61 +317,124 @@
<h2 class="card-title">文件加载</h2>
<div class="form-group">
<label for="filePaths">文件路径(多个路径用逗号分隔)</label>
<input type="text" id="filePaths" placeholder="例如: /path/to/file1.pdf,/path/to/file2.txt">
<input
type="text"
id="filePaths"
placeholder="例如: /path/to/file1.pdf,/path/to/file2.txt"
/>
</div>
<div class="form-group">
<label for="collectionName">集合名称(可选)</label>
<input type="text" id="collectionName" placeholder="例如: my_collection">
<input
type="text"
id="collectionName"
placeholder="例如: my_collection"
/>
</div>
<div class="form-group">
<label for="collectionDesc">集合描述(可选)</label>
<textarea id="collectionDesc" rows="2" placeholder="例如: 这是一个测试集合"></textarea>
<textarea
id="collectionDesc"
rows="2"
placeholder="例如: 这是一个测试集合"
></textarea>
</div>
<button id="loadFilesBtn">加载文件</button>
<div id="loadStatus" class="status"></div>
<div
id="loadStatus"
class="status"
></div>
</div>
<div class="card">
<h2 class="card-title">网站内容加载</h2>
<div class="form-group">
<label for="websiteUrls">网站URL(多个URL用逗号分隔)</label>
<input type="text" id="websiteUrls" placeholder="例如: https://example.com/page1,https://example.com/page2">
<input
type="text"
id="websiteUrls"
placeholder="例如: https://example.com/page1,https://example.com/page2"
/>
</div>
<div class="form-group">
<label for="webCollectionName">集合名称(可选)</label>
<input type="text" id="webCollectionName" placeholder="例如: web_collection">
<input
type="text"
id="webCollectionName"
placeholder="例如: web_collection"
/>
</div>
<div class="form-group">
<label for="webCollectionDesc">集合描述(可选)</label>
<textarea id="webCollectionDesc" rows="2" placeholder="例如: 来自网站的内容"></textarea>
<textarea
id="webCollectionDesc"
rows="2"
placeholder="例如: 来自网站的内容"
></textarea>
</div>
<button id="loadWebsiteBtn">加载网站内容</button>
<div id="webLoadStatus" class="status"></div>
<div
id="webLoadStatus"
class="status"
></div>
</div>
<div class="card">
<h2 class="card-title">智能查询</h2>
<div class="form-group">
<label for="queryText">请输入您的问题</label>
<textarea id="queryText" rows="3" placeholder="例如: 请生成一份关于人工智能发展趋势的报告"></textarea>
<textarea
id="queryText"
rows="3"
placeholder="例如: 请生成一份关于人工智能发展趋势的报告"
></textarea>
</div>
<div class="form-group">
<label for="maxIter">最大迭代次数 (1-10)</label>
<input type="number" id="maxIter" min="1" max="10" value="3">
<input
type="number"
id="maxIter"
min="1"
max="10"
value="3"
/>
</div>
<button id="queryBtn">执行查询</button>
<button id="clearMessagesBtn" style="margin-left: 10px; background-color: var(--text-secondary);">清空消息</button>
<div id="queryStatus" class="status"></div>
<div id="queryResult" class="result-container">
<button
id="clearMessagesBtn"
style="margin-left: 10px; background-color: var(--text-secondary)"
>
清空消息
</button>
<div
id="queryStatus"
class="status"
></div>
<div
id="queryResult"
class="result-container"
>
<h3>查询结果:</h3>
<div class="query-result" id="resultText"></div>
<div
class="query-result"
id="resultText"
></div>
</div>
<div id="processResult" class="result-container">
<div
id="processResult"
class="result-container"
>
<h3>处理过程:</h3>
<div id="messageStream" class="message-stream">
<div class="message-container" id="messageContainer"></div>
<div
id="messageStream"
class="message-stream"
>
<div
class="message-container"
id="messageContainer"
></div>
</div>
</div>
</div>
@ -374,7 +455,11 @@
const statusElement = document.getElementById(elementId);
// 清除之前的类型类
statusElement.classList.remove('status-success', 'status-error', 'status-loading');
statusElement.classList.remove(
'status-success',
'status-error',
'status-loading'
);
// 添加新的类型类
if (type === 'success') {
@ -396,7 +481,7 @@
const container = document.getElementById('messageContainer');
container.innerHTML = '';
messages.forEach(message => {
messages.forEach((message) => {
addMessageToContainer(message);
});
@ -436,14 +521,21 @@
// 确保处理过程容器是可见的
const processContainer = document.getElementById('processResult');
if (processContainer && !processContainer.classList.contains('visible')) {
if (
processContainer &&
!processContainer.classList.contains('visible')
) {
processContainer.classList.add('visible');
}
// 滚动到底部
container.scrollTop = container.scrollHeight;
console.log('Message added successfully, container now has', container.children.length, 'messages');
console.log(
'Message added successfully, container now has',
container.children.length,
'messages'
);
}
// 工具函数:隐藏状态信息
@ -485,7 +577,9 @@
'"': '&quot;',
"'": '&#039;'
};
return text.replace(/[&<>"']/g, function(m) { return map[m]; });
return text.replace(/[&<>"']/g, function (m) {
return map[m];
});
}
// 工具函数:设置按钮加载状态
@ -507,7 +601,9 @@
eventSource = null;
}
if (window.currentEventSource) {
console.log('Closing currentEventSource in closeEventSource function');
console.log(
'Closing currentEventSource in closeEventSource function'
);
window.currentEventSource.close();
window.currentEventSource = null;
}
@ -543,7 +639,9 @@
}
isStreaming = false;
setButtonLoading(document.getElementById('queryBtn'), false);
console.log('Query completed - connection closed, isStreaming set to false');
console.log(
'Query completed - connection closed, isStreaming set to false'
);
break;
case 'error':
console.error('Error:', message.content);
@ -559,15 +657,28 @@
break;
case 'info':
// 处理信息消息
console.log('Processing info message:', message.content.substring(0, 100) + '...');
console.log(
'Processing info message:',
message.content.substring(0, 100) + '...'
);
addMessageToContainer(message);
break;
case 'answer':
// 处理answer类型,显示查询结果
console.log('Processing answer message:', message.content.substring(0, 100) + '...');
console.log(
'Processing answer message:',
message.content.substring(0, 100) + '...'
);
// 将结果内容显示在结果区域
if (message.content && message.content !== "==== FINAL ANSWER====") {
document.getElementById('resultText').textContent = message.content;
if (
message.content &&
message.content !== '==== FINAL ANSWER===='
) {
// document.getElementById('resultText').textContent =
// marked.parse(message.content);
document.getElementById('resultText').innerHTML = marked.parse(
message.content
);
showResult();
}
// 不将answer消息添加到处理过程容器中,只显示在查询结果框中
@ -586,15 +697,15 @@
eventSource = new EventSource('/stream-messages/');
eventSource.onopen = function(event) {
eventSource.onopen = function (event) {
console.log('EventSource connection opened');
};
eventSource.onmessage = function(event) {
eventSource.onmessage = function (event) {
handleStreamMessage(event.data);
};
eventSource.onerror = function(event) {
eventSource.onerror = function (event) {
console.error('EventSource error:', event);
if (eventSource.readyState === EventSource.CLOSED) {
console.log('EventSource connection closed');
@ -603,18 +714,25 @@
}
// 加载文件功能
document.getElementById('loadFilesBtn').addEventListener('click', async function() {
document
.getElementById('loadFilesBtn')
.addEventListener('click', async function () {
const button = this;
const filePathsInput = document.getElementById('filePaths').value;
const collectionName = document.getElementById('collectionName').value;
const collectionDesc = document.getElementById('collectionDesc').value;
const collectionName =
document.getElementById('collectionName').value;
const collectionDesc =
document.getElementById('collectionDesc').value;
if (!filePathsInput) {
showStatus('loadStatus', '请提供至少一个文件路径', 'error');
return;
}
const filePaths = filePathsInput.split(',').map(path => path.trim()).filter(path => path);
const filePaths = filePathsInput
.split(',')
.map((path) => path.trim())
.filter((path) => path);
setButtonLoading(button, true);
showStatus('loadStatus', '正在加载文件...', 'loading');
@ -649,7 +767,9 @@
});
// 清空消息功能
document.getElementById('clearMessagesBtn').addEventListener('click', async function() {
document
.getElementById('clearMessagesBtn')
.addEventListener('click', async function () {
try {
const response = await fetch('/clear-messages/', {
method: 'POST',
@ -683,18 +803,25 @@
});
// 加载网站内容功能
document.getElementById('loadWebsiteBtn').addEventListener('click', async function() {
document
.getElementById('loadWebsiteBtn')
.addEventListener('click', async function () {
const button = this;
const urlsInput = document.getElementById('websiteUrls').value;
const collectionName = document.getElementById('webCollectionName').value;
const collectionDesc = document.getElementById('webCollectionDesc').value;
const collectionName =
document.getElementById('webCollectionName').value;
const collectionDesc =
document.getElementById('webCollectionDesc').value;
if (!urlsInput) {
showStatus('webLoadStatus', '请提供至少一个网站URL', 'error');
return;
}
const urls = urlsInput.split(',').map(url => url.trim()).filter(url => url);
const urls = urlsInput
.split(',')
.map((url) => url.trim())
.filter((url) => url);
setButtonLoading(button, true);
showStatus('webLoadStatus', '正在加载网站内容...', 'loading');
@ -729,7 +856,9 @@
});
// 查询功能 - 使用实时流
document.getElementById('queryBtn').addEventListener('click', async function() {
document
.getElementById('queryBtn')
.addEventListener('click', async function () {
const button = this;
const queryText = document.getElementById('queryText').value;
const maxIter = parseInt(document.getElementById('maxIter').value);
@ -771,22 +900,26 @@
}
// 使用EventSource直接连接到查询流
const eventSource = new EventSource(`/query-stream/?original_query=${encodeURIComponent(queryText)}&max_iter=${maxIter}`);
const eventSource = new EventSource(
`/query-stream/?original_query=${encodeURIComponent(
queryText
)}&max_iter=${maxIter}`
);
// 保存EventSource引用以便后续关闭
window.currentEventSource = eventSource;
eventSource.onopen = function(event) {
eventSource.onopen = function (event) {
console.log('EventSource connection opened for query');
showStatus('queryStatus', ' 正在处理...', 'loading');
};
eventSource.onmessage = function(event) {
eventSource.onmessage = function (event) {
console.log('Received message:', event.data);
handleStreamMessage(event.data);
};
eventSource.onerror = function(event) {
eventSource.onerror = function (event) {
console.error('EventSource error:', event);
if (eventSource.readyState === EventSource.CLOSED) {
console.log('EventSource connection closed due to error');
@ -795,7 +928,6 @@
window.currentEventSource = null;
}
};
} catch (error) {
console.error('Query error:', error);
showStatus('queryStatus', `请求失败: ${error.message}`, 'error');
@ -805,12 +937,12 @@
});
// 页面卸载时清理连接
window.addEventListener('beforeunload', function() {
window.addEventListener('beforeunload', function () {
if (window.currentEventSource) {
window.currentEventSource.close();
window.currentEventSource = null;
}
});
</script>
</body>
</body>
</html>
Loading…
Cancel
Save