langchain-ai / langchain

šŸ¦œšŸ”— Build context-aware reasoning applications
https://python.langchain.com
MIT License
92.05k stars 14.65k forks source link

APIChain InvalidSchema: No connection adapters were found #19512

Open duotangx opened 5 months ago

duotangx commented 5 months ago

Checked other resources

Example Code

pip install langchain langchain-anthropic

api_docs = """ Using the API

Other Available API Endpoints Certain API endpoints without a specific "get" function are also accessible:

Request Rate Limiting API usage is subject to request limits per hour as follows:

from langchain.chains import APIChain from langchain_anthropic import ChatAnthropic

llm = ChatAnthropic( anthropic_api_key=, model="claude-3-haiku-20240307", temperature=0 )

chain = APIChain.from_llm_and_api_docs( llm, api_docs, verbose=True, limit_to_domains=None )

chain.run( "Get Microsoft's income statement." )

Error Message and Stack Trace (if applicable)

Entering new APIChain chain... To get Microsoft's income statement, the appropriate API endpoint is:

/api/income-statement/MSFT/

This URL will fetch the annual income statement for Microsoft (ticker symbol MSFT) using the get_income_statement() function.

The full API URL would be:

https://discountingcashflows.com/api/income-statement/MSFT/

This URL is the most concise way to retrieve Microsoft's income statement data, as it directly targets the relevant endpoint without any unnecessary parameters.

InvalidSchema Traceback (most recent call last) in <cell line: 17>() 15 ) 16 ---> 17 chain.run( 18 "Get Microsoft's income statement." 19 )

13 frames /usr/local/lib/python3.10/dist-packages/langchain_core/_api/deprecation.py in warning_emitting_wrapper(*args, kwargs) 143 warned = True 144 emit_warning() --> 145 return wrapped(*args, *kwargs) 146 147 async def awarning_emitting_wrapper(args: Any, kwargs: Any) -> Any:

/usr/local/lib/python3.10/dist-packages/langchain/chains/base.py in run(self, callbacks, tags, metadata, *args, **kwargs) 543 if len(args) != 1: 544 raise ValueError("run supports only one positional argument.") --> 545 return self(args[0], callbacks=callbacks, tags=tags, metadata=metadata)[ 546 _output_key 547 ]

/usr/local/lib/python3.10/dist-packages/langchain_core/_api/deprecation.py in warning_emitting_wrapper(*args, kwargs) 143 warned = True 144 emit_warning() --> 145 return wrapped(*args, *kwargs) 146 147 async def awarning_emitting_wrapper(args: Any, kwargs: Any) -> Any:

/usr/local/lib/python3.10/dist-packages/langchain/chains/base.py in call(self, inputs, return_only_outputs, callbacks, tags, metadata, run_name, include_run_info) 376 } 377 --> 378 return self.invoke( 379 inputs, 380 cast(RunnableConfig, {k: v for k, v in config.items() if v is not None}),

/usr/local/lib/python3.10/dist-packages/langchain/chains/base.py in invoke(self, input, config, **kwargs) 161 except BaseException as e: 162 run_manager.on_chain_error(e) --> 163 raise e 164 run_manager.on_chain_end(outputs) 165

/usr/local/lib/python3.10/dist-packages/langchain/chains/base.py in invoke(self, input, config, **kwargs) 151 self._validate_inputs(inputs) 152 outputs = ( --> 153 self._call(inputs, run_manager=run_manager) 154 if new_arg_supported 155 else self._call(inputs)

/usr/local/lib/python3.10/dist-packages/langchain/chains/api/base.py in _call(self, inputs, run_manager) 162 f"{api_url} is not in the allowed domains: {self.limit_to_domains}" 163 ) --> 164 api_response = self.requests_wrapper.get(api_url) 165 _run_manager.on_text( 166 str(api_response), color="yellow", end="\n", verbose=self.verbose

/usr/local/lib/python3.10/dist-packages/langchain_community/utilities/requests.py in get(self, url, kwargs) 150 def get(self, url: str, kwargs: Any) -> Union[str, Dict[str, Any]]: 151 """GET the URL and return the text.""" --> 152 return self._get_resp_content(self.requests.get(url, **kwargs)) 153 154 def post(

/usr/local/lib/python3.10/dist-packages/langchain_community/utilities/requests.py in get(self, url, kwargs) 28 def get(self, url: str, kwargs: Any) -> requests.Response: 29 """GET the URL and return the text.""" ---> 30 return requests.get(url, headers=self.headers, auth=self.auth, kwargs) 31 32 def post(self, url: str, data: Dict[str, Any], kwargs: Any) -> requests.Response:

/usr/local/lib/python3.10/dist-packages/requests/api.py in get(url, params, kwargs) 71 """ 72 ---> 73 return request("get", url, params=params, kwargs) 74 75

