更新.gitignore文件以忽略日志文件,新增api_key.txt文件以管理API密钥,并在对话转工单和查询完整性判断模块中添加日志记录和堆栈跟踪功能,提升错误处理和调试能力。

This commit is contained in:
2025-06-20 09:43:37 +08:00
parent e0e893eb09
commit 450a632ad2
6 changed files with 196 additions and 127 deletions
+1 -1
View File
@@ -8,4 +8,4 @@ data/excel/*
rag2_0/demo/Test.py rag2_0/demo/Test.py
data/excel/*.xlsx data/excel/*.xlsx
rag2_0/demo/ProfessionalTermAnalyzer.py rag2_0/demo/ProfessionalTermAnalyzer.py
mariadb_client.log data/logs/*
+118
View File
@@ -0,0 +1,118 @@
sk-kvgfuqeqvpmfsccykyoohheshclcrtvjlnewratvrjpkpbkc
sk-mxbapcczwjsyrictwgigxgcvdgptyfrlynrewqioegqwrggv
sk-dujjzxrknevesbagqgqmuffxsosjoueviubnmodoormlmlzt
sk-lsukfggzghmdhtfhqcbmlfqabbtapwpuxnvtwshqqqlaesie
sk-aulumxzhvaladchcwgmsxidtdsvzytbpvzqgfuvcxlwbwcgl
sk-otxxemniwhxkdvroszmmkitswwuykosnqoldrkzdoflqpgvw
sk-zlruqobfdbjebyyvkmehakpcvfgnlfbdlbfrepusazzckbnv
sk-zryimztrlkgvcaiolarhvbcewmhwruhqfcndbylonzlqvdox
sk-rczjqufgdisqplkrmvhaxmdgcboluvxympvzljlreuqeeviq
sk-xfnvcksdgwufsktvmhpqrwpgovsxxtaeehtxnaqjtxmubqzl
sk-gcostftlutooxzsnqefcgyfxqytidvfjpxhbuxppgatwczoq
sk-wwonvjnowbcxmoyoluynnkjwerghspzdulyidskunkordaft
sk-qmrkfvvbbfssuoreyvwqawoveyowuvxviqzqknotyweqmuog
sk-nprpuknjmikvoaxnwgyshwwwtnifvixpuqtzkzmcacdnvoib
sk-xanwnicepdxfqrfejzuxjcrhdsglfypkoxlcmmtamrtjkork
sk-lvtdgodiaurqyiwdxtdrgxifguychhccqlqkhqctscvqbfgi
sk-aedlbtlmqcttxwnvlfmxzaysamocamqxjceoyqjfgpcowybw
sk-fahdvndjblyjlizamvwcrxnilsgmbgbvwssxgquhkezgpqne
sk-tzludgttzxvpvwayazdbppbauvathdtccafjrhojpemucgyi
sk-hrbroidbfusidwnsmxenuzljxgdzzxiimlezygxplavnxjik
sk-ylgoiqxmtxeojdnonthxtweungyzldaqarvjxlqyztlvyrff
sk-asuqbqwdhjcqnvtjlwufyrkrwkobnrbmukzarvcctsgjipdp
sk-dpgpymiydutoexgvkajwgahagnfmcqzafwulccudnzvleifz
sk-nbksjgcngsayoumnsdbkcpnqivnvxjenwpzuazzrkhnsgeoo
sk-iaafvpjyqiocgzchbdldbkgcffqniahkcbgoviuevuogulcm
sk-jgybgyayxlwoxeijgrjcneqlyusleohgbliuwpsuhocrjsmk
sk-wzjsmwxcbbpcrqivqfzjwufqqjtlwejtncnvbpeicznkwiuh
sk-izdjicdoyillktsihkiapuvwebisehtlgykozrvzfkgncwsc
sk-fcsfmyivfuojsqsditvobfqprdpeunukycpcfnoxkraqevpx
sk-szyjgyxrcvyxpvzfwgmbxnflxngxvcplitcctsdvvrqjgftk
sk-jzbodthsnvjwbyrnynsxrudtqfnbdbrcxebjwjgajocnzqse
sk-fxepossfzpmccibfwqpkluorzqlbtcaplepeugtfzfsctcbl
sk-ympnflocrkxjrbubsxqdjqwicuyavvvysctlpfhunkcrzxjx
sk-flhqvziknntednkcgjaxlyzzsrfzjhrzrmteqonajpbiinni
sk-xfregpbbquqbxpiobjzanydsjivrjrnbokzxcqtnhxhyghhe
sk-jrdzerhmvrtvzawkksowbgkggkubwfquplmrxbdhespqgtis
sk-jjbpnkbeupsxyclcivbhizcfpfjrppddunbqynyjkqhtmpwu
sk-oqehupcveovkjqqtxypqyifidcdissuyehwrkdwgruoyjkpq
sk-jnnmltwtqwuoyagoogzzeraczmyfxhoairiddgayksqdfnbr
sk-eghuepxnbcollzrjwbzqvbnhiiwagkejaclyhvaodeqgwrog
sk-poszkbjdmamimconjustnrxxqusuzlryxkrzkpronlenrmen
sk-zolvcegarsrwqhwgvwzgtqupodsdmckjiocyvoyldbkusbzc
sk-ywfafulcniaqdgdcsnbtqquaqeuiqlkcnknkaflwxyuemcow
sk-hhedmocgtfpywbbpwamgfkygrahiqsuurntlbqqbmjwfipmm
sk-gzdqfoyvulrqscdpjlwlufdecrsyjpmwpkknuhnjsvtyftox
sk-bkcufidsebujopqqwexwxwpmevrpelmvxzdymncvllcyojce
sk-olabhscekudzkyudypkcjvehwqunagubwdmtppugrjmcptwv
sk-zpdqyocliebhqpkuwvebpgcnfjdkvavdltimllmgkthwnwph
sk-gvhchlfelocjniuydusyhhwacnomxnvucjonzkhtqoplnbcr
sk-lzneagvdxhisodndnxnpkntghpkimjmjsebiqdzaoqzuhbla
sk-xotcfdkigykevngedupitbcatjqppxmcibjtcebyoglykuxz
sk-ufydqsdqnwsegaqwtappzwdyzqnoblyunfvslomnnmykedgk
sk-jwasykftbkyjzdqlwcxuicrwzxsbhttilxfefbrozrznpwlv
sk-xngteojwkxmftyaabjdwwgyoadspsowmcpcqobteutdcfmnr
sk-akzkgniebruqrtuqskvlibkpcxjuazhcatysptkfyqivldfn
sk-vpqkxtmcgkggllexchzysuewyfaoexzasoumxngdplzgwksw
sk-fvcsqdbqmdlwxzjyofrilusqcypbfyczogaqwqrjrwvojmer
sk-htjprscvfgskjtjzpxxxjhyymshagogykpawxekrrfbgftyx
sk-vtlgznzanapdinnlpuuygdidejxvlvlziolumckxwntzvxcn
sk-npwaykpqovytxhihxepeaxuwgnzvqvscirwbiffudyebibwe
sk-kduozskjwsbxytajaedemqemimflzoqdrfbbuopuogbxptos
sk-cmyaaofqksxeccaiswwholizxtdhqoszpilbqhmwwablwtwl
sk-zltwpyvzodfszrvqcmjxycfshshmqmgtpghiaulcrtrilqup
sk-svpublkronxohqmjvtdemtyqopuwyknynmxvurkmmoqsfesk
sk-tindfeurhffenyetmblplxgytcgqnbbruatchpddtstnajvq
sk-ttwgosljnfdqbevvfkjewspoasountxeyiesuuwwpuoseatw
sk-ikzwjzfxxnocfqvkhbolmmnojdqfvdxzmlruynfoneahgraq
sk-zomatpdlatgtzvuoeabofeandiiespmsinosenjlmdigkvjk
sk-xypcnibvqgebhwvsudjuxlycwombofshifpltstezflountf
sk-vhtbtqsdyhwsrsitpppjpulbpnwlhjeeaujccggdjvjtucru
sk-ygqyapfsdpxxzihadttugvofrcgwlnsrqjvrqfrsrlgqidch
sk-cczurtilupwyrnqnjpdjltzamjbpyaxnwgzqoykvfwecezhs
sk-hsalsmvnzmvlknpzldciqligtjrvhcjdbjtcqhorptsgoisr
sk-ierjdccoycmipzflzvzjqdmjazmbczxhwejwrjmuouxpcqev
sk-rlthtjzrxkdlfsemijumxiwwsoxkwnjovobtqwprhnducsqi
sk-doocedvfjsmwysxyzpptojnwwuoucxvrknlrdsnomffljems
sk-tgxnplgtwawfnnetghvlzoinksickbynzsgovbrmlrkzzrsy
sk-aggkwzdteggbcgyzimiivphpzibnpmqfbkmgtwyggsjfdymg
sk-tzynazayiglcpzejedpfdftqvtuqynygluorjbbcvrnmsbfl
sk-mcaqucnscgznmtvtzhooxbdafzhcgjgpusnjfbftroedzujk
sk-mlfnxfmwwhturavnsbyedkgrhxfspbfitfyqkllezgdtzhwn
sk-meaqykzphtqqoiswdtbxfqndddmtgvwrdnzdxprozlumrojs
sk-vrtfrtioocmrylrrqpburhkgwmyxfipnissumgufmjpzjqoo
sk-rhknxievjjjzcmkvfwqosnaiglsoufytfkbhhgconiibwriy
sk-wzsvxjfnvpceeoapbzdimpwecckpmcsqmflocttnqyvqvrsr
sk-lflfajincbdljrfwkhrjunyolzuxtcfdbzmspyfizpbdwvvh
sk-siujvueppvhhokbofqlcdxudpswdfwpetvxyittpbarddhsu
sk-avpyhivanabvdyorypdmlqnfetivlwoovfvgsgklumxeqgzy
sk-fvmpnspfeleqrgumwnvzevbtgmdqvftlbvswoghrtxfengfa
sk-wxaeehghpdettyrsnhjrawddnqzxghfjbkkokbwtnbdocsmi
sk-yighqmadjhvixkhjpcknrkapqsyxmphcqvjhlbfzgigfghft
sk-orepiytzucdtxgnxuxhekaivcpzwnunpiauccujrhbkifodc
sk-qsfrireujzrpomdjcfcgbfqncnferyzfcsralnszvurfvkgz
sk-tjienchcxamgldtzjtigpitklsonwcuhyhltswwcnsfhmois
sk-gdtqulaciovvnzwklpckwyheysaplirhgimzreqzkhfxotjh
sk-rqhynqmafsydevjctxeuqizuiithschhiztmqnpawqjjbhyv
sk-idrdvmcgmjmoxowxswfcorfdjmprfukrumimaljjnlwqkazu
sk-hrrmqrhscocbzhpfkzuoptnubgfiedololapvyfftapaawdb
sk-rtqzxuylhryzqnotvkzelvhomuovmbvpxrytydvqevisciwg
sk-ttgsojzjchifbrpwfmcajfujbxexbyvlovgbgpfdvkzqjzpu
sk-tvclqjccfylijwcujuxpppvnumkvmxbctevfqfxjryyygoep
sk-qyazelyawtgyohimgbswwetajekuvmyteweviovvqsjybtwq
sk-zowapfiiqrpeuahmnkopcyccwiyzweigvekiusiuirtsfmbj
sk-qwanpokfsquwwrpxceavasxwmxjarfaxheraamqhsyegfgum
sk-smqpfdbcnhpifwsrpwutwzpscbkeinkmfeoabesztmnicvez
sk-cnvevlfppneiztcgayxiydukhexujtiqjajpdhbrtnenizxe
sk-jmjgjraheompbftegtdzrwcnlyxsfhtrjootwuqirgmodxdm
sk-tfkyyzbhdowskndsnqkniivwhmmfmhnjdzitgvwhmhfrobeh
sk-spjtulrgqkvepawufkloxktfmkyjjhffnmzcththdmnlqkwp
sk-xafrjoiwnundkubilpoxmzpmbsizljfgrerckqgpcnvguqma
sk-dtjwhkzhljzzmchfvoyywjbsdpvgtgnlpzdkgegwnjjnsesc
sk-lurglxyefchyowvybancbtxdavndwvcengfhcrzcdouqsdmp
sk-nckmscferrehepawtytvvzzcexsgbxszmrerkwvzsbvnwckq
sk-hpgusoznbejkugxugsstyezaihqatwmwiwelwjwudekoxlbq
sk-yyqtojpqfrtkyvmhbjvnzhuujzgvitqpuxkytgxspwqscptz
sk-vcwenoaiegiwqhdvalxrvttwqmcrudttpfqhlvtdocsxvvob
sk-npnyztbrdaqtbnldlvfelkfbfozykuwykkkfsrsisytusymj
sk-rjaadeqsgoskclkuqkkyjxdknngrdsjwlgucqutiskroprzk
+24 -10
View File
@@ -11,10 +11,23 @@ from langchain.output_parsers import PydanticOutputParser
from rag2_0.tool.ModelTool import OpenAiLLM from rag2_0.tool.ModelTool import OpenAiLLM
from dotenv import load_dotenv from dotenv import load_dotenv
import httpx import httpx
import traceback
import re import re
import logging
load_dotenv() load_dotenv()
# 配置日志
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
handlers=[
logging.StreamHandler(),
logging.FileHandler('dialogue_to_workorder.log', encoding='utf-8')
]
)
logger = logging.getLogger("dialogue_to_workorder")
# ================ 模型定义 ================ # ================ 模型定义 ================
class UserQuestionAndSolution(BaseModel): class UserQuestionAndSolution(BaseModel):
user_question: str = Field(description="用户的核心问题") user_question: str = Field(description="用户的核心问题")
@@ -60,12 +73,13 @@ def retry_llm_call(max_retries=3, delay=2):
except Exception as e: except Exception as e:
last_exception = e last_exception = e
retries += 1 retries += 1
print(f"LLM调用失败,正在进行第{retries}次重试: {str(e)}") logger.warning(f"LLM调用失败,正在进行第{retries}次重试: {str(e)}")
if retries < max_retries: if retries < max_retries:
time.sleep(delay*retries) time.sleep(delay*retries)
stack_trace = traceback.format_exc()
logger.error(f"LLM调用失败,堆栈跟踪信息:\n{stack_trace}")
# 所有重试都失败后,抛出最后一次的异常 # 所有重试都失败后,抛出最后一次的异常
print(f"LLM调用失败,已达到最大重试次数{max_retries}") logger.error(f"LLM调用失败,已达到最大重试次数{max_retries}")
raise last_exception raise last_exception
return wrapper return wrapper
@@ -472,8 +486,8 @@ class DialogueToWorkorder:
df = pd.read_excel(conversation_excel_path) df = pd.read_excel(conversation_excel_path)
# 检查数据框的列 # 检查数据框的列
print(f"Excel文件列名: {df.columns.tolist()}") logger.info(f"Excel文件列名: {df.columns.tolist()}")
print(f"数据总行数: {len(df)}") logger.info(f"数据总行数: {len(df)}")
# 解析产品详情 # 解析产品详情
product_detail_dict = self.parse_product_detail_excel(product_detail_excel_path) product_detail_dict = self.parse_product_detail_excel(product_detail_excel_path)
@@ -482,7 +496,7 @@ class DialogueToWorkorder:
conversation_dict = self.group_conversations_by_id(df) conversation_dict = self.group_conversations_by_id(df)
# 限制处理的会话数量为前2000个 # 限制处理的会话数量为前2000个
if len(conversation_dict) > 2000: if len(conversation_dict) > 2000:
print(f"会话总数为 {len(conversation_dict)},限制处理前2000个会话") logger.info(f"会话总数为 {len(conversation_dict)},限制处理前2000个会话")
# 获取所有会话ID # 获取所有会话ID
conversation_ids = list(conversation_dict.keys()) conversation_ids = list(conversation_dict.keys())
# 只保留前2000个会话 # 只保留前2000个会话
@@ -492,7 +506,7 @@ class DialogueToWorkorder:
} }
conversation_dict = limited_conversation_dict conversation_dict = limited_conversation_dict
else: else:
print(f"会话总数为 {len(conversation_dict)},处理全部会话") logger.info(f"会话总数为 {len(conversation_dict)},处理全部会话")
# 使用线程池处理每个会话 # 使用线程池处理每个会话
workorder_dict_list = [] workorder_dict_list = []
with concurrent.futures.ThreadPoolExecutor(max_workers=max_workers) as executor: with concurrent.futures.ThreadPoolExecutor(max_workers=max_workers) as executor:
@@ -509,9 +523,9 @@ class DialogueToWorkorder:
result_workorders = future.result() result_workorders = future.result()
# 将每个会话的所有工单添加到总列表中 # 将每个会话的所有工单添加到总列表中
workorder_dict_list.extend(result_workorders) workorder_dict_list.extend(result_workorders)
print(f"完成处理会话ID: {conversation_id},生成工单数量: {len(result_workorders)}") logger.info(f"完成处理会话ID: {conversation_id},生成工单数量: {len(result_workorders)}")
except Exception as exc: except Exception as exc:
print(f"处理会话ID: {conversation_id} 时发生错误: {exc}") logger.error(f"处理会话ID: {conversation_id} 时发生错误: {exc}")
return workorder_dict_list return workorder_dict_list
@@ -581,7 +595,7 @@ class DialogueToWorkorder:
col_letter = chr(64 + i // 26) + chr(65 + i % 26) col_letter = chr(64 + i // 26) + chr(65 + i % 26)
worksheet.column_dimensions[col_letter].width = column_widths[column] worksheet.column_dimensions[col_letter].width = column_widths[column]
print(f"结果已保存到 {output_file}") logger.info(f"结果已保存到 {output_file}")
return output_file return output_file
+4 -1
View File
@@ -22,6 +22,7 @@ import os
import time import time
import re import re
import argparse import argparse
import traceback
from pathlib import Path from pathlib import Path
from rag2_0.tool.ModelTool import OpenAiLLM from rag2_0.tool.ModelTool import OpenAiLLM
from rag2_0.tool.APIKeyManager import APIKeyManager from rag2_0.tool.APIKeyManager import APIKeyManager
@@ -194,8 +195,10 @@ class QueryCompletenessJudge:
retry_delay *= 2 retry_delay *= 2
else: else:
# 已达到最大重试次数,返回错误 # 已达到最大重试次数,返回错误
stack_trace = traceback.format_exc()
print(f"错误: 经过 {max_retries} 次重试后仍然失败: {str(e)}") print(f"错误: 经过 {max_retries} 次重试后仍然失败: {str(e)}")
return False, f"错误: 经过 {max_retries} 次重试后仍然失败: {str(e)}" print(f"堆栈跟踪信息:\n{stack_trace}")
return False, f"错误: 经过 {max_retries} 次重试后仍然失败: {str(e)}\n堆栈摘要: {str(e).__class__.__name__}"
# 不应该到达这里,但为了代码完整性添加 # 不应该到达这里,但为了代码完整性添加
return False, "未知错误:重试机制逻辑错误" return False, "未知错误:重试机制逻辑错误"
+45 -111
View File
@@ -17,104 +17,6 @@ import requests
# sk-bdagppigfxexcofiossccywvcqggbpywjapkdbtqycbgvqpz # sk-bdagppigfxexcofiossccywvcqggbpywjapkdbtqycbgvqpz
# sk-dvbaktabkdwdpjgxyoozlwnejosjyhdgqwllfeborqahndxs # sk-dvbaktabkdwdpjgxyoozlwnejosjyhdgqwllfeborqahndxs
API_KEY_LIST=[
"sk-kvgfuqeqvpmfsccykyoohheshclcrtvjlnewratvrjpkpbkc",
"sk-kzhxlqvqcxlnbdgnpalqnzumkmspepkttkgbophnkqanainw",
"sk-tovmogiablsoeabwgqyvevpcfichyjpuzqdymmvksspdrtqt",
"sk-yvyvoiegjrdlgihnxlaaznzdhnvpmfowtwmofomcodaoeaqs",
"sk-vccwuaomxhjcszjhheipoqqmsnuetasiveombkyrptstesbi",
"sk-mxbapcczwjsyrictwgigxgcvdgptyfrlynrewqioegqwrggv",
"sk-dujjzxrknevesbagqgqmuffxsosjoueviubnmodoormlmlzt",
"sk-rpptsvdeifcnyfkkrwnphgkrlchrqrbkglxrmztdzvfutdor",
"sk-lsukfggzghmdhtfhqcbmlfqabbtapwpuxnvtwshqqqlaesie",
"sk-aulumxzhvaladchcwgmsxidtdsvzytbpvzqgfuvcxlwbwcgl",
"sk-tzdqzroakecvseclcmrbhdnepveatybhhzxfpzxzgirpqcdy",
"sk-otxxemniwhxkdvroszmmkitswwuykosnqoldrkzdoflqpgvw",
"sk-zlruqobfdbjebyyvkmehakpcvfgnlfbdlbfrepusazzckbnv",
"sk-zryimztrlkgvcaiolarhvbcewmhwruhqfcndbylonzlqvdox",
"sk-rczjqufgdisqplkrmvhaxmdgcboluvxympvzljlreuqeeviq",
"sk-xfnvcksdgwufsktvmhpqrwpgovsxxtaeehtxnaqjtxmubqzl",
"sk-gcostftlutooxzsnqefcgyfxqytidvfjpxhbuxppgatwczoq",
"sk-wwonvjnowbcxmoyoluynnkjwerghspzdulyidskunkordaft",
"sk-rbuykocecbdoqteveeggwzvrhbvisgaerffexjsnyvjefhdk",
"sk-qmrkfvvbbfssuoreyvwqawoveyowuvxviqzqknotyweqmuog",
"sk-nprpuknjmikvoaxnwgyshwwwtnifvixpuqtzkzmcacdnvoib",
"sk-xanwnicepdxfqrfejzuxjcrhdsglfypkoxlcmmtamrtjkork",
"sk-lvtdgodiaurqyiwdxtdrgxifguychhccqlqkhqctscvqbfgi",
"sk-aedlbtlmqcttxwnvlfmxzaysamocamqxjceoyqjfgpcowybw",
"sk-fahdvndjblyjlizamvwcrxnilsgmbgbvwssxgquhkezgpqne",
"sk-tzludgttzxvpvwayazdbppbauvathdtccafjrhojpemucgyi",
"sk-hrbroidbfusidwnsmxenuzljxgdzzxiimlezygxplavnxjik",
"sk-ylgoiqxmtxeojdnonthxtweungyzldaqarvjxlqyztlvyrff",
"sk-asuqbqwdhjcqnvtjlwufyrkrwkobnrbmukzarvcctsgjipdp",
"sk-dpgpymiydutoexgvkajwgahagnfmcqzafwulccudnzvleifz",
"sk-nbksjgcngsayoumnsdbkcpnqivnvxjenwpzuazzrkhnsgeoo",
"sk-iaafvpjyqiocgzchbdldbkgcffqniahkcbgoviuevuogulcm",
"sk-muvjguqeshyimzowqnqgxwpsgujlpkqgrisxsimthtyrpypx",
"sk-jgybgyayxlwoxeijgrjcneqlyusleohgbliuwpsuhocrjsmk",
"sk-wzjsmwxcbbpcrqivqfzjwufqqjtlwejtncnvbpeicznkwiuh",
"sk-izdjicdoyillktsihkiapuvwebisehtlgykozrvzfkgncwsc",
"sk-fcsfmyivfuojsqsditvobfqprdpeunukycpcfnoxkraqevpx",
"sk-szyjgyxrcvyxpvzfwgmbxnflxngxvcplitcctsdvvrqjgftk",
"sk-jzbodthsnvjwbyrnynsxrudtqfnbdbrcxebjwjgajocnzqse",
"sk-fxepossfzpmccibfwqpkluorzqlbtcaplepeugtfzfsctcbl",
"sk-ympnflocrkxjrbubsxqdjqwicuyavvvysctlpfhunkcrzxjx",
"sk-flhqvziknntednkcgjaxlyzzsrfzjhrzrmteqonajpbiinni",
"sk-xfregpbbquqbxpiobjzanydsjivrjrnbokzxcqtnhxhyghhe",
"sk-jrdzerhmvrtvzawkksowbgkggkubwfquplmrxbdhespqgtis",
"sk-jjbpnkbeupsxyclcivbhizcfpfjrppddunbqynyjkqhtmpwu",
"sk-oqehupcveovkjqqtxypqyifidcdissuyehwrkdwgruoyjkpq",
"sk-jnnmltwtqwuoyagoogzzeraczmyfxhoairiddgayksqdfnbr",
"sk-eghuepxnbcollzrjwbzqvbnhiiwagkejaclyhvaodeqgwrog",
"sk-poszkbjdmamimconjustnrxxqusuzlryxkrzkpronlenrmen",
"sk-zolvcegarsrwqhwgvwzgtqupodsdmckjiocyvoyldbkusbzc",
"sk-ywfafulcniaqdgdcsnbtqquaqeuiqlkcnknkaflwxyuemcow",
"sk-hhedmocgtfpywbbpwamgfkygrahiqsuurntlbqqbmjwfipmm",
"sk-gzdqfoyvulrqscdpjlwlufdecrsyjpmwpkknuhnjsvtyftox",
"sk-bkcufidsebujopqqwexwxwpmevrpelmvxzdymncvllcyojce",
"sk-olabhscekudzkyudypkcjvehwqunagubwdmtppugrjmcptwv",
"sk-zpdqyocliebhqpkuwvebpgcnfjdkvavdltimllmgkthwnwph",
"sk-gvhchlfelocjniuydusyhhwacnomxnvucjonzkhtqoplnbcr",
"sk-lzneagvdxhisodndnxnpkntghpkimjmjsebiqdzaoqzuhbla",
"sk-xotcfdkigykevngedupitbcatjqppxmcibjtcebyoglykuxz",
"sk-ufydqsdqnwsegaqwtappzwdyzqnoblyunfvslomnnmykedgk",
"sk-jwasykftbkyjzdqlwcxuicrwzxsbhttilxfefbrozrznpwlv",
"sk-xngteojwkxmftyaabjdwwgyoadspsowmcpcqobteutdcfmnr",
"sk-akzkgniebruqrtuqskvlibkpcxjuazhcatysptkfyqivldfn",
"sk-vpqkxtmcgkggllexchzysuewyfaoexzasoumxngdplzgwksw",
"sk-fvcsqdbqmdlwxzjyofrilusqcypbfyczogaqwqrjrwvojmer",
"sk-htjprscvfgskjtjzpxxxjhyymshagogykpawxekrrfbgftyx",
"sk-vtlgznzanapdinnlpuuygdidejxvlvlziolumckxwntzvxcn",
"sk-npwaykpqovytxhihxepeaxuwgnzvqvscirwbiffudyebibwe",
"sk-kduozskjwsbxytajaedemqemimflzoqdrfbbuopuogbxptos",
"sk-cmyaaofqksxeccaiswwholizxtdhqoszpilbqhmwwablwtwl",
"sk-zltwpyvzodfszrvqcmjxycfshshmqmgtpghiaulcrtrilqup",
"sk-svpublkronxohqmjvtdemtyqopuwyknynmxvurkmmoqsfesk",
"sk-tindfeurhffenyetmblplxgytcgqnbbruatchpddtstnajvq",
"sk-ttwgosljnfdqbevvfkjewspoasountxeyiesuuwwpuoseatw",
"sk-ikzwjzfxxnocfqvkhbolmmnojdqfvdxzmlruynfoneahgraq",
"sk-zomatpdlatgtzvuoeabofeandiiespmsinosenjlmdigkvjk",
"sk-xypcnibvqgebhwvsudjuxlycwombofshifpltstezflountf",
"sk-vhtbtqsdyhwsrsitpppjpulbpnwlhjeeaujccggdjvjtucru",
"sk-ygqyapfsdpxxzihadttugvofrcgwlnsrqjvrqfrsrlgqidch",
"sk-cczurtilupwyrnqnjpdjltzamjbpyaxnwgzqoykvfwecezhs",
"sk-hsalsmvnzmvlknpzldciqligtjrvhcjdbjtcqhorptsgoisr",
"sk-ierjdccoycmipzflzvzjqdmjazmbczxhwejwrjmuouxpcqev",
"sk-rlthtjzrxkdlfsemijumxiwwsoxkwnjovobtqwprhnducsqi",
"sk-doocedvfjsmwysxyzpptojnwwuoucxvrknlrdsnomffljems",
"sk-tgxnplgtwawfnnetghvlzoinksickbynzsgovbrmlrkzzrsy",
"sk-aggkwzdteggbcgyzimiivphpzibnpmqfbkmgtwyggsjfdymg",
"sk-tzynazayiglcpzejedpfdftqvtuqynygluorjbbcvrnmsbfl",
"sk-mcaqucnscgznmtvtzhooxbdafzhcgjgpusnjfbftroedzujk",
"sk-mlfnxfmwwhturavnsbyedkgrhxfspbfitfyqkllezgdtzhwn",
"sk-meaqykzphtqqoiswdtbxfqndddmtgvwrdnzdxprozlumrojs",
"sk-vrtfrtioocmrylrrqpburhkgwmyxfipnissumgufmjpzjqoo",
"sk-rhknxievjjjzcmkvfwqosnaiglsoufytfkbhhgconiibwriy",
"sk-wzsvxjfnvpceeoapbzdimpwecckpmcsqmflocttnqyvqvrsr",
"sk-lflfajincbdljrfwkhrjunyolzuxtcfdbzmspyfizpbdwvvh",
"sk-siujvueppvhhokbofqlcdxudpswdfwpetvxyittpbarddhsu",
"sk-avpyhivanabvdyorypdmlqnfetivlwoovfvgsgklumxeqgzy",
]
class APIKeyManager: class APIKeyManager:
""" """
@@ -129,6 +31,8 @@ class APIKeyManager:
_key_usage: Dict[str, Dict] = {} _key_usage: Dict[str, Dict] = {}
# 当前正在使用的密钥索引 # 当前正在使用的密钥索引
_current_index = 0 _current_index = 0
api_file_path = "api_key.txt"
@classmethod @classmethod
def get_instance(cls, env_var_name: str = "OPENAI_API_KEY", separator: str = ";"): def get_instance(cls, env_var_name: str = "OPENAI_API_KEY", separator: str = ";"):
@@ -193,7 +97,8 @@ class APIKeyManager:
], ],
"max_tokens": 1 "max_tokens": 1
} }
for key in API_KEY_LIST: instance = cls.get_instance()
for key in instance.api_keys:
headers = headers_template.copy() headers = headers_template.copy()
headers["Authorization"] = f"Bearer {key}" headers["Authorization"] = f"Bearer {key}"
try: try:
@@ -233,6 +138,24 @@ class APIKeyManager:
return response.json() return response.json()
@classmethod
def remove_invalid_api_keys(cls, api_keys: List[str]):
"""
移除无效的API密钥
"""
instance = cls.get_instance()
for key in api_keys:
instance.api_keys.remove(key)
@classmethod
def save_api_keys(cls):
"""
保存API密钥到文件
"""
instance = cls.get_instance()
with open(cls.api_file_path, "w") as f:
f.write("\n".join(instance.api_keys))
def __init__(self, env_var_name: str = "OPENAI_API_KEY", separator: str = ";"): def __init__(self, env_var_name: str = "OPENAI_API_KEY", separator: str = ";"):
""" """
初始化API密钥管理器 初始化API密钥管理器
@@ -260,17 +183,15 @@ class APIKeyManager:
Returns: Returns:
API密钥列表 API密钥列表
""" """
# api_keys = []
# env_value = os.environ.get(self.env_var_name) # 从文件中读取api_key
with open(self.api_file_path, "r") as f:
# if env_value: api_keys = f.readlines()
# # 分割环境变量并移除空白字符
# keys = [key.strip() for key in env_value.split(self.separator)] # 移除空白字符
# # 过滤掉空字符串 api_keys = [key.strip() for key in api_keys if key.strip()]
# api_keys = [key for key in keys if key]
return api_keys
# return api_keys
return API_KEY_LIST
def _get_next_api_key(self) -> Optional[str]: def _get_next_api_key(self) -> Optional[str]:
""" """
@@ -349,6 +270,19 @@ if __name__ == "__main__":
# 获取实例并查看使用统计 # 获取实例并查看使用统计
instance = APIKeyManager.get_instance() instance = APIKeyManager.get_instance()
stats = instance.get_usage_stats() stats = instance.get_usage_stats()
all_balance=0.0
buy_balance=16 * 10 * 14 # 购买16次,一次10条api_key,每个api_key有14元
invalid_api_keys = []
for key, data in stats.items(): for key, data in stats.items():
usage_stats = APIKeyManager.get_key_usage_stats(key) usage_stats = APIKeyManager.get_key_usage_stats(key)
print(f"api key:{key}---赠送余额:{usage_stats['data']['balance']}") all_balance+=float(usage_stats['data']['balance'])
print(f"api key:{key}---赠送余额:{usage_stats['data']['balance']}")
if float(usage_stats['data']['balance']) == 0:
invalid_api_keys.append(key)
print(f"剩余总赠送余额:{all_balance}元,累计消耗:{buy_balance-all_balance}")
print(f"无效的API密钥:{invalid_api_keys}")
print(f"开始移除无效的API密钥,并重新保存")
APIKeyManager.remove_invalid_api_keys(invalid_api_keys)
APIKeyManager.save_api_keys()
print(f"移除无效的API密钥,并重新保存完成")
+4 -4
View File
@@ -144,7 +144,10 @@ class OpenAiLLM:
max_retries = 3 max_retries = 3
retry_count = 0 retry_count = 0
if "timeout" not in self._kwargs:
timeout = httpx.Timeout(300.0)
self._kwargs["timeout"] = timeout
if need_retry: if need_retry:
while retry_count < max_retries: while retry_count < max_retries:
try: try:
@@ -154,7 +157,6 @@ class OpenAiLLM:
completion = client.chat.completions.create( completion = client.chat.completions.create(
model=self._model, model=self._model,
messages=[{'role': 'user', 'content': user_prompt}], messages=[{'role': 'user', 'content': user_prompt}],
timeout=httpx.Timeout(300.0),
**self._kwargs **self._kwargs
) )
return completion.choices[0].message return completion.choices[0].message
@@ -162,7 +164,6 @@ class OpenAiLLM:
except Exception as e: except Exception as e:
retry_count += 1 retry_count += 1
if retry_count == max_retries: if retry_count == max_retries:
logging.error(f"LLM 重试{max_retries}次后仍然失败: {e}")
raise e raise e
else: else:
time.sleep(5*retry_count) # 重试前等待1秒 time.sleep(5*retry_count) # 重试前等待1秒
@@ -173,7 +174,6 @@ class OpenAiLLM:
completion = client.chat.completions.create( completion = client.chat.completions.create(
model=self._model, model=self._model,
messages=[{'role': 'user', 'content': user_prompt}], messages=[{'role': 'user', 'content': user_prompt}],
timeout=httpx.Timeout(300.0),
**self._kwargs **self._kwargs
) )
return completion.choices[0].message return completion.choices[0].message