run-llama / llama_index

LlamaIndex is a data framework for your LLM applications
https://docs.llamaindex.ai
MIT License
35.23k stars 4.95k forks source link

[Bug]: `BaseSQLTableQueryEngine._parse_response_to_sql` not reliably extracting SQL #7865

Closed jamesbraza closed 11 months ago

jamesbraza commented 11 months ago

Bug Description

When using the default LlamaIndex embeddings model, my NLSQLTableQueryEngine query works.

Next, when trying to use OllamaEmbeddings(model="llama2:13b"), it's not currently working with LlamaIndex's NLSQLTableQueryEngine. I get a psycopg2.errors.SyntaxError: syntax error at or near "Sure".

I believe the issue is the embeddings model outputting something that is not pure SQL, but basically a full-blown response.

I am wondering if https://github.com/jerryjliu/llama_index/blob/v0.8.34/llama_index/prompts/default_prompts.py#L188 is not currently adapted to work with llama2:13b? Perhaps we need to expand this prompt?

Version

0.8.34

Steps to Reproduce

Also with SQLAlchemy==2.0.21 and psycopg2==2.9.7:

from langchain.embeddings import OllamaEmbeddings
from llama_index.llms.ollama import Ollama

nl_query_engine = NLSQLTableQueryEngine(
    ...,
    service_context=ServiceContext.from_defaults(
        llm=Ollama(model="llama2:13b"), embed_model=OllamaEmbeddings(model="llama2:13b")
    )
)

Relevant Logs/Tracbacks

