目 录前 言第一步加logging第二步加异常处理第三步做配置管理前 言今天主要任务是给咱们的系统增加一些日志、异常处理并且加配置管理这样咱们系统在出错时可以不再看traceback而是能看清楚哪一步挂了。此外咱们前面的代码API KEY、路径和模型名字是写死在代码中的今天咱们将添加配置管理让他们从代码中解耦。第一步加logging首先创建一个设置日志的函数logger_config.pyimportloggingdefsetup_logger():logging.basicConfig(levellogging.INFO,format%(asctime)s | %(levelname)s | %(name)s | %(message)s)returnlogging.getLogger(rag_agent)然后在app.py、agent.py、rag_system.py里都引入fromlogger_configimportsetup_logger loggersetup_logger()关于日志这里需要补充一些相关知识1、关于日志设置的字段%(xxx)s是占位符其中%(asctime)s日志记录的时间戳如 2024-01-15 10:30:45,123%(levelname)s日志级别INFO、WARNING、ERROR、DEBUG等%(name)s日志记录器的名称通常是模块名或自定义名称%(message)s实际的日志消息内容2、levellogging.INFO语句设置日志等级为信息级这个级别以下的信息会被忽略关于日志级别CRITICAL (50) ← 最严重最少输出↓ERROR (40)↓WARNING (30)↓INFO (20)↓DEBUG (10) ← 最不严重最多输出第二步加异常处理前面的代码默认我们的每一步都成功但是在做工程项目的时候我们最好假设每一步都“可能失败”所以我们需要对各种操作加上异常处理app.py中的/ask我们需要加上异常处理fromfastapiimportHTTPExceptionapp.post(/ask)defask_question(req:QueryRequest):try:answerrun_agent(req.question,TOOLS,rag)return{question:req.question,answer:answer}exceptExceptionase:logger.exception(Error occurred in /ask)raiseHTTPException(status_code500,detailstr(e))前面我们定义的get_embedding函数可能因为网络不稳导致embedding失败我们同样可以加上异常处理importtimeimportnumpyasnpdefget_embedding(text,max_retries3):forattemptinrange(max_retries):try:responseclient2.embeddings.create(modeltext-embedding-3-small,inputtext)returnnp.array(response.data[0].embedding,dtypefloat32)exceptExceptionase:logger.warning(fEmbedding failed, retry{attempt1}/{max_retries}:{e})time.sleep(2)logger.error(Embedding failed after all retries)raiseRuntimeError(Embedding generation failed)choose_tool中模型有时可能不按要求返回JSON所以这里也要加保护defchoose_tool(query,tools):tool_desc\n.join([f{t[name]}:{t[description]}fortintools])promptf You are an AI agent. Available tools:{tool_desc}User question:{query}Return JSON: {{tool: ..., input: ...}} try:responseclient.chat.completions.create(modelCHAT_MODEL,messages[{role:user,content:prompt}])contentresponse.choices[0].message.contentreturnjson.loads(content)except:logger.warning(fTool decision parse failed:{content})return{tool:llm,input:query}第三步做配置管理这里容易踩坑所以要特别说一下为什么要做配置管理咱们再代码中写死API KEY、BASE URL、DATA路径以及模型名字刚开始代码肯定能跑但是有可能在日后出现问题因为系统有可能会遇到换模型、换平台、上传服务器部署以及上Django这种情况如果遇到代码量又比较大那么就得一个个改很麻烦所以咱们做一个配置管理以后想要换的话只需要修改配置文件就可以了。咱们前面在根目录创建过一个.env文件那个时候咱们在里面放了两个API KEY这回咱们将内容丰富一下写成下面的样子DEEPSEEK_API_KEY你的deepseek_key DEEPSEEK_BASE_URLhttps://api.deepseek.com EMBEDDING_API_KEY你的embedding_key EMBEDDING_BASE_URLhttps://api.shubiaobiao.com/v1 CHAT_MODELdeepseek-chat EMBEDDING_MODELtext-embedding-3-small DATA_DIRdata随后创建一个config.py文件在里面引入咱们所有的配置信息fromdotenvimportload_dotenvimportos load_dotenv()DEEPSEEK_API_KEYos.getenv(DEEPSEEK_API_KEY)DEEPSEEK_BASE_URLos.getenv(DEEPSEEK_BASE_URL,https://api.deepseek.com)EMBEDDING_API_KEYos.getenv(EMBEDDING_API_KEY)EMBEDDING_BASE_URLos.getenv(EMBEDDING_BASE_URL)CHAT_MODELos.getenv(CHAT_MODEL,deepseek-chat)EMBEDDING_MODELos.getenv(EMBEDDING_MODEL,text-embedding-3-small)DATA_DIRos.getenv(DATA_DIR,data)然后咱们就可以修改咱们代码中用到大模型的地方了比如llm_utils.py中咱们模型的调用部分可以按照下面的方式修改fromdotenvimportload_dotenvimportos load_dotenv()DEEPSEEK_API_KEYos.getenv(DEEPSEEK_API_KEY)DEEPSEEK_BASE_URLos.getenv(DEEPSEEK_BASE_URL,https://api.deepseek.com)EMBEDDING_API_KEYos.getenv(EMBEDDING_API_KEY)EMBEDDING_BASE_URLos.getenv(EMBEDDING_BASE_URL)CHAT_MODELos.getenv(CHAT_MODEL,deepseek-chat)EMBEDDING_MODELos.getenv(EMBEDDING_MODEL,text-embedding-3-small)DATA_DIRos.getenv(DATA_DIR,data)如果这篇文章对你有帮助可以点个赞完整代码地址https://github.com/1186141415/A-Paper-Rag-Agent