增加显示详细日志开关

This commit is contained in:
glide-the 2023-09-08 20:48:31 +08:00
parent 228fc5bd93
commit 5550e3c1a9
12 changed files with 97 additions and 49 deletions

View File

@ -5,6 +5,8 @@ LOG_FORMAT = "%(asctime)s - %(filename)s[line:%(lineno)d] - %(levelname)s: %(mes
logger = logging.getLogger()
logger.setLevel(logging.INFO)
logging.basicConfig(format=LOG_FORMAT)
# 是否显示详细日志
log_verbose = False
# 在以下字典中修改属性值以指定本地embedding模型存储位置

View File

@ -6,7 +6,7 @@ sys.path.append(os.path.dirname(os.path.dirname(__file__)))
from configs.model_config import LLM_MODEL, NLTK_DATA_PATH
from configs.server_config import OPEN_CROSS_DOMAIN, HTTPX_DEFAULT_TIMEOUT
from configs import VERSION
from configs import VERSION, logger, log_verbose
import argparse
import uvicorn
from fastapi import Body
@ -140,6 +140,8 @@ def create_app():
r = httpx.post(controller_address + "/list_models")
return BaseResponse(data=r.json()["models"])
except Exception as e:
logger.error(f'{e.__class__.__name__}: {e}',
exc_info=e if log_verbose else None)
return BaseResponse(
code=500,
data=[],
@ -165,6 +167,8 @@ def create_app():
)
return r.json()
except Exception as e:
logger.error(f'{e.__class__.__name__}: {e}',
exc_info=e if log_verbose else None)
return BaseResponse(
code=500,
msg=f"failed to stop LLM model {model_name} from controller: {controller_address}。错误信息是: {e}")
@ -190,6 +194,8 @@ def create_app():
)
return r.json()
except Exception as e:
logger.error(f'{e.__class__.__name__}: {e}',
exc_info=e if log_verbose else None)
return BaseResponse(
code=500,
msg=f"failed to switch LLM model from controller: {controller_address}。错误信息是: {e}")

View File