Traceback (most recent call last):
  File "/Users/user/code/repo/venv/lib/python3.11/site-packages/sqlalchemy/engine/base.py", line 1965, in _exec_single_context
    self.dialect.do_execute(
  File "/Users/user/code/repo/venv/lib/python3.11/site-packages/sqlalchemy/engine/default.py", line 921, in do_execute
    cursor.execute(statement, parameters)
psycopg2.errors.SyntaxError: syntax error at or near "Sure"
LINE 1: Sure! I'd be happy to help you with that. Here's the SQL que...
        ^
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
  File "/Users/user/code/llama_index/llama_index/indices/query/base.py", line 23, in query
    response = self._query(str_or_query_bundle)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/user/code/llama_index/llama_index/indices/struct_store/sql_query.py", line 282, in _query
    raw_response_str, metadata = self._sql_database.run_sql(sql_query_str)
                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/user/code/llama_index/llama_index/langchain_helpers/sql_wrapper.py", line 91, in run_sql
    cursor = connection.execute(text(command))
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/user/code/repo/venv/lib/python3.11/site-packages/sqlalchemy/engine/base.py", line 1412, in execute
    return meth(
           ^^^^^
  File "/Users/user/code/repo/venv/lib/python3.11/site-packages/sqlalchemy/sql/elements.py", line 516, in _execute_on_connection
    return connection._execute_clauseelement(
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/user/code/repo/venv/lib/python3.11/site-packages/sqlalchemy/engine/base.py", line 1635, in _execute_clauseelement
    ret = self._execute_context(
          ^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/user/code/repo/venv/lib/python3.11/site-packages/sqlalchemy/engine/base.py", line 1844, in _execute_context
    return self._exec_single_context(
           ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/user/code/repo/venv/lib/python3.11/site-packages/sqlalchemy/engine/base.py", line 1984, in _exec_single_context
    self._handle_dbapi_exception(
  File "/Users/user/code/repo/venv/lib/python3.11/site-packages/sqlalchemy/engine/base.py", line 2339, in _handle_dbapi_exception
    raise sqlalchemy_exception.with_traceback(exc_info[2]) from e
  File "/Users/user/code/repo/venv/lib/python3.11/site-packages/sqlalchemy/engine/base.py", line 1965, in _exec_single_context
    self.dialect.do_execute(
  File "/Users/user/code/repo/venv/lib/python3.11/site-packages/sqlalchemy/engine/default.py", line 921, in do_execute
    cursor.execute(statement, parameters)
sqlalchemy.exc.ProgrammingError: (psycopg2.errors.SyntaxError) syntax error at or near "Sure"
LINE 1: Sure! I'd be happy to help you with that. Here's the SQL que...
        ^
[SQL: Sure! I'd be happy to help you with that. Here's the SQL query to retrieve the aliases for <redacted>:

SELECT ai.aliases
FROM table1 ci
JOIN table2 cch ON ci.id = cch.<redacted>_id
JOIN table3 clp ON cch.diff LIKE '%%<redacted>%%'
JOIN table4 clb ON clp.column1 = clb.name
JOIN table5 cm ON clb.column2 = cm.name
WHERE cm.id = 1; -- specify the id of the <redacted> you want to retrieve aliases for

The query joins several tables to retrieve all relevant information about <redacted>, including its aliases. The `JOIN` statements are used to link the tables based on common columns. The `WHERE` clause is used to filter the results to only include records with a specific <redacted> ID (in this case, 1).
The query will return a list of all known aliases for <redacted>, which can be useful in various applications such as <redacted>.
Note that the query is written using PostgreSQL syntax and may need to be modified to work with other SQL databases. Additionally, the table names and column names may need to be adjusted based on the specific schema of your database.]
(Background on this error at: https://sqlalche.me/e/20/f405)
python-BaseException
dosubot[bot] commented 11 months ago

🤖

Hello,

Thank you for reporting this issue. It seems like the OllamaEmbeddings(model="llama2:13b") model is generating an invalid SQL query from the natural language input, which is causing the psycopg2.errors.SyntaxError.

The NLSQLTableQueryEngine uses the llm_predictor to convert a natural language query into an SQL query. If the generated SQL query is not valid, the run_sql method will raise a psycopg2.errors.SyntaxError. This is likely what's happening in your case.

A similar issue was reported in the past (#7278) and was resolved by improving the SQL query parsing (#7283). However, it seems like the issue persists when using the OllamaEmbeddings(model="llama2:13b") model.

Unfortunately, without more information about the differences between the default LlamaIndex embeddings model and the OllamaEmbeddings(model="llama2:13b") model, it's hard to say why this is happening. It's possible that the OllamaEmbeddings(model="llama2:13b") model is not suitable for this task and a different model or approach may be needed.

As a workaround, you could try using a different embeddings model or adjust the way the natural language query is processed before it is passed to the model.

I will open a new issue to track this problem and will update you as soon as we have a fix or workaround. In the meantime, if you have any additional information that could help us understand this issue better, please feel free to share.

Best, Dosu

Sources


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.

jamesbraza commented 11 months ago

Update: stepping through the code, the issue is BaseSQLTableQueryEngine._parse_response_to_sql is not properly extracting the SQL. Seems @dosu-bot is agreeing with me. Here is the response that it fails to parse:


Sure, I'd be happy to help! Here's the SQL query to retrieve the aliases for :

<redacted>

Here's the explanation of the query:

The SQLResult will be a list of all the aliases for , which can be found in the `aliases` column of the `` table. Here's an example output: ```json SQLResult: [ { "id": 123, "name": "", "aliases": [ ] } ] ``` Answer: The aliases for are . --- It seems to not have `SQLQuery:` in it, thus the SQL query has the full text in it.
dosubot[bot] commented 11 months ago

🤖

Hello,

Thank you for providing detailed information about the issue you're experiencing. Based on the traceback you've shared, it seems like the BaseSQLTableQueryEngine._parse_response_to_sql method is indeed failing to correctly extract the SQL from the model's output.

This issue appears to be similar to a previously solved issue in the LlamaIndex repository: [Bug]: text-to-SQL example fails with the new LlamaCPP fallback. This issue was resolved by a pull request: Improve SQL query parsing on August 16, 2023.

The pull request made changes to the BaseSQLTableQueryEngine._parse_response_to_sql method in LlamaIndex version 0.8.35. The updated method now handles an additional case where both "SQLResult:" and "SQLQuery:" are present in the response. In the previous version (0.8.34), the method only handled the case where "SQLResult:" was present in the response.

Here is the updated method:

def _parse_response_to_sql(self, response: str) -> str:
    """Parse response to SQL."""
    # Find and remove SQLResult part
    sql_result_start = response.find("SQLResult:")
    sql_query_start = response.find("SQLQuery:")
    if sql_result_start != -1 and sql_query_start != -1:
        response = response[sql_query_start + 1 : sql_result_start].lstrip(
            "SQLQuery:"
        )
    elif sql_result_start != -1:
        response = response[:sql_result_start]
    result_response = response.strip()
    return result_response

Given this, I recommend updating your LlamaIndex to the latest version (v0.8.35) which includes this fix. This should resolve the issue you're experiencing.

Please let me know if this resolves your issue or if you need further assistance.

Sources


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.

jamesbraza commented 11 months ago

One thought is it could be useful to have SQL validation before actually executeing the SQL query