Skip to content

Commit 600caa7

Browse files
loki log
1 parent 4302902 commit 600caa7

File tree

15 files changed

+192
-33
lines changed

15 files changed

+192
-33
lines changed

LICENSE

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
MIT License
22

3-
Copyright (c) 2024 TheLab
3+
Copyright (c) 2025 TheLab
44

55
Permission is hereby granted, free of charge, to any person obtaining a copy
66
of this software and associated documentation files (the "Software"), to deal

config.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,10 @@ class Settings(BaseSettings):
8383
GLOBAL_MODE: Literal["public", "private"] = "public"
8484
GLOBAL_LLM: Literal["public", "private"] = "public"
8585

86+
# Loki设置
87+
LOKI_URL: Optional[str] = None
88+
LOKI_TAG: Optional[str] = None
89+
8690
@property
8791
def DATABASE_URL(self) -> str:
8892
"""获取数据库连接URL.

database.py

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
"""
55

66
import enum
7+
import logging
78
from datetime import datetime
89

910
from alembic.migration import MigrationContext
@@ -29,6 +30,8 @@
2930

3031
from config import get_settings
3132

33+
logger = logging.getLogger(__name__)
34+
3235
settings = get_settings()
3336

3437
# 创建数据库引擎
@@ -381,7 +384,7 @@ def create_tables():
381384
for table in Base.metadata.sorted_tables:
382385
if table.name not in existing_tables:
383386
# 如果表不存在,创建新表
384-
print(f"创建表 {table.name}")
387+
logger.info(f"创建表 {table.name}")
385388
table.create(engine)
386389
else:
387390
# 如果表存在,更新表结构
@@ -393,12 +396,12 @@ def create_tables():
393396
col,
394397
) in metadata_columns.items():
395398
if col_name not in existing_columns:
396-
print(f"添加列 {col_name}")
399+
logger.info(f"添加列 {col_name}")
397400
try:
398401
op.add_column(table.name, col)
399402
except Exception as e:
400-
print(f"添加列 {col_name} 时出错: {str(e)}")
401-
print("表结构更新完成")
403+
logger.error(f"添加列 {col_name} 时出错: {str(e)}")
404+
logger.info("表结构更新完成")
402405
else:
403406
# SQLite 数据库,由于 SQLite 限制,使用临时表进行迁移
404407
Base.metadata.create_all(bind=engine)
@@ -408,7 +411,7 @@ def create_tables():
408411
except Exception as e:
409412
# 回滚事务
410413
trans.rollback()
411-
print(f"更新表结构时出错: {str(e)}")
414+
logger.error(f"更新表结构时出错: {str(e)}")
412415
raise
413416

414417
# 初始化数据库数据

frontend/src/api/files.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,15 @@ export const fileApi = {
154154
});
155155
},
156156