@ -1,7 +1,7 @@
from fastapi.responses import StreamingResponse
from typing import List
import openai
from configs.model_config import llm_model_dict, LLM_MODEL, logger
from configs.model_config import llm_model_dict, LLM_MODEL, logger, log_verbose
from pydantic import BaseModel
@ -46,7 +46,9 @@ async def openai_chat(msg: OpenAiChatMsgIn):
print(answer)
yield(answer)
except Exception as e:
logger.error(f"获取ChatCompletion时出错{e}")
msg = f"获取ChatCompletion时出错{e}"
logger.error(f'{e.__class__.__name__}: {msg}',
exc_info=e if log_verbose else None)
return StreamingResponse(
get_response(msg),

View File

@ -2,6 +2,7 @@ import asyncio
from typing import Awaitable, List, Tuple, Dict, Union
from pydantic import BaseModel, Field
from langchain.prompts.chat import ChatMessagePromptTemplate
from configs import logger, log_verbose
async def wrap_done(fn: Awaitable, event: asyncio.Event):
@ -10,7 +11,9 @@ async def wrap_done(fn: Awaitable, event: asyncio.Event):
await fn
except Exception as e:
# TODO: handle exception
print(f"Caught exception: {e}")
msg = f"Caught exception: {e}"
logger.error(f'{e.__class__.__name__}: {msg}',
exc_info=e if log_verbose else None)
finally:
# Signal the aiter to stop.
event.set()

View File

@ -3,7 +3,7 @@ from server.utils import BaseResponse, ListResponse
from server.knowledge_base.utils import validate_kb_name
from server.knowledge_base.kb_service.base import KBServiceFactory
from server.db.repository.knowledge_base_repository import list_kbs_from_db
from configs.model_config import EMBEDDING_MODEL, logger
from configs.model_config import EMBEDDING_MODEL, logger, log_verbose
from fastapi import Body
@ -31,7 +31,8 @@ async def create_kb(knowledge_base_name: str = Body(..., examples=["samples"]),
kb.create_kb()
except Exception as e:
msg = f"创建知识库出错: {e}"
logger.error(msg)
logger.error(f'{e.__class__.__name__}: {msg}',
exc_info=e if log_verbose else None)
return BaseResponse(code=500, msg=msg)
return BaseResponse(code=200, msg=f"已新增知识库 {knowledge_base_name}")
@ -57,7 +58,8 @@ async def delete_kb(
return BaseResponse(code=200, msg=f"成功删除知识库 {knowledge_base_name}")
except Exception as e:
msg = f"删除知识库时出现意外: {e}"
logger.error(msg)
logger.error(f'{e.__class__.__name__}: {msg}',
exc_info=e if log_verbose else None)
return BaseResponse(code=500, msg=msg)
return BaseResponse(code=500, msg=f"删除知识库失败 {knowledge_base_name}")

View File

@ -3,7 +3,7 @@ import urllib
from fastapi import File, Form, Body, Query, UploadFile
from configs.model_config import (DEFAULT_VS_TYPE, EMBEDDING_MODEL,
VECTOR_SEARCH_TOP_K, SCORE_THRESHOLD,
logger,)
logger, log_verbose,)
from server.utils import BaseResponse, ListResponse, run_in_thread_pool
from server.knowledge_base.utils import (validate_kb_name, list_files_from_folder,get_file_path,
files2docs_in_thread, KnowledgeFile)
@ -80,7 +80,8 @@ def _save_files_in_thread(files: List[UploadFile],
return dict(code=200, msg=f"成功上传文件 {filename}", data=data)
except Exception as e:
msg = f"{filename} 文件上传失败,报错信息为: {e}"
logger.error(msg)
logger.error(f'{e.__class__.__name__}: {msg}',
exc_info=e if log_verbose else None)
return dict(code=500, msg=msg, data=data)
params = [{"file": file, "knowledge_base_name": knowledge_base_name, "override": override} for file in files]
@ -100,7 +101,7 @@ def _save_files_in_thread(files: List[UploadFile],
# yield json.dumps(result, ensure_ascii=False)
# return StreamingResponse(generate(files, knowledge_base_name=knowledge_base_name, override=override), media_type="text/event-stream")
# TODO: 等langchain.document_loaders支持内存文件的时候再开通
# def files2docs(files: List[UploadFile] = File(..., description="上传文件,支持多文件"),
@ -141,7 +142,7 @@ async def upload_docs(files: List[UploadFile] = File(..., description="上传文
filename = result["data"]["file_name"]
if result["code"] != 200:
failed_files[filename] = result["msg"]
if filename not in file_names:
file_names.append(filename)
@ -185,9 +186,10 @@ async def delete_docs(knowledge_base_name: str = Body(..., examples=["samples"])
kb.delete_doc(kb_file, delete_content, not_refresh_vs_cache=True)
except Exception as e:
msg = f"{file_name} 文件删除失败,错误信息:{e}"
logger.error(msg)
logger.error(f'{e.__class__.__name__}: {msg}',
exc_info=e if log_verbose else None)
failed_files[file_name] = msg
if not not_refresh_vs_cache:
kb.save_vector_store()
@ -225,7 +227,8 @@ async def update_docs(
kb_files.append(KnowledgeFile(filename=file_name, knowledge_base_name=knowledge_base_name))
except Exception as e:
msg = f"加载文档 {file_name} 时出错:{e}"
logger.error(msg)
logger.error(f'{e.__class__.__name__}: {msg}',
exc_info=e if log_verbose else None)
failed_files[file_name] = msg
# 从文件生成docs并进行向量化。
@ -249,7 +252,8 @@ async def update_docs(
kb.update_doc(kb_file, docs=v, not_refresh_vs_cache=True)
except Exception as e:
msg = f"{file_name} 添加自定义docs时出错{e}"
logger.error(msg)
logger.error(f'{e.__class__.__name__}: {msg}',
exc_info=e if log_verbose else None)
failed_files[file_name] = msg
if not not_refresh_vs_cache:
@ -291,7 +295,8 @@ def download_doc(
)
except Exception as e:
msg = f"{kb_file.filename} 读取文件失败,错误信息是:{e}"
logger.error(msg)
logger.error(f'{e.__class__.__name__}: {msg}',
exc_info=e if log_verbose else None)
return BaseResponse(code=500, msg=msg)
return BaseResponse(code=500, msg=f"{kb_file.filename} 读取文件失败")

View File

@ -6,7 +6,7 @@ from configs.model_config import (
CACHED_VS_NUM,
EMBEDDING_MODEL,
SCORE_THRESHOLD,
logger,
logger, log_verbose,
)
from server.knowledge_base.kb_service.base import KBService, SupportedVSType
from functools import lru_cache
@ -46,7 +46,7 @@ def load_faiss_vector_store(
ids = [k for k, v in search_index.docstore._dict.items()]
search_index.delete(ids)
search_index.save_local(vs_path)
if tick == 0: # vector store is loaded first time
_VECTOR_STORE_TICKS[knowledge_base_name] = 0
@ -166,4 +166,4 @@ if __name__ == '__main__':
faissService.add_doc(KnowledgeFile("README.md", "test"))
faissService.delete_doc(KnowledgeFile("README.md", "test"))
faissService.do_drop_kb()
print(faissService.search_docs("如何启动api服务"))
print(faissService.search_docs("如何启动api服务"))

View File

@ -1,4 +1,4 @@
from configs.model_config import EMBEDDING_MODEL, DEFAULT_VS_TYPE
from configs.model_config import EMBEDDING_MODEL, DEFAULT_VS_TYPE, logger, log_verbose
from server.knowledge_base.utils import (get_file_path, list_kbs_from_folder,
list_files_from_folder, run_in_thread_pool,
files2docs_in_thread,
@ -30,7 +30,9 @@ def file_to_kbfile(kb_name: str, files: List[str]) -> List[KnowledgeFile]:
kb_file = KnowledgeFile(filename=file, knowledge_base_name=kb_name)
kb_files.append(kb_file)
except Exception as e:
print(f"{e},已跳过")
msg = f"{e},已跳过"
logger.error(f'{e.__class__.__name__}: {msg}',
exc_info=e if log_verbose else None)
return kb_files

View File

@ -8,7 +8,7 @@ from configs.model_config import (
CHUNK_SIZE,
OVERLAP_SIZE,
ZH_TITLE_ENHANCE,
logger,
logger, log_verbose,
)
from functools import lru_cache
import importlib
@ -189,7 +189,9 @@ def get_loader(loader_name: str, file_path_or_content: Union[str, bytes, io.Stri
document_loaders_module = importlib.import_module('langchain.document_loaders')
DocumentLoader = getattr(document_loaders_module, loader_name)
except Exception as e:
logger.error(f"为文件{file_path_or_content}查找加载器{loader_name}时出错:{e}")
msg = f"为文件{file_path_or_content}查找加载器{loader_name}时出错:{e}"
logger.error(f'{e.__class__.__name__}: {msg}',
exc_info=e if log_verbose else None)
document_loaders_module = importlib.import_module('langchain.document_loaders')
DocumentLoader = getattr(document_loaders_module, "UnstructuredFileLoader")
@ -228,7 +230,9 @@ def make_text_splitter(
chunk_overlap=chunk_overlap,
)
except Exception as e:
logger.error(f"查找分词器 {splitter_name} 时出错:{e}")
msg = f"查找分词器 {splitter_name} 时出错:{e}"
logger.error(f'{e.__class__.__name__}: {msg}',
exc_info=e if log_verbose else None)
TextSplitter = getattr(text_splitter_module, "RecursiveCharacterTextSplitter")
text_splitter = TextSplitter(
chunk_size=chunk_size,
@ -330,7 +334,8 @@ def files2docs_in_thread(
return True, (file.kb_name, file.filename, file.file2text(**kwargs))
except Exception as e:
msg = f"从文件 {file.kb_name}/{file.filename} 加载文档时出错:{e}"
logger.error(msg)
logger.error(f'{e.__class__.__name__}: {msg}',
exc_info=e if log_verbose else None)
return False, (file.kb_name, file.filename, msg)
kwargs_list = []
@ -345,7 +350,7 @@ def files2docs_in_thread(
file = KnowledgeFile(filename=filename, knowledge_base_name=kb_name)
kwargs["file"] = file
kwargs_list.append(kwargs)
for result in run_in_thread_pool(func=file2docs, params=kwargs_list, pool=pool):
yield result

View File

@ -4,7 +4,7 @@ import sys
import os
sys.path.append(os.path.dirname(os.path.dirname(__file__)))
from configs.model_config import llm_model_dict, LLM_MODEL, LOG_PATH, logger
from configs.model_config import llm_model_dict, LLM_MODEL, LOG_PATH, logger, log_verbose
from server.utils import MakeFastAPIOffline, set_httpx_timeout, llm_device
@ -140,7 +140,7 @@ def create_model_worker_app(
sys.modules["fastchat.serve.model_worker"].worker = worker
sys.modules["fastchat.serve.model_worker"].args = args
sys.modules["fastchat.serve.model_worker"].gptq_config = gptq_config
MakeFastAPIOffline(app)
app.title = f"FastChat LLM Server ({LLM_MODEL})"
return app

View File

@ -4,7 +4,7 @@ from typing import List
from fastapi import FastAPI
from pathlib import Path
import asyncio
from configs.model_config import LLM_MODEL, llm_model_dict, LLM_DEVICE, EMBEDDING_DEVICE
from configs.model_config import LLM_MODEL, llm_model_dict, LLM_DEVICE, EMBEDDING_DEVICE, logger, log_verbose
from configs.server_config import FSCHAT_MODEL_WORKERS
import os
from server import model_workers
@ -86,9 +86,10 @@ def torch_gc():
from torch.mps import empty_cache
empty_cache()
except Exception as e:
print(e)
print("如果您使用的是 macOS 建议将 pytorch 版本升级至 2.0.0 或更高版本,以支持及时清理 torch 产生的内存占用。")
msg=("如果您使用的是 macOS 建议将 pytorch 版本升级至 2.0.0 或更高版本,"
"以支持及时清理 torch 产生的内存占用。")
logger.error(f'{e.__class__.__name__}: {msg}',
exc_info=e if log_verbose else None)
def run_async(cor):
'''
@ -217,7 +218,9 @@ def get_model_worker_config(model_name: str = LLM_MODEL) -> dict:
try:
config["worker_class"] = getattr(model_workers, provider)
except Exception as e:
print(f"在线模型 {model_name} 的provider没有正确配置")
msg = f"在线模型 {model_name} 的provider没有正确配置"
logger.error(f'{e.__class__.__name__}: {msg}',
exc_info=e if log_verbose else None)
config["device"] = llm_device(config.get("device") or LLM_DEVICE)
return config
@ -322,11 +325,11 @@ def run_in_thread_pool(
'''
tasks = []
pool = pool or thread_pool
for kwargs in params:
thread = pool.submit(func, **kwargs)
tasks.append(thread)
for obj in as_completed(tasks):
yield obj.result()

View File

@ -11,7 +11,7 @@ from configs.model_config import (
SCORE_THRESHOLD,
VECTOR_SEARCH_TOP_K,
SEARCH_ENGINE_TOP_K,
logger,
logger, log_verbose,
)
from configs.server_config import HTTPX_DEFAULT_TIMEOUT
import httpx
@ -78,7 +78,9 @@ class ApiRequest:
else:
return httpx.get(url, params=params, **kwargs)
except Exception as e:
logger.error(f"error when get {url}: {e}")
msg = f"error when get {url}: {e}"
logger.error(f'{e.__class__.__name__}: {msg}',
exc_info=e if log_verbose else None)
retry -= 1
async def aget(
@ -99,7 +101,9 @@ class ApiRequest:
else:
return await client.get(url, params=params, **kwargs)
except Exception as e:
logger.error(f"error when aget {url}: {e}")
msg = f"error when aget {url}: {e}"
logger.error(f'{e.__class__.__name__}: {msg}',
exc_info=e if log_verbose else None)
retry -= 1
def post(
@ -121,7 +125,9 @@ class ApiRequest:
else:
return httpx.post(url, data=data, json=json, **kwargs)
except Exception as e:
logger.error(f"error when post {url}: {e}")
msg = f"error when post {url}: {e}"
logger.error(f'{e.__class__.__name__}: {msg}',
exc_info=e if log_verbose else None)
retry -= 1
async def apost(
@ -143,7 +149,9 @@ class ApiRequest:
else:
return await client.post(url, data=data, json=json, **kwargs)
except Exception as e:
logger.error(f"error when apost {url}: {e}")
msg = f"error when apost {url}: {e}"
logger.error(f'{e.__class__.__name__}: {msg}',
exc_info=e if log_verbose else None)
retry -= 1
def delete(
@ -164,7 +172,9 @@ class ApiRequest:
else:
return httpx.delete(url, data=data, json=json, **kwargs)
except Exception as e:
logger.error(f"error when delete {url}: {e}")
msg = f"error when delete {url}: {e}"
logger.error(f'{e.__class__.__name__}: {msg}',
exc_info=e if log_verbose else None)
retry -= 1
async def adelete(
@ -186,7 +196,9 @@ class ApiRequest:
else:
return await client.delete(url, data=data, json=json, **kwargs)
except Exception as e:
logger.error(f"error when adelete {url}: {e}")
msg = f"error when adelete {url}: {e}"
logger.error(f'{e.__class__.__name__}: {msg}',
exc_info=e if log_verbose else None)
retry -= 1
def _fastapi_stream2generator(self, response: StreamingResponse, as_json: bool =False):
@ -197,7 +209,7 @@ class ApiRequest:
loop = asyncio.get_event_loop()
except:
loop = asyncio.new_event_loop()
try:
for chunk in iter_over_async(response.body_iterator, loop):
if as_json and chunk:
@ -205,7 +217,9 @@ class ApiRequest:
elif chunk.strip():
yield chunk
except Exception as e:
logger.error(f"error when run fastapi router: {e}")
msg = f"error when run fastapi router: {e}"
logger.error(f'{e.__class__.__name__}: {msg}',
exc_info=e if log_verbose else None)
def _httpx_stream2generator(
self,
@ -226,7 +240,9 @@ class ApiRequest:
pprint(data, depth=1)
yield data
except Exception as e:
logger.error(f"接口返回json错误 {chunk}’。错误信息是:{e}")
msg = f"接口返回json错误 {chunk}’。错误信息是:{e}"
logger.error(f'{e.__class__.__name__}: {msg}',
exc_info=e if log_verbose else None)
else:
print(chunk, end="", flush=True)
yield chunk
@ -241,7 +257,8 @@ class ApiRequest:
yield {"code": 500, "msg": msg}
except Exception as e:
msg = f"API通信遇到错误{e}"
logger.error(msg)
logger.error(f'{e.__class__.__name__}: {msg}',
exc_info=e if log_verbose else None)
yield {"code": 500, "msg": msg}
# 对话相关操作
@ -414,7 +431,8 @@ class ApiRequest:
return response.json()
except Exception as e:
msg = "API未能返回正确的JSON。" + (errorMsg or str(e))
logger.error(msg)
logger.error(f'{e.__class__.__name__}: {msg}',
exc_info=e if log_verbose else None)
return {"code": 500, "msg": msg}
def list_knowledge_bases(
@ -531,7 +549,7 @@ class ApiRequest:
"top_k": top_k,
"score_threshold": score_threshold,
}
if no_remote_api:
from server.knowledge_base.kb_doc_api import search_docs
return search_docs(**data)
@ -736,7 +754,7 @@ class ApiRequest:
json=data,
)
return r.json()
def change_llm_model(
self,
model_name: str,