feat: add checkpoint aput method and test#269
feat: add checkpoint aput method and test#269averikitsch merged 13 commits intogoogleapis:langgraph-basefrom
Conversation
|
/gcbrun |
|
/gcbrun |
| @@ -754,14 +753,14 @@ async def _ainit_checkpoint_table( | |||
| self, | |||
There was a problem hiding this comment.
Can we make sure this is the exact same as the AlloyDB library? For example the arguments are in a different order https://github.com/googleapis/langchain-google-alloydb-pg-python/blob/4f24eea67ff0aeec547463f3a77a07f6da209718/src/langchain_google_alloydb_pg/engine.py#L770
and missing quotes around the table name https://github.com/googleapis/langchain-google-alloydb-pg-python/blob/4f24eea67ff0aeec547463f3a77a07f6da209718/src/langchain_google_alloydb_pg/engine.py#L783. please make sure there are no other difference beyond naming differences
There was a problem hiding this comment.
Yes, it is the same implementation of the method but, you are right. There was a mismatch in the arguments. It's fixed now.
| self.schema_name = schema_name | ||
|
|
||
| @classmethod | ||
| async def create( |
There was a problem hiding this comment.
Please make sure the argument order matches AlloyDB
There was a problem hiding this comment.
idem, there was a mismatching. It's addressed.
tests/test_async_checkpoint.py
Outdated
| assert dict(next_config) == test_config | ||
|
|
||
| # Verify if the checkpoint is stored correctly in the database | ||
| results = await afetch(async_engine, f"SELECT * FROM {table_name}") |
There was a problem hiding this comment.
Table names need to be in quotes
There was a problem hiding this comment.
I have added too all table names the quotes.
tests/test_async_checkpoint.py
Outdated
| yield async_engine | ||
| # use default table for AsyncPostgresSaver. | ||
| await aexecute(async_engine, f'DROP TABLE IF EXISTS "{table_name}"') | ||
| await aexecute(async_engine, f'DROP TABLE IF EXISTS"{table_name_writes}"') |
tests/test_async_checkpoint.py
Outdated
|
|
||
| project_id = os.environ["PROJECT_ID"] | ||
| region = os.environ["REGION"] | ||
| cluster_id = os.environ["CLUSTER_ID"] |
tests/test_async_checkpoint.py
Outdated
| async_engine = await PostgresEngine.afrom_instance( | ||
| project_id=project_id, | ||
| region=region, | ||
| cluster=cluster_id, |
tests/test_async_checkpoint.py
Outdated
| return result_fetch | ||
|
|
||
|
|
||
| @pytest_asyncio.fixture ##(scope="module") |
There was a problem hiding this comment.
Removed. There was another comment just like that and, I have also removed it.
|
/gcbrun |
|
|
/gcbrun |
|
/gcbrun |
| ) | ||
|
|
||
| return metadata.tables[f"{schema_name}.{table_name}"] | ||
| return metadata.tables[f'"{schema_name}"."{table_name}"'] |
tests/test_async_checkpoint.py
Outdated
| await aexecute(async_engine, f'DROP TABLE IF EXISTS "{table_name}"') | ||
| await aexecute(async_engine, f'DROP TABLE IF EXISTS "{table_name_writes}"') | ||
| await async_engine.close() | ||
| await async_engine._connector.close() |
There was a problem hiding this comment.
I have a doubt here, do I need to use await "async_engine.close_async()" instead of "await async_engine.close()"?
There was a problem hiding this comment.
The for the connector use close_async() for the engine continue to use close(). https://github.com/GoogleCloudPlatform/cloud-sql-python-connector?tab=readme-ov-file#async-context-manager
There was a problem hiding this comment.
I changed this and I added the "async_engine.close_asyn()" just as you suggested.
|
/gcbrun |
tests/test_engine.py
Outdated
|
|
||
| # Verify that the query is executed on the custom table. | ||
| stmt = f"SELECT column_name, data_type FROM information_schema.columns WHERE table_name = '{custom_table_name}';" | ||
| stmt = f'SELECT column_name, data_type FROM information_schema.columns WHERE table_name = "{table_name}";' |
There was a problem hiding this comment.
These values shouldn't be in double quotes only single quotes
There was a problem hiding this comment.
I've removes double quotes here.
averikitsch
left a comment
There was a problem hiding this comment.
____________________________ test_checkpoint_alist _____________________________
async_engine = <langchain_google_cloud_sql_pg.engine.PostgresEngine object at 0x7f8ed8342310>
checkpointer = <langchain_google_cloud_sql_pg.async_checkpoint.AsyncPostgresSaver object at 0x7f8ed83ffbd0>
test_data = {'checkpoints': [{'channel_values': {'my_key': 'meow', 'node': 'node'}, 'channel_versions': {'start': 2, 'my_key':...rce': 'input', 'step': 2, 'writes': {}}, {'parents': None, 'source': 'loop', 'step': 1, 'writes': {'foo': 'bar'}}, {}]}
@pytest.mark.asyncio
async def test_checkpoint_alist(
async_engine: PostgresEngine,
checkpointer: AsyncPostgresSaver,
test_data: dict[str, Any],
) -> None:
configs = test_data["configs"]
checkpoints = test_data["checkpoints"]
metadata = test_data["metadata"]
await checkpointer.aput(configs[1], checkpoints[1], metadata[0], {})
await checkpointer.aput(configs[2], checkpoints[2], metadata[1], {})
await checkpointer.aput(configs[3], checkpoints[3], metadata[2], {})
# call method / assertions
query_1 = {"source": "input"} # search by 1 key
query_2 = {
"step": 1,
"writes": {"foo": "bar"},
} # search by multiple keys
query_3: dict[str, Any] = {} # search by no keys, return all checkpoints
query_4 = {"source": "update", "step": 1} # no match
search_results_1 = [c async for c in checkpointer.alist(None, filter=query_1)]
tests/test_async_checkpoint.py:242:
tests/test_async_checkpoint.py:242: in
search_results_1 = [c async for c in checkpointer.alist(None, filter=query_1)]
/builder/home/.local/lib/python3.11/site-packages/langchain_google_cloud_sql_pg/async_checkpoint.py:444: in alist
result = await conn.stream(text(query), args)
/builder/home/.local/lib/python3.11/site-packages/sqlalchemy/ext/asyncio/base.py:151: in start
start_value = await util.anext_(self.gen)
/builder/home/.local/lib/python3.11/site-packages/sqlalchemy/ext/asyncio/engine.py:582: in stream
result = await greenlet_spawn(
/builder/home/.local/lib/python3.11/site-packages/sqlalchemy/util/_concurrency_py3k.py:190: in greenlet_spawn
result = context.switch(*args, **kwargs)
/builder/home/.local/lib/python3.11/site-packages/sqlalchemy/engine/base.py:1412: in execute
distilled_parameters = _distill_params_20(parameters)
lib/sqlalchemy/cyextension/util.pyx:32: in sqlalchemy.cyextension.util._distill_params_20
???
???
E sqlalchemy.exc.ArgumentError: List argument must consist only of tuples or dictionaries
lib/sqlalchemy/cyextension/util.pyx:23: ArgumentError
|
/gcbrun |
tests/test_engine.py
Outdated
|
|
||
| # Verify that the query is executed on the custom table. | ||
| stmt = f"SELECT column_name, data_type FROM information_schema.columns WHERE table_name = '{custom_table_name}';" | ||
| stmt = f'SELECT column_name, data_type FROM information_schema.columns WHERE table_name = "{table_name_writes}";' |
There was a problem hiding this comment.
please update to use single quotes around table name
There was a problem hiding this comment.
Ok, I've replaced the single quotes for double quotes instead.
tests/test_engine.py
Outdated
| table_name = f"checkpoint{uuid.uuid4()}" | ||
| table_name_writes = f"{table_name}_writes" | ||
| await engine.ainit_checkpoint_table(table_name=table_name) | ||
| stmt = f'SELECT column_name, data_type FROM information_schema.columns WHERE table_name = "{table_name_writes}";' |
There was a problem hiding this comment.
please update to use single quotes around table name
tests/test_engine.py
Outdated
| table_name = f"checkpoint{uuid.uuid4()}" | ||
| table_name_writes = f"{table_name}_writes" | ||
| engine.init_checkpoint_table(table_name=table_name) | ||
| stmt = f'SELECT column_name, data_type FROM information_schema.columns WHERE table_name = "{table_name}";' |
There was a problem hiding this comment.
please update to use single quotes around table name
There was a problem hiding this comment.
This was also addressed. Thank you for all the comments.
|
/gcbrun |
Thank you for opening a Pull Request! Before submitting your PR, there are a few things you can do to make sure it goes smoothly:
Fixes #<issue_number_goes_here> 🦕