/usr/local/lib/python3.10/dist-packages/requests/api.py in request(method, url, kwargs) 57 # cases, and look like a memory leak in others. 58 with sessions.Session() as session: ---> 59 return session.request(method=method, url=url, kwargs) 60 61

/usr/local/lib/python3.10/dist-packages/requests/sessions.py in request(self, method, url, params, data, headers, cookies, files, auth, timeout, allow_redirects, proxies, hooks, stream, verify, cert, json) 587 } 588 send_kwargs.update(settings) --> 589 resp = self.send(prep, **send_kwargs) 590 591 return resp

/usr/local/lib/python3.10/dist-packages/requests/sessions.py in send(self, request, **kwargs) 695 696 # Get the appropriate adapter to use --> 697 adapter = self.get_adapter(url=request.url) 698 699 # Start time (approximately) of the request

/usr/local/lib/python3.10/dist-packages/requests/sessions.py in get_adapter(self, url) 792 793 # Nothing matches :-/ --> 794 raise InvalidSchema(f"No connection adapters were found for {url!r}") 795 796 def close(self):

InvalidSchema: No connection adapters were found for "To get Microsoft's income statement, the appropriate API endpoint is:\n\n/api/income-statement/MSFT/\n\nThis URL will fetch the annual income statement for Microsoft (ticker symbol MSFT) using the get_income_statement() function.\n\nThe full API URL would be:\n\nhttps://discountingcashflows.com/api/income-statement/MSFT/\n\nThis URL is the most concise way to retrieve Microsoft's income statement data, as it directly targets the relevant endpoint without any unnecessary parameters."

Description

Trying to request API data from discountingcashflows.com free API (no key required). When I set limit_to_domains=None I get the above error and when I set limit_to_domains=["https://discountingcashflows.com/"] I get a ValueError: {api_url} is not in the allowed domains.

System Info

langchain==0.1.13 langchain-anthropic==0.1.4 langchain-community==0.0.29 langchain-core==0.1.33 langchain-text-splitters==0.0.1 Linux-6.1.58+-x86_64-with-glibc2.35 Python 3.10.12

@dosu-bot

duotangx commented 5 months ago

@dosu-bot any thoughts?

dosubot[bot] commented 5 months ago

Hey @duotangx, great to see you diving into another challenge with LangChain! Hope you're doing well since our last adventure. šŸ˜Š

Based on the information you've provided, it seems like the issue might be related to the api_docs parameter or the limit_to_domains parameter in the APIChain.from_llm_and_api_docs method.

The InvalidSchema error typically occurs when the requests library in Python is used to make a request to a URL with a schema (protocol) that it does not support. The requests library natively supports http:// and https:// schemas. If you're encountering this error, it's likely because the URL you're trying to access does not use one of these supported schemas or there's a typo in the URL schema. Please ensure that the URL you're using starts with either http:// or https://.