157+
// 重命名文件或文件夹
158+
renameFolder: async (folderId: string, request: RenameFileRequest) => {
159+
return handleRequest(`${BASE_URL}/folders/${folderId}/rename`, {
160+
method: 'PUT',
161+
headers: getAuthHeaders(),
162+
body: JSON.stringify(request),
163+
});
164+
},
165+
157166
// 移动文件或文件夹
158167
moveFile: async (fileId: string, request: MoveFileRequest) => {
159168
return handleRequest(`${BASE_URL}/documents/${fileId}/move`, {

frontend/src/components/FileList/index.tsx

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -285,7 +285,8 @@ const FileList: React.FC<FileListProps> = ({
285285
}
286286
};
287287

288-
const handleRename = async (fileId: string, newName: string) => {
288+
const handleRenameDocument = async (fileId: string, newName: string) => {
289+
if (!fileId || !newName) return;
289290
try {
290291
setLoading(true);
291292
await fileApi.renameFile(fileId, { newName });
@@ -300,6 +301,22 @@ const FileList: React.FC<FileListProps> = ({
300301
}
301302
};
302303

304+
const handleRenameFolder = async (folderId: string, newName: string) => {
305+
if (!folderId || !newName) return;
306+
try {
307+
setLoading(true);
308+
await fileApi.renameFolder(folderId, { newName });
309+
setOperation(null);
310+
fetchFiles(getCurrentFolderId());
311+
(window as any).toast.success('重命名成功');
312+
} catch (error) {
313+
console.error('Error renaming folder:', error);
314+
(window as any).toast.error('重命名失败');
315+
} finally {
316+
setLoading(false);
317+
}
318+
};
319+
303320
const handleDownload = async (fileId: string, isFolder: boolean) => {
304321
(window as any).toast.info("文件正在下载中...");
305322
try {
@@ -714,7 +731,13 @@ const FileList: React.FC<FileListProps> = ({
714731
/>
715732
<div className={styles.dialogActions}>
716733
<button onClick={() => setOperation(null)}>取消</button>
717-
<button onClick={() => handleRename(operation.fileId || '', operation.data?.newName || '')}>
734+
<button onClick={() => {
735+
if (files.find(f => f.id === operation.fileId)?.isFolder) {
736+
handleRenameFolder(operation.fileId || '', operation.data?.newName || '');
737+
} else {
738+
handleRenameDocument(operation.fileId || '', operation.data?.newName || '');
739+
}
740+
}}>
718741
确定
719742
</button>
720743
</div>

main.py

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
import logging
77
import os
8+
import sys
89
from contextlib import asynccontextmanager
910

1011
import uvicorn
@@ -15,7 +16,39 @@
1516

1617
from routers import auth, conversations, documents, folders, forum, search, settings
1718

18-
logging.basicConfig(level=logging.DEBUG)
19+
# 配置根日志记录器
20+
root_logger = logging.getLogger()
21+
root_logger.setLevel(logging.DEBUG)
22+
23+
# 配置控制台处理器
24+
console_handler = logging.StreamHandler(sys.stdout)
25+
console_handler.setLevel(logging.DEBUG)
26+
console_formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
27+
console_handler.setFormatter(console_formatter)
28+
29+
# 移除所有现有的处理器
30+
for handler in root_logger.handlers[:]:
31+
root_logger.removeHandler(handler)
32+
33+
# 添加新的处理器
34+
root_logger.addHandler(console_handler)
35+
36+
if os.getenv("LOKI_URL", None):
37+
import logging_loki
38+
39+
# 配置Loki处理器
40+
loki_handler = logging_loki.LokiHandler(
41+
url=os.getenv("LOKI_URL"),
42+
tags={"application": os.getenv("LOKI_TAG", "ai_doc_system")},
43+
version="1",
44+
auth=None,
45+
)
46+
loki_handler.setLevel(logging.DEBUG)
47+
root_logger.addHandler(loki_handler)
48+
49+
50+
logging.getLogger("urllib3").setLevel(logging.WARNING)
51+
1952
logger = logging.getLogger(__name__)
2053

2154

manage.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ def migrate_legacy_db():
116116
cursor.execute("SELECT id, title, linked_file_path, linked_task_id, created_at, updated_at FROM api_document")
117117
documents = cursor.fetchall()
118118

119-
print(documents[:10])
119+
logger.info(documents[:10])
120120

121121
# 创建项目
122122
project_id_to_folder_id = {}
@@ -126,7 +126,7 @@ def migrate_legacy_db():
126126
project_name = project[1]
127127
project_created_at = project[2]
128128
project_updated_at = project[3]
129-
print(
129+
logger.info(
130130
project_id,
131131
project_name,
132132
project_created_at,
@@ -146,7 +146,7 @@ def migrate_legacy_db():
146146
db.refresh(folder)
147147
project_id_to_folder_id[project_id] = folder.id
148148
project_id_to_project_name[project_id] = project_name
149-
print(folder.id)
149+
logger.info(folder.id)
150150

151151
# 集合对应项目的映射
152152
collection_id_to_project_id = {}
@@ -170,7 +170,7 @@ def migrate_legacy_db():
170170
# 所属的项目
171171
project_id = collection_id_to_project_id[collection_id]
172172
project_name = project_id_to_project_name[project_id]
173-
print(
173+
logger.info(
174174
collection_id,
175175
collection_name,
176176
collection_created_at,
@@ -212,7 +212,7 @@ def migrate_legacy_db():
212212
doc_persist_path = os.path.join(os.path.dirname(__file__), "./tmp/persist", doc_uuid)
213213
doc_abs_path = os.path.join(doc_persist_path, doc_title)
214214
doc_thumbnail_path = os.path.join(doc_persist_path, "thumbnail.png")
215-
print(
215+
logger.info(
216216
doc_title,
217217
doc_uuid,
218218
doc_file_path,

prepdocs/parse_page.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ def _process_batch_pages(
9898

9999
async def _process_pdf(self, file_path: Path) -> list[str]:
100100
"""异步处理 PDF 文件,返回图片路径列表."""
101-
print("PDF processing start")
101+
logger.info("PDF processing start")
102102

103103
# 打开PDF文件
104104
pdf = pdfium.PdfDocument(file_path)
@@ -166,7 +166,7 @@ async def _process_pdf(self, file_path: Path) -> list[str]:
166166
# 确保页面顺序正确
167167
image_paths = [path for path in temp_paths if path is not None]
168168

169-
print("PDF processing end")
169+
logger.info("PDF processing end")
170170
return image_paths
171171

172172
async def process_document_async(self, file_path: str, title: str) -> Section:

rag/knowledgebase.py

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
import asyncio
77
import hashlib
8+
import logging
89
import os
910
import traceback
1011
from concurrent.futures.thread import ThreadPoolExecutor
@@ -28,6 +29,8 @@
2829

2930
from database import Document as DBDocument
3031

32+
logger = logging.getLogger(__name__)
33+
3134
# DEBUG日志
3235

3336
# logging.basicConfig(stream=sys.stdout, level=logging.DEBUG)
@@ -133,7 +136,7 @@ def __init__(
133136
# 用于存储用户的查询和模型的回答,以支持上下文增强生成(RAG)。
134137
# 格式通常为[(用户查询, 模型回答), ...],在后续查询中,历史上下文将拼接到用户的新查询中。
135138
self.history = []
136-
print("RAG 初始化完成")
139+
logger.info("RAG 初始化完成")
137140

138141
# async:这是一个异步函数,允许通过await 调用异步操作,提高性能(特别是涉及I/O操作时,如数据库或网络访问)
139142
# text: str:用户提供的文本内容,通常为需要存储和处理的文档。
@@ -190,10 +193,10 @@ async def upload_files(self, file_paths: list[str]):
190193
"""
191194
docs = []
192195
for file_path in file_paths[:50]:
193-
print(f"Ingesting file: {file_path}")
196+
logger.info(f"Ingesting file: {file_path}")
194197
with open(file_path, "r", encoding="utf-8") as f:
195198
text = f.read()
196-
print(f"Text length: {len(text)}")
199+
logger.info(f"Text length: {len(text)}")
197200
doc_id = f"web_{os.path.basename(file_path)}_{hashlib.md5(text.encode()).hexdigest()}"
198201
docs.append(
199202
Document(
@@ -255,7 +258,7 @@ async def remove_all_documents(self, num_workers: int = 5):
255258
else:
256259
tasks = [self.remove_document_by_id(doc_id) for doc_id in all_docs.keys()]
257260
await asyncio.gather(*tasks)
258-
print("All documents removed")
261+
logger.info("All documents removed")
259262

260263
async def retrieve(
261264
self,
@@ -418,6 +421,7 @@ async def query_documents(rag, request: QueryRequest):
418421
return QueryResponse(response=result["response"], sources=result["sources"])
419422
except Exception as e:
420423
traceback.print_exc()
424+
logger.error(f"查询文档时发生错误: {str(e)} {traceback.format_exc()}")
421425
raise e
422426

423427

@@ -429,6 +433,7 @@ async def upload_text_to_rag(rag, text: str):
429433
return {"message": "文本上传成功", "doc_id": doc_id}
430434
except Exception as e:
431435
traceback.print_exc()
436+
logger.error(f"上传纯文本时发生错误: {str(e)} {traceback.format_exc()}")
432437
raise e
433438

434439

requirements.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@ pydantic[email]==2.8.0
3333
pypdfium2==4.30.1
3434
python-dotenv==1.0.1
3535
python-jose[cryptography]==3.4.0
36+
37+
# 日志
38+
python-logging-loki==0.3.1
3639
python-multipart==0.0.19
3740
redis==5.0.1
3841
sqlalchemy==2.0.23

0 commit comments

Comments
 (0)