1.? 遇到問題
? ? ? ? Python 基于 Langchain 對接 Claude 3.7 大模型接口進行問答時,由于國內不在Claude支持的國家和地區,所以一直調不通,錯誤? ? anthropic.PermissionDeniedError: Error code: 403 - {'error': {'type': 'forbidden', 'message': 'Request not allowed'}}?
? ? ? ? ?詳細堆棧如下:
ERROR:root:Error code: 403 - {'error': {'type': 'forbidden', 'message': 'Request not allowed'}}
Traceback (most recent call last):File "E:\Idea_workspace\Temp_view\test-python\test\llm\test_claude37.py", line 58, in <module>for chunk in llm.stream(messages):File "D:\Program Files\Python311\Lib\site-packages\langchain_core\language_models\chat_models.py", line 494, in streamfor chunk in self._stream(input_messages, stop=stop, **kwargs):File "D:\Program Files\Python311\Lib\site-packages\langchain_anthropic\chat_models.py", line 995, in _streamstream = self._client.messages.create(**payload)^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^File "D:\Program Files\Python311\Lib\site-packages\anthropic\_utils\_utils.py", line 275, in wrapperreturn func(*args, **kwargs)^^^^^^^^^^^^^^^^^^^^^File "D:\Program Files\Python311\Lib\site-packages\anthropic\resources\messages\messages.py", line 953, in createreturn self._post(^^^^^^^^^^^File "D:\Program Files\Python311\Lib\site-packages\anthropic\_base_client.py", line 1336, in postreturn cast(ResponseT, self.request(cast_to, opts, stream=stream, stream_cls=stream_cls))^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^File "D:\Program Files\Python311\Lib\site-packages\anthropic\_base_client.py", line 1013, in requestreturn self._request(^^^^^^^^^^^^^^File "D:\Program Files\Python311\Lib\site-packages\anthropic\_base_client.py", line 1117, in _requestraise self._make_status_error_from_response(err.response) from None
anthropic.PermissionDeniedError: Error code: 403 - {'error': {'type': 'forbidden', 'message': 'Request not allowed'}}
2.? 解決問題
? ? ? ? 調用Claude 3.7 進行問答時,通常會采用流式輸出?或?異步調用,這兩種不同的調用 解決403有點差異。 原理都是通過設置代理客戶端(如下圖,配上ip:端口就能訪問外網的那種)、轉發請求。
代碼里有注釋,所以就不過多說明了,有問題可留言溝通。
from langchain_anthropic import ChatAnthropic
from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import ChatPromptTemplate
import httpx
import os
import dotenv
import logging
import asynciodotenv.load_dotenv()
INPUT_PLACEHOLDER = '{input}'
# 讀取環境變量值,或直接改為你的代理地址,比如:proxy_url = http://192.168.1.101:10082
proxy_url = os.getenv("CLAUDE_PROXY")if proxy_url:#新建異步httpx客戶端async_transport = httpx.AsyncHTTPTransport(proxy=httpx.Proxy(url=proxy_url))async_http_client = httpx.AsyncClient(transport=async_transport)#新建httpx客戶端transport = httpx.HTTPTransport(proxy=httpx.Proxy(url=proxy_url))http_client = httpx.Client(transport=transport)
else:async_http_client = Nonehttp_client = None
llm = ChatAnthropic(thinking={"type": "enabled","budget_tokens": 4096},model="claude-3-7-sonnet-20250219",max_tokens=8192
)
if http_client:# 設置同步httpx客戶端llm._client._client = http_client
if async_http_client:# 設置異步httpx客戶端llm._async_client._client = async_http_client
system_prompt = """
你是一個人工智能助手,你可以回答用戶的問題。"""
prompt = ChatPromptTemplate.from_messages([("system", system_prompt),("user", INPUT_PLACEHOLDER)
])
output_parser = StrOutputParser()
messages = prompt.format(input="你是誰?中文回答")# Stream 流式輸出 同步調用
try:for chunk in llm.stream(messages):print("" + chunk.text(), end="")
except Exception as e:logging.exception(e)#Async 異步調用
async def main():result = await llm.ainvoke(messages)print("\n\n異步:" + result.text())asyncio.run(main())
效果如圖
?3. 總結
? ? ? ? 其實Claude 3.7 403問題一直困擾研發團隊,不得不 花錢租用Aws服務器在上面做調試&開發,成本又高又不方便(尤其是多人使用)。
? ? ? ? 后來找時間看了些?langchain_anthropic和httpx的源碼 該問題才算完美解決。