Regarding the ValueError when setting limit_to_domains to the specific domain, the limit_to_domains parameter in the APIChain.from_llm_and_api_docs method is an optional sequence of strings (Optional[Sequence[str]]). Each domain string should include the scheme (e.g., https://) and the domain name. An empty tuple (the default value) means no domains are allowed, and setting the parameter to None would allow all domains, although this is not recommended for security reasons. Please ensure that any domain limitations or filtering logic you're applying is correctly implemented and that any URL or domain you're specifying matches the expected format and types required by your code or any libraries you're using.

The api_docs parameter in the APIChain.from_llm_and_api_docs method is expected to be a string. This parameter represents the documentation of the API that the chain will interact with. It is used within the chain to inform the language model about the API's capabilities, endpoints, parameters, and any other relevant information that can help in generating accurate API calls and interpreting the responses.

The api_docs parameter interacts with the limit_to_domains parameter in the sense that the API calls generated based on the api_docs are constrained by the domains specified in limit_to_domains. If a generated API URL does not match any of the domains in limit_to_domains, the chain will raise a ValueError, indicating that the URL is not in the allowed domains.

If you're still facing the issue, could you please provide more details about the api_docs you're using and the exact limit_to_domains value you're setting? This will help in identifying the root cause of the issue.

Sources

#### About Dosu This response is meant to be useful and save you time. It is **not meant to be a precise solution**, but rather a starting point for your own research. Help me be more useful! Please leave a šŸ‘ if this is helpful and šŸ‘Ž if it is irrelevant. If you want to continue the conversation, start your reply with @dosu-bot.
duotangx commented 5 months ago

@dosu-bot

api_docs = """ Using the API

apiUrl=https://discountingcashflows.com No API key is required. To fetch annual income statements, use get_income_statement() at /api/income-statement/AAPL/. For quarterly income statements, get_income_statement_quarterly() is available at /api/income-statement/quarterly/AAPL/. Use get_income_statement_ltm() for income statements over the last twelve months (LTM) at /api/income-statement/ltm/AAPL/. Annual balance sheet statements can be retrieved with get_balance_sheet_statement() via /api/balance-sheet-statement/AAPL/. For quarterly balance sheet data, there's get_balance_sheet_statement_quarterly() at /api/balance-sheet-statement/quarterly/AAPL/. Annual cash flow statements are accessible through get_cash_flow_statement() at /api/cash-flow-statement/AAPL/. get_cash_flow_statement_quarterly() at /api/cash-flow-statement/quarterly/AAPL/ fetches quarterly cash flow statements. LTM cash flow data is obtainable with get_cash_flow_statement_ltm() at /api/cash-flow-statement/ltm/AAPL/. Stock market quotes can be accessed using get_quote() at /api/quote/AAPL/. Company profiles are available via get_profile() at /api/profile/AAPL/. For the latest treasury rates, use get_treasury() at /api/treasury/. Daily treasury rates (full history) can be fetched with get_treasury_daily() at /api/treasury/daily/. get_treasury_monthly() at /api/treasury/monthly/ provides monthly treasury rates (full history). Annual treasury rates (full history) are accessible through get_treasury_annual() at /api/treasury/annual/. Annual financial ratios can be retrieved using get_ratios() at /api/ratios/AAPL/. For quarterly financial ratios, there's get_ratios_quarterly() at /api/ratios/quarterly/AAPL/. LTM financial ratios are available with get_ratios_ltm() at /api/ratios/ltm/AAPL/. To access annually adjusted dividends, use get_dividends_annual() at /api/dividends/AAPL/. Quarterly adjusted dividends can be fetched with get_dividends_quarterly() at /api/dividends/quarterly/AAPL/. Dividends as reported are available through get_dividends_reported() at /api/dividends/reported/AAPL/. For a full history of daily market prices, use get_prices_daily() at /api/prices/daily/AAPL/. Annual market share prices (full history) are accessible via get_prices_annual() at /api/prices/annual/AAPL/. Annual CPI data can be retrieved using get_cpi_annual() at /api/economic/annual/CPI/. FX market prices for all currencies are available through get_fx() at /api/fx/. Equity risk premium for all countries can be accessed with get_risk_premium() at /api/risk-premium/. Other Available API Endpoints Certain API endpoints without a specific "get" function are also accessible:

Revenue Breakdown (requires subscription) through /api/revenue-analysis//// with ticker options like AAPL, MSFT, etc., type as geographic or product, and period as annual or quarter. Transcripts are available at /api/transcript//// with ticker options and specific quarter/year. SEC Filings can be accessed via /api/sec-filings//. Institutional Holders information is retrievable through /api/institutional-holders///, with date indicating the filing report date. Stock News is available at /api/news///, with an optional limit parameter (defaults to 10). Request Rate Limiting API usage is subject to request limits per hour as follows:

Unauthenticated users are limited to 500 requests. Authenticated users have a 1,000 request limit. Essential users can make 15,000 requests. Ultimate users enjoy unlimited requests. Exceeding these limits will result in an HTTP 403 Forbidden Response for further requests. """

limit_to_domains=["https://discountingcashflows.com"]

I have a sense this is being caused by the APIChain.from_llm_and_api_docs not properly parsing the response to extract the correct API URL.

dosubot[bot] commented 5 months ago

Based on the information you've provided, it seems like the issue might be related to how the limit_to_domains parameter is being used. The limit_to_domains parameter is used to restrict the domains that the APIChain instance can make requests to. If the domain of the API you're trying to access is not included in this list, it could lead to the errors you're experiencing.

In your case, you're trying to access the API at https://discountingcashflows.com, so you should ensure that this domain is included in the limit_to_domains list. However, it's important to note that the limit_to_domains parameter expects a list of domain names, not URLs. This means that you should include discountingcashflows.com in the list, not https://discountingcashflows.com.

Here's how you can modify your code:

limit_to_domains=["discountingcashflows.com"]

Regarding the InvalidSchema error, it's likely that the requests library is unable to find a suitable connection adapter for the URL you're trying to access. This could be due to a number of reasons, such as an incorrect URL scheme (e.g., http:// vs https://), a typo in the URL, or a problem with your network connection.

In your case, it seems like the URL scheme might be the issue. The requests library expects URLs to start with http:// or https://, but the URL in your api_docs string starts with apiUrl=. You should modify your api_docs string to use the correct URL scheme:

api_docs = """
Using the API

apiUrl=https://discountingcashflows.com
...
"""

I hope this helps! If you're still encountering issues, please provide more details about the error messages you're seeing, and I'll be happy to assist you further.

Sources

#### About Dosu This response is meant to be useful and save you time. It is **not meant to be a precise solution**, but rather a starting point for your own research. Help me be more useful! Please leave a šŸ‘ if this is helpful and šŸ‘Ž if it is irrelevant. If you want to continue the conversation, start your reply with @dosu-bot.
duotangx commented 5 months ago

@dosu-bot is there a better way to format/structure the api_docs to make it easier for 'from_llm_and_api_docs' to parse?

dosubot[bot] commented 5 months ago

Based on the information you've provided, it seems like the api_docs string you're using might not be structured in a way that the APIChain.from_llm_and_api_docs method can parse effectively. The method expects a string that contains documentation or information necessary for making API calls and processing their responses.

To improve the parsing of the api_docs string, you should structure it in a way that clearly and concisely documents the API endpoints, parameters, and expected responses. Here's a simplified example of how you might structure part of the api_docs string in JSON format for better parsing:

[
  {
    "endpoint": "https://discountingcashflows.com/api/v1/cashflows",
    "method": "GET",
    "description": "Retrieves a list of cash flow entries.",
    "parameters": [
      {
        "name": "startDate",
        "type": "string",
        "required": false,
        "description": "The start date for filtering cash flows."
      },
      {
        "name": "endDate",
        "type": "string",
        "required": false,
        "description": "The end date for filtering cash flows."
      }
    ],
    "responses": [
      {
        "status": 200,
        "body": {
          "cashFlows": [
            {
              "date": "2023-01-01",
              "amount": 1000
            }
          ]
        }
      }
    ],
    "examples": {
      "request": "/api/v1/cashflows?startDate=2023-01-01&endDate=2023-12-31",
      "response": {
        "status": 200,
        "body": {
          "cashFlows": [
            {
              "date": "2023-01-01",
              "amount": 1000
            }
          ]
        }
      }
    }
  }
]

This example uses JSON to structure the documentation for a hypothetical endpoint. It includes the endpoint's URL, the HTTP method, a description, parameters with details, expected responses, and examples of requests and responses. Adjust the structure and content according to the specifics of the API you are documenting.

Please note that this is a general suggestion and the actual structure of the api_docs string might need to be adjusted based on the specific requirements of the APIChain.from_llm_and_api_docs method and the API you're interacting with.

For more details, you can refer to the source code of the APIChain.from_llm_and_api_docs method in the LangChain library here.

Sources

#### About Dosu This response is meant to be useful and save you time. It is **not meant to be a precise solution**, but rather a starting point for your own research. Help me be more useful! Please leave a šŸ‘ if this is helpful and šŸ‘Ž if it is irrelevant. If you want to continue the conversation, start your reply with @dosu-bot.
ronidas39 commented 3 months ago

my code: `from langchain_openai import ChatOpenAI from langchain.chains import APIChain import json

llm=ChatOpenAI(model="gpt-4o")

api_docs={ "endpoint": "https://api.coinap.io/v2/assets/{name}", "method": "GET", "description": "Retrieves information of a crypto token.", "parameters": [ { "name": "name", "type": "string", "required": True, "description": "The name of the crypto token in lowercase." } ] } chain=APIChain.from_llm_and_api_docs( llm, api_docs=json.dumps(api_docs), verbose=True, limit_to_domains=["https://api.coincap.io/v2/assets/"] ) response=chain.invoke("give information on bitcoin")`

error getting:

https://api.coinap.io/v2/assets/bitcoin is not in the allowed domains: ['https://api.coincap.io/v2/assets/']

please help I have followed your suggestion

ronidas39 commented 3 months ago

i have fixed it if you are also having same issue try to use from langchain_openai import OpenAI dont use from langchain_openai import ChatOpenAI ChatOpenAI has some problem with request module . Langchai_openai team should fix it