自定义LLM交互类¶
介绍¶
如果当前TFRobot不支持的LLM模型,开发者可以自行扩展LLM模型,通常继承ChatLLM即可。
开发重点¶
- 配置属性。对于LLM服务API接口一般会有一些配置属性,比如
api_key,temperature等。这些属性可以通过利用Pydantic数据模型进行属性定义。 - 重点实现方法,主要有以下方法:
construct_request_paramsLLM-API请求参数构建。这个方法其使命是将TFRobot内部的通用数据类转换为LLM-API所需的请求参数结构。construct_llm_resultLLMResult构建函数。这个方法其使命是将LLM-API返回的数据类型转换为TFRobot内部通用的LLMResult类。complete大语言模型的工作函数,主要完成API调用,其主要能力有两个方面:- 通信:除了与LLM服务完成通信,也需要通过配合OpenTelemetry将与LLM的通信进度与结果对外输出,保证用户可以实时获取到当前LLM工作进展。
- 重试:如果遇到问题导致的请求异常,可以进行重试。特殊的一点是如果遇到上下文超长问题,可以通过截断上下文进行重试。这一部分的关键在于如何从错误中识别上下文超长的问题。
其它细节¶
collapse_context折叠上下文的函数,在基类中已经进行了一轮通用实现。一般来讲子类实现只需要按要求调用即可。但基类的实现不满足要求,比如折叠规则不对,提供的参数也无法通过配置达到要求。则可以自行实现此方法对其进行替换。tokenize_str计算字符串的token数量。这个方法在基类中已经进行了一轮通用实现。一般来讲LLM-Server应该提供Token统计的能力,借助LLM-Server的统计能力,可以尽可能地不使用此方法,但此方法可以用于在LLM-Server不提供统计能力的情况下,通过字符串配合Tiktoken库进行统计。但如果Tokenizer使用的并非Tiktoken等情况,可以自行实现此方法进行替换。
具体的实现可以参考目前的封装。比如GPT,Claude等
细节介绍¶
-
@retry装饰器.@retry( stop=stop_after_attempt(3), wait=wait_exponential(multiplier=1, min=4, max=10), retry=retry_if_exception_type((openai.APITimeoutError, openai.APIConnectionError)), before_sleep=before_sleep_log(logger, logging.WARN), )需要重点关注retry的条件,使用的是retry_if_exception_type,如果complete方法中使用的是openai的SDK,则可以使用这些异常(当前可以根据自身情况添加其它异常或者减少异常)。但如果使用的是httpx库的Client进行API请求,则需要标记httpx的相关异常,比如httpx.HTTPStatusError等,具体遇到哪些异常后重试,一般是在调试过程中确定的,需要多写测试的Case进行观察,制定最终策略。
-
collapse_context方法try: chat_completion_stream: Stream[ChatCompletionChunk] = cast( Stream[ChatCompletionChunk], self._client.chat.completions.create(**params), ) except BadRequestError as e: if e.body["code"] == "context_length_exceeded": # type: ignore if not self.context_window or not self.max_tokens or self.max_tokens is inspect.Parameter.empty: raise ValueError("目前Prompt超过最大上下文,但当前配置未指定模型上下文相关配置,故而无法自动伸缩")不同的LLM服务端其上下文过长的异常反馈不一,有很多往往没有独立的状态码标识,这对于识别返回时「超长上下文捕获」提出了挑战,目前来讲,通用的思路,也是触发一下超长的异常后,通过断点来查看异常的具体信息,然后根据异常信息来进行判断,比如上面代码以目前OpenAI的SDK为例进行捕获。