agent请求增加出错重试机制
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
import asyncio
|
import asyncio
|
||||||
|
import time
|
||||||
from concurrent.futures import ThreadPoolExecutor
|
from concurrent.futures import ThreadPoolExecutor
|
||||||
from threading import Lock
|
from threading import Lock
|
||||||
from typing import TypedDict
|
from typing import TypedDict
|
||||||
@@ -7,6 +8,8 @@ import httpx
|
|||||||
|
|
||||||
from docutranslate.logger import translater_logger
|
from docutranslate.logger import translater_logger
|
||||||
|
|
||||||
|
MAX_RETRY_COUNT = 3
|
||||||
|
|
||||||
|
|
||||||
class AgentArgs(TypedDict, total=False):
|
class AgentArgs(TypedDict, total=False):
|
||||||
baseurl: str
|
baseurl: str
|
||||||
@@ -39,6 +42,8 @@ class Agent:
|
|||||||
def __init__(self, baseurl: str = "", key: str = "xx", model_id: str = "", system_prompt: str = "", temperature=0.7,
|
def __init__(self, baseurl: str = "", key: str = "xx", model_id: str = "", system_prompt: str = "", temperature=0.7,
|
||||||
max_concurrent=15, timeout: int = TIMEOUT):
|
max_concurrent=15, timeout: int = TIMEOUT):
|
||||||
self.baseurl = baseurl.strip()
|
self.baseurl = baseurl.strip()
|
||||||
|
if self.baseurl.endswith("/"):
|
||||||
|
self.baseurl = self.baseurl[:-1]
|
||||||
self.key = key.strip()
|
self.key = key.strip()
|
||||||
self.model_id = model_id.strip()
|
self.model_id = model_id.strip()
|
||||||
self.system_prompt = system_prompt
|
self.system_prompt = system_prompt
|
||||||
@@ -47,6 +52,7 @@ class Agent:
|
|||||||
self.client_async = httpx.AsyncClient(trust_env=False, proxy=None, verify=False)
|
self.client_async = httpx.AsyncClient(trust_env=False, proxy=None, verify=False)
|
||||||
self.max_concurrent = max_concurrent
|
self.max_concurrent = max_concurrent
|
||||||
self.timeout = timeout
|
self.timeout = timeout
|
||||||
|
|
||||||
def _prepare_request_data(self, prompt: str, system_prompt: str, temperature=None, top_p=0.9):
|
def _prepare_request_data(self, prompt: str, system_prompt: str, temperature=None, top_p=0.9):
|
||||||
if temperature is None:
|
if temperature is None:
|
||||||
temperature = self.temperature
|
temperature = self.temperature
|
||||||
@@ -64,14 +70,13 @@ class Agent:
|
|||||||
}
|
}
|
||||||
return headers, data
|
return headers, data
|
||||||
|
|
||||||
async def send_async(self, prompt: str, system_prompt: None | str = None) -> str:
|
async def send_async(self, prompt: str, system_prompt: None | str = None, retry=True, retry_count=0) -> str:
|
||||||
if system_prompt is None:
|
if system_prompt is None:
|
||||||
system_prompt = self.system_prompt
|
system_prompt = self.system_prompt
|
||||||
|
if prompt.strip() == "":
|
||||||
"""Sends a single prompt asynchronously."""
|
return prompt
|
||||||
headers, data = self._prepare_request_data(prompt, system_prompt)
|
headers, data = self._prepare_request_data(prompt, system_prompt)
|
||||||
if self.baseurl.endswith("/"):
|
|
||||||
self.baseurl = self.baseurl[:-1]
|
|
||||||
try:
|
try:
|
||||||
response = await self.client_async.post(
|
response = await self.client_async.post(
|
||||||
f"{self.baseurl}/chat/completions",
|
f"{self.baseurl}/chat/completions",
|
||||||
@@ -83,12 +88,19 @@ class Agent:
|
|||||||
result = response.json()["choices"][0]["message"]["content"]
|
result = response.json()["choices"][0]["message"]["content"]
|
||||||
return result
|
return result
|
||||||
except httpx.HTTPStatusError as e:
|
except httpx.HTTPStatusError as e:
|
||||||
print(f"AI请求错误,prompt:{prompt}\n")
|
translater_logger.error(f"AI请求错误 (async): {e.response.status_code} - {e.response.text}")
|
||||||
raise Exception(f"AI请求错误 (async): {e.response.status_code} - {e.response.text}") from e
|
|
||||||
except httpx.RequestError as e:
|
except httpx.RequestError as e:
|
||||||
raise Exception(f"AI请求连接错误 (async): {e}") from e
|
translater_logger.warning(Exception(f"AI请求连接错误 (async): {repr(e)}\nprompt:{prompt}"))
|
||||||
except (KeyError, IndexError) as e:
|
except (KeyError, IndexError) as e:
|
||||||
raise Exception(f"AI响应格式错误 (async): {e}") from e
|
translater_logger.error(f"AI响应格式错误 (async): {repr(e)}")
|
||||||
|
return ""
|
||||||
|
if retry and retry_count < MAX_RETRY_COUNT:
|
||||||
|
translater_logger.info(f"正在重试,重试次数{retry_count}")
|
||||||
|
await asyncio.sleep(0.5)
|
||||||
|
return await self.send_async(prompt, system_prompt, retry=True, retry_count=retry_count + 1)
|
||||||
|
else:
|
||||||
|
translater_logger.error(f"达到重试次数上限")
|
||||||
|
return ""
|
||||||
|
|
||||||
async def send_prompts_async(
|
async def send_prompts_async(
|
||||||
self,
|
self,
|
||||||
@@ -122,14 +134,12 @@ class Agent:
|
|||||||
results = await asyncio.gather(*tasks, return_exceptions=False)
|
results = await asyncio.gather(*tasks, return_exceptions=False)
|
||||||
return results
|
return results
|
||||||
|
|
||||||
def send(self, prompt: str, system_prompt: None | str = None) -> str:
|
def send(self, prompt: str, system_prompt: None | str = None, retry=True, retry_count=0) -> str:
|
||||||
if system_prompt is None:
|
if system_prompt is None:
|
||||||
system_prompt = self.system_prompt
|
system_prompt = self.system_prompt
|
||||||
|
if prompt.strip() == "":
|
||||||
"""Sends a single prompt asynchronously."""
|
return prompt
|
||||||
headers, data = self._prepare_request_data(prompt, system_prompt)
|
headers, data = self._prepare_request_data(prompt, system_prompt)
|
||||||
if self.baseurl.endswith("/"):
|
|
||||||
self.baseurl = self.baseurl[:-1]
|
|
||||||
try:
|
try:
|
||||||
response = self.client.post(
|
response = self.client.post(
|
||||||
f"{self.baseurl}/chat/completions",
|
f"{self.baseurl}/chat/completions",
|
||||||
@@ -141,11 +151,19 @@ class Agent:
|
|||||||
result = response.json()["choices"][0]["message"]["content"]
|
result = response.json()["choices"][0]["message"]["content"]
|
||||||
return result
|
return result
|
||||||
except httpx.HTTPStatusError as e:
|
except httpx.HTTPStatusError as e:
|
||||||
raise Exception(f"AI请求错误 (async): {e.response.status_code} - {e.response.text}") from e
|
translater_logger.error(f"AI请求错误 (sync): {e.response.status_code} - {e.response.text}")
|
||||||
except httpx.RequestError as e:
|
except httpx.RequestError as e:
|
||||||
raise Exception(f"AI请求连接错误 (async): {e}") from e
|
translater_logger.warning(f"AI请求连接错误 (sync): {repr(e)}\nprompt:{prompt}")
|
||||||
except (KeyError, IndexError) as e:
|
except (KeyError, IndexError) as e:
|
||||||
raise Exception(f"AI响应格式错误 (async): {e}") from e
|
translater_logger.error(f"AI响应格式错误 (sync): {repr(e)}")
|
||||||
|
return ""
|
||||||
|
if retry and retry_count < MAX_RETRY_COUNT:
|
||||||
|
translater_logger.info(f"正在重试,重试次数{retry_count}")
|
||||||
|
time.sleep(0.5)
|
||||||
|
return self.send(prompt, system_prompt, retry=True, retry_count=retry_count + 1)
|
||||||
|
else:
|
||||||
|
translater_logger.error(f"达到重试次数上限")
|
||||||
|
return ""
|
||||||
|
|
||||||
def _send_prompt_count(self, prompt: str, system_prompt: None | str, count: PromptsCount) -> str:
|
def _send_prompt_count(self, prompt: str, system_prompt: None | str, count: PromptsCount) -> str:
|
||||||
result = self.send(prompt, system_prompt)
|
result = self.send(prompt, system_prompt)
|
||||||
|
|||||||
@@ -320,8 +320,8 @@ class FileTranslater:
|
|||||||
pico = f"<style>{resource_path("static/pico.css").read_text(encoding='utf-8')}</style>"
|
pico = f"<style>{resource_path("static/pico.css").read_text(encoding='utf-8')}</style>"
|
||||||
html_template = resource_path("template/markdown.html").read_text(encoding='utf-8')
|
html_template = resource_path("template/markdown.html").read_text(encoding='utf-8')
|
||||||
katex_css = f"<style>{resource_path("static/katex.css").read_text(encoding='utf-8')}</style>" if not cdn else r"""<link href="https://cdn.bootcdn.net/ajax/libs/KaTeX/0.16.9/katex.min.css" rel="stylesheet">"""
|
katex_css = f"<style>{resource_path("static/katex.css").read_text(encoding='utf-8')}</style>" if not cdn else r"""<link href="https://cdn.bootcdn.net/ajax/libs/KaTeX/0.16.9/katex.min.css" rel="stylesheet">"""
|
||||||
katex_js = f"<script>{resource_path("static/katex.js").read_text(encoding='utf-8')}</script>" if not cdn else r"""<script src="https://cdn.bootcdn.net/ajax/libs/KaTeX/0.16.9/katex.min.js"></script>"""
|
katex_js = f"<script>{resource_path("static/katex.js").read_text(encoding='utf-8')}</script>" if not cdn else r"""<script defer src="https://cdn.bootcdn.net/ajax/libs/KaTeX/0.16.9/katex.min.js"></script>"""
|
||||||
auto_render = f'<script>{resource_path("static/autoRender.js").read_text(encoding='utf-8')}</script>' if not cdn else r"""<script src="https://cdn.bootcdn.net/ajax/libs/KaTeX/0.16.9/contrib/auto-render.min.js"></script>"""
|
auto_render = f'<script>{resource_path("static/autoRender.js").read_text(encoding='utf-8')}</script>' if not cdn else r"""<script defer src="https://cdn.bootcdn.net/ajax/libs/KaTeX/0.16.9/contrib/auto-render.min.js"></script>"""
|
||||||
# language=javascript
|
# language=javascript
|
||||||
renderMathInElement = r"""
|
renderMathInElement = r"""
|
||||||
<script>
|
<script>
|
||||||
|
|||||||
Reference in New Issue
Block a user