diff --git a/deepsearcher/backend/templates/index.html b/deepsearcher/backend/templates/index.html
index a0ef791..465eaad 100644
--- a/deepsearcher/backend/templates/index.html
+++ b/deepsearcher/backend/templates/index.html
@@ -14,6 +14,7 @@
--success-color: #10b981;
--error-color: #ef4444;
--warning-color: #f59e0b;
+ --info-color: #3b82f6;
}
* {
@@ -191,6 +192,29 @@
line-height: 1.6;
}
+ /* 进度日志样式 */
+ .progress-log {
+ background-color: #1e1e1e;
+ color: #d4d4d4;
+ border-radius: 6px;
+ padding: 16px;
+ font-family: 'Courier New', monospace;
+ font-size: 14px;
+ margin: 16px 0;
+ max-height: 300px;
+ overflow-y: auto;
+ display: none;
+ }
+
+ .progress-log.visible {
+ display: block;
+ }
+
+ .progress-log-entry {
+ margin: 4px 0;
+ line-height: 1.4;
+ }
+
footer {
text-align: center;
margin-top: 30px;
@@ -266,6 +290,10 @@
查询结果:
@@ -319,6 +347,37 @@
resultElement.classList.remove('visible');
}
+ // 工具函数:显示进度日志
+ function showProgressLog(messages) {
+ const logElement = document.getElementById('progressLog');
+ if (messages && messages.length > 0) {
+ logElement.innerHTML = messages.map(msg =>
+ `
${escapeHtml(msg)}
`
+ ).join('');
+ logElement.classList.add('visible');
+ } else {
+ logElement.classList.remove('visible');
+ }
+ }
+
+ // 工具函数:隐藏进度日志
+ function hideProgressLog() {
+ const logElement = document.getElementById('progressLog');
+ logElement.classList.remove('visible');
+ }
+
+ // 工具函数:转义HTML特殊字符
+ function escapeHtml(text) {
+ const map = {
+ '&': '&',
+ '<': '<',
+ '>': '>',
+ '"': '"',
+ "'": '''
+ };
+ return text.replace(/[&<>"']/g, function(m) { return map[m]; });
+ }
+
// 工具函数:设置按钮加载状态
function setButtonLoading(button, loading) {
if (loading) {
@@ -347,6 +406,7 @@
setButtonLoading(button, true);
showStatus('loadStatus', '正在加载文件...', 'loading');
hideResult();
+ hideProgressLog();
try {
const response = await fetch('/load-files/', {
@@ -392,6 +452,7 @@
setButtonLoading(button, true);
showStatus('webLoadStatus', '正在加载网站内容...', 'loading');
hideResult();
+ hideProgressLog();
try {
const response = await fetch('/load-website/', {
@@ -439,6 +500,7 @@
setButtonLoading(button, true);
showStatus('queryStatus', '正在处理查询...', 'loading');
hideResult();
+ hideProgressLog();
try {
const response = await fetch(`/query/?original_query=${encodeURIComponent(queryText)}&max_iter=${maxIter}`, {
@@ -455,6 +517,9 @@
document.getElementById('resultText').textContent = data.result;
document.getElementById('tokenInfo').textContent = `消耗Token数: ${data.consume_token}`;
showResult();
+
+ // 显示进度日志
+ showProgressLog(data.progress_messages);
} else {
showStatus('queryStatus', `查询失败: ${data.detail}`, 'error');
}
diff --git a/deepsearcher/utils/log.py b/deepsearcher/utils/log.py
index f6771de..eedbe25 100644
--- a/deepsearcher/utils/log.py
+++ b/deepsearcher/utils/log.py
@@ -1,5 +1,6 @@
import logging
-
+import io
+from typing import List
from termcolor import colored
@@ -50,6 +51,44 @@ class ColoredFormatter(logging.Formatter):
# return super().format(record)
+class StreamCaptureHandler(logging.Handler):
+ """
+ A custom logging handler that captures log messages in a list.
+
+ This handler stores log messages in memory so they can be retrieved later,
+ which is useful for sending log messages to a frontend.
+ """
+
+ def __init__(self):
+ super().__init__()
+ self.messages: List[str] = []
+
+ def emit(self, record):
+ """
+ Emit a log record by storing it in the messages list.
+
+ Args:
+ record: The log record to emit.
+ """
+ log_entry = self.format(record)
+ self.messages.append(log_entry)
+
+ def get_messages(self) -> List[str]:
+ """
+ Get all captured log messages.
+
+ Returns:
+ A list of captured log messages.
+ """
+ return self.messages.copy()
+
+ def clear_messages(self):
+ """
+ Clear all captured log messages.
+ """
+ self.messages.clear()
+
+
# config log
dev_logger = logging.getLogger("dev")
dev_formatter = ColoredFormatter("%(asctime)s - %(levelname)s - %(message)s")
@@ -60,8 +99,11 @@ dev_logger.setLevel(logging.INFO)
progress_logger = logging.getLogger("progress")
progress_handler = logging.StreamHandler()
+progress_capture_handler = StreamCaptureHandler()
progress_handler.setFormatter(ColoredFormatter("%(message)s"))
+progress_capture_handler.setFormatter(logging.Formatter("%(message)s"))
progress_logger.addHandler(progress_handler)
+progress_logger.addHandler(progress_capture_handler)
progress_logger.setLevel(logging.INFO)
dev_mode = False
@@ -158,3 +200,21 @@ def color_print(message, **kwargs):
**kwargs: Additional keyword arguments to pass to the logger.
"""
progress_logger.info(message)
+ progress_handler.flush()
+
+
+def get_progress_messages() -> List[str]:
+ """
+ Get all captured progress messages.
+
+ Returns:
+ A list of captured progress messages.
+ """
+ return progress_capture_handler.get_messages()
+
+
+def clear_progress_messages():
+ """
+ Clear all captured progress messages.
+ """
+ progress_capture_handler.clear_messages()
\ No newline at end of file
diff --git a/main.py b/main.py
index 9a29d40..78916c4 100644
--- a/main.py
+++ b/main.py
@@ -155,11 +155,12 @@ def load_files(
HTTPException: If loading files fails.
"""
try:
+ # 修复batch_size为None时的问题
load_from_local_files(
paths_or_directory=paths,
collection_name=collection_name,
collection_description=collection_description,
- batch_size=batch_size,
+ batch_size=batch_size if batch_size is not None else 256, # 提供默认值
)
return {"message": "Files loaded successfully."}
except Exception as e:
@@ -205,11 +206,12 @@ def load_website(
HTTPException: If loading website content fails.
"""
try:
+ # 修复batch_size为None时的问题
load_from_website(
urls=urls,
collection_name=collection_name,
collection_description=collection_description,
- batch_size=batch_size,
+ batch_size=batch_size if batch_size is not None else 256, # 提供默认值
)
return {"message": "Website loaded successfully."}
except Exception as e:
@@ -244,8 +246,21 @@ def perform_query(
HTTPException: If the query fails.
"""
try:
+ # 清除之前的进度消息
+ from deepsearcher.utils.log import clear_progress_messages
+ clear_progress_messages()
+
result_text, _, consume_token = query(original_query, max_iter)
- return {"result": result_text, "consume_token": consume_token}
+
+ # 获取进度消息
+ from deepsearcher.utils.log import get_progress_messages
+ progress_messages = get_progress_messages()
+
+ return {
+ "result": result_text,
+ "consume_token": consume_token,
+ "progress_messages": progress_messages
+ }
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))