likes
comments
collection
share

Langchain设置Proxy后 Request timed out

作者站长头像
站长
· 阅读数 6

python/langchain

简介

    在使用Langchain 0.1.x版本的时候,使用ChatOpanAI类和其它相关类设置Proxy时不生效, 因为在0.1.1x版本中Langchain底层对于HTTP的请求,目前底层使用的是Httpx包,而Httpx的代理设置有点不同。

版本

python 10

langchain = "~=0.1.x"

openai = "~=1.13.3"

langchain-openai = "~=0.1.1"

代码样例

# 基于Langchain创建ChatOpenAI,并且设置proxy
llm = ChatOpenAI(openai_proxy="http://127.0.0.1:8889", **confs)

# 在不用科学上网的全局代理时会报错:
openai.APITimeoutError: Request timed out.


解决方法

1. 科学上网全局代理

    这个适合自用电脑,但是在服务器上,不实用,一般公司服务器内部有代理。

2. 代码内设置全局代理

    设置全局代理能解决Api timeout问题,但是会影响内部的API 访问, 导致请求国内的模型也走代理,使得国外模型正常,国内模型Timeout。

import os
os.environ["http_proxy"] = llm_conf.get('proxy')
os.environ["https_proxy"] = llm_conf.get('proxy')
llm = ChatOpenAI(**confs)

3. 源代码修改代理

    这个目前在网上很多方案都是直接修改Openai库的源代码,用于覆盖创建httpx Client时的Proxy,这种方案需要修改源代码,库包更新会被覆盖, openai/_base_client.py AsyncAPIClient, SyncAPIClient两处添加如下代码:

    if base_url is not None and 'api.openai' in base_url:
        print(f"openai/_base_client.py/{self.__name__}")
        # 用户定义
        user_define_proxies = {"http://": "http://127.0.0.1:8889", "https://": "http://127.0.0.1:8889"}
        # 覆盖代码内传的proxies
        proxies = user_define_proxies

4. httpx client创建

    其实从方案3的Openai源代码可知,此处是用于创建httpx的客户端,然后基于Stream的True/False,创建AsyncAPIClient或者SyncAPIClient,而在ChatOpenAI的类属性中发现可以传入http_client的,注意:在langchain-openai = "0.1.1"版本可以输入 http_async_client参数,所以可以创建httpx的client来使得proxy生效。

SyncHttpxClientWrapper 和AsyncHttpxClientWrapper 直接拿的Openai库的类,分别继承了httpx.client 和 httpx.AsyncClient

代码如下:

# default_limits  设置Httpx 连接池限制
def syncHttpxClient(
        base_url,
        timeout,
        proxies: Dict[str, str],
        transport: Optional[BaseTransport] = None,
        limits: Limits = default_limits
):
    """
    获取同步的Httpx, 
    :param base_url:
    :param timeout:
    :param proxies:
    :param transport:
    :param limits:
    :return:
    """
    return SyncHttpxClientWrapper(
        base_url=base_url,
        # cast to a valid type because mypy doesn't understand our type narrowing
        timeout=cast(Timeout, timeout),
        proxies=proxies,
        transport=transport,
        limits=limits,
        follow_redirects=True,
        verify=False,
        http2=True
    )


def asyncHttpxClient(
        base_url,
        timeout,
        proxies: Dict[str, str],
        transport: Optional[BaseTransport] = None,
        limits: Limits = default_limits
):
    """获取异步的Httpx"""

    return AsyncHttpxClientWrapper(
        base_url=base_url,
        # cast to a valid type because mypy doesn't understand our type narrowing
        timeout=cast(Timeout, timeout),
        proxies=proxies,
        transport=transport,
        limits=limits,
        follow_redirects=True,
        verify=False,
        http2=True
    )
    
# 创建Httpx的客户端
if llm_conf.get('proxy'):
    proxies = {
        "http://": llm_conf.get('proxy'),
        "https://": llm_conf.get('proxy'),
    }
http_client = None
async_http_client = None
if not kwargs.get('streaming', False):
    http_client = syncHttpxClient(llm_conf['api_base'], proxies=proxies, timeout=llm_conf['request_timeout'])
else:
    async_http_client = asyncHttpxClient(llm_conf['api_base'], proxies=proxies, timeout=llm_conf['request_timeout'])
    
llm = ChatOpenAI(http_client=http_client, http_async_client=async_http_client, **llm_conf)

上面4种方法,能够解决Langchain创建ChatOpenAI后openai.APITimeoutError: Request timed out.的问题,最终还是推荐方法4,可灵活制定httpx client。

感谢感谢