Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(memory-store): fix vector search function #1046

Merged
merged 3 commits into from
Jan 13, 2025
Merged

Conversation

Ahmad-mtos
Copy link
Contributor

@Ahmad-mtos Ahmad-mtos commented Jan 13, 2025

PR Type

Bug fix, Enhancement


Description

  • Adjusted confidence parameter range and default value.

  • Refined distance calculation logic for vector search.

  • Updated SQL query to improve search result ordering.

  • Enhanced input validation for confidence parameter.


Changes walkthrough 📝

Relevant files
Enhancement
000022_vector_search.up.sql
Refined vector search SQL function and parameters               

memory-store/migrations/000022_vector_search.up.sql

  • Changed confidence default value from 0.5 to 0.0.
  • Expanded confidence range to include negative values.
  • Updated distance calculation to simplify formula.
  • Adjusted SQL query to refine search result ordering.
  • +8/-8     

    💡 PR-Agent usage: Comment /help "your question" on any pull request to receive relevant information


    Important

    Refines vector search by adjusting confidence parameter range, improving distance calculation, and updating SQL query for better result ordering.

    • Behavior:
      • Adjusted confidence parameter range to -1.0 to 1.0 and default to 0.0 in Docs.py and models.tsp.
      • Refined distance calculation logic in 000022_vector_search.up.sql to simplify formula and improve search result ordering.
    • SQL:
      • Updated SQL query in 000022_vector_search.up.sql to order results by ascending distance.
      • Changed confidence validation to allow negative values in 000022_vector_search.up.sql.
    • Validation:
      • Enhanced input validation for confidence parameter in Docs.py and models.tsp.

    This description was created by Ellipsis for c9e9e87. It will automatically update as commits are pushed.

    Copy link
    Contributor

    PR Reviewer Guide 🔍

    Here are some key observations to aid the review process:

    ⏱️ Estimated effort to review: 3 🔵🔵🔵⚪⚪
    🧪 No relevant tests
    🔒 No security concerns identified
    ⚡ Recommended focus areas for review

    Breaking Change

    The confidence parameter range has been expanded to include negative values (-1 to 1) and its default value changed from 0.5 to 0.0. This could affect existing queries that rely on the previous behavior.

    confidence float DEFAULT 0.0,
    Logic Change

    The distance calculation and ordering logic has been significantly modified - removing normalization and reversing sort order. Verify this maintains expected search quality and ranking.

            (d.embedding <=> $1) as distance,
            d.embedding,
            d.metadata,
            doc_owners.owner_type,
            doc_owners.owner_id
        FROM docs_embeddings d
        LEFT JOIN doc_owners ON d.doc_id = doc_owners.doc_id
        WHERE d.developer_id = $7
        AND (d.embedding <=> $1) <= $2
        %s
        %s
        ORDER BY (d.embedding <=> $1)
        LIMIT ($3 * 4)  -- Get more candidates than needed
    )
    SELECT DISTINCT ON (doc_id) *
    FROM ranked_docs
    ORDER BY doc_id, distance

    Copy link
    Contributor

    @ellipsis-dev ellipsis-dev bot left a comment

    Choose a reason for hiding this comment

    The reason will be displayed to describe this comment to others. Learn more.

    👍 Looks good to me! Reviewed everything up to 3c9e5ee in 19 seconds

    More details
    • Looked at 61 lines of code in 1 files
    • Skipped 0 files when reviewing.
    • Skipped posting 3 drafted comments based on config settings.
    1. memory-store/migrations/000022_vector_search.up.sql:22
    • Draft comment:
      The change in confidence range from 0 to 1 to -1 to 1 is not explained. Ensure this change is intentional and does not affect the logic adversely.
    • Reason this comment was not posted:
      Confidence changes required: 50%
      The change in confidence range from 0 to 1 to -1 to 1 is not explained in the PR description. This change might affect the logic of the function, especially how the search threshold is calculated and used.
    2. memory-store/migrations/000022_vector_search.up.sql:32
    • Draft comment:
      The calculation of search_threshold as 1.0 - confidence is a significant change. Verify this aligns with the intended functionality.
    • Reason this comment was not posted:
      Confidence changes required: 50%
      The calculation of search_threshold as 1.0 - confidence is a significant change from the previous logic. This should be verified to ensure it aligns with the intended functionality.
    3. memory-store/migrations/000022_vector_search.up.sql:72
    • Draft comment:
      The ordering of results by distance in ascending order is a change from the previous descending order. Verify this aligns with the intended functionality.
    • Reason this comment was not posted:
      Confidence changes required: 50%
      The ordering of results by distance in ascending order is a change from the previous descending order. This should be verified to ensure it aligns with the intended functionality.

    Workflow ID: wflow_Nu96N69xNi9NY2nF


    You can customize Ellipsis with 👍 / 👎 feedback, review rules, user-specific overrides, quiet mode, and more.

    Copy link
    Contributor

    qodo-merge-pro-for-open-source bot commented Jan 13, 2025

    PR Code Suggestions ✨

    Explore these optional code suggestions:

    CategorySuggestion                                                                                                                                    Score
    General
    ✅ Optimize query performance by eliminating redundant distance calculations and ensuring proper result ordering based on vector similarity
    Suggestion Impact:The commit addressed the ordering aspect by explicitly adding ASC to ORDER BY clauses, though it did not implement the suggested CTE approach

    code diff:

    -            ORDER BY (d.embedding <=> $1)
    +            ORDER BY (d.embedding <=> $1) ASC
                 LIMIT ($3 * 4)  -- Get more candidates than needed
             )
             SELECT DISTINCT ON (doc_id) *
             FROM ranked_docs
    -        ORDER BY doc_id, distance
    +        ORDER BY doc_id, distance ASC

    The distance calculation in the ORDER BY clause should be consistent with the WHERE
    clause to ensure optimal query performance. Cache the calculated distance in a CTE
    or derived table to avoid computing it multiple times.

    memory-store/migrations/000022_vector_search.up.sql [70-73]

    -SELECT DISTINCT ON (doc_id) *
    -FROM ranked_docs
    -ORDER BY doc_id, distance
    +WITH final_docs AS (
    +  SELECT DISTINCT ON (doc_id) *
    +  FROM ranked_docs
    +)
    +SELECT *
    +FROM final_docs
    +ORDER BY distance
     LIMIT $3
    • Apply this suggestion
    Suggestion importance[1-10]: 8

    Why: The suggestion improves query performance by using a CTE to avoid recalculating distances and ensures results are ordered primarily by distance, which better aligns with the vector search's purpose.

    8
    Improve function efficiency by validating critical parameters early to prevent unnecessary computation

    The confidence validation should be placed before any expensive operations and
    database queries to fail fast on invalid input.

    memory-store/migrations/000022_vector_search.up.sql [18-24]

     BEGIN
         -- Input validation
    +    IF confidence < -1 OR confidence > 1 THEN
    +        RAISE EXCEPTION 'confidence must be between -1 and 1';
    +    END IF;
    +
         IF k <= 0 THEN
             RAISE EXCEPTION 'k must be greater than 0';
         END IF;
     
    -    IF confidence < -1 OR confidence > 1 THEN
    -        RAISE EXCEPTION 'confidence must be between -1 and 1';
    -    END IF;
    -
    • Apply this suggestion
    Suggestion importance[1-10]: 5

    Why: While the suggestion follows good practice of failing fast, the actual performance impact is minimal since both validations are simple checks performed at the start of the function.

    5
    Optimize query performance by using an appropriate limit multiplier based on actual deduplication needs

    The LIMIT clause in the subquery multiplies k by 4 without clear justification. This
    could lead to unnecessary data processing. Consider adding a comment explaining the
    multiplier or adjusting it based on actual requirements.

    memory-store/migrations/000022_vector_search.up.sql [68]

    -LIMIT ($3 * 4)  -- Get more candidates than needed
    +LIMIT ($3 * 2)  -- Buffer for deduplication while maintaining performance
    • Apply this suggestion
    Suggestion importance[1-10]: 4

    Why: The suggestion raises a valid point about the arbitrary multiplier, but changing from 4 to 2 without clear evidence of the optimal value might impact the quality of results after deduplication.

    4

    Copy link
    Contributor

    @ellipsis-dev ellipsis-dev bot left a comment

    Choose a reason for hiding this comment

    The reason will be displayed to describe this comment to others. Learn more.

    👍 Looks good to me! Incremental review on aff6bd4 in 14 seconds

    More details
    • Looked at 19 lines of code in 1 files
    • Skipped 0 files when reviewing.
    • Skipped posting 2 drafted comments based on config settings.
    1. memory-store/migrations/000022_vector_search.up.sql:67
    • Draft comment:
      The explicit 'ASC' in the ORDER BY clause is redundant since 'ASC' is the default order. However, it improves clarity.
    • Reason this comment was not posted:
      Confidence changes required: 10%
      The ORDER BY clause in the SQL query has been updated to explicitly use 'ASC'. This is a good practice for clarity, but it doesn't change the default behavior since 'ASC' is the default order.
    2. memory-store/migrations/000022_vector_search.up.sql:72
    • Draft comment:
      The explicit 'ASC' in the ORDER BY clause is redundant since 'ASC' is the default order. However, it improves clarity.
    • Reason this comment was not posted:
      Confidence changes required: 10%
      The ORDER BY clause in the final SELECT statement has been updated to explicitly use 'ASC'. This is a good practice for clarity, but it doesn't change the default behavior since 'ASC' is the default order.

    Workflow ID: wflow_Mx2NN1Y1H5gMuKJa


    You can customize Ellipsis with 👍 / 👎 feedback, review rules, user-specific overrides, quiet mode, and more.

    Copy link
    Contributor

    qodo-merge-pro-for-open-source bot commented Jan 13, 2025

    CI Failure Feedback 🧐

    (Checks updated until commit c9e9e87)

    Action: Test

    Failed stage: Run tests [❌]

    Failed test name: test_agent_routes

    Failure summary:

    The action failed due to a database connection pool configuration error. Specifically, the min_size
    (10) was set larger than the max_size (4) in the asyncpg connection pool initialization, which is
    invalid. This caused the test client fixture to fail to initialize, leading to test failures in:

  • test_agent_routes:9 route: unauthorized should fail
  • test_agent_routes:26 route: create agent
  • test_agent_routes:43 route: create agent with instructions

  • Relevant error logs:
    1:  ##[group]Operating System
    2:  Ubuntu
    ...
    
    1335:  PASS  test_agent_queries:28 query: create agent sql                          1%
    1336:  PASS  test_agent_queries:44 query: create or update agent sql                2%
    1337:  PASS  test_agent_queries:63 query: update agent sql                          2%
    1338:  PASS  test_agent_queries:85 query: get agent not exists sql                  3%
    1339:  PASS  test_agent_queries:96 query: get agent exists sql                      3%
    1340:  PASS  test_agent_queries:111 query: list agents sql                          4%
    1341:  PASS  test_agent_queries:122 query: patch agent sql                          4%
    1342:  PASS  test_agent_queries:143 query: delete agent sql                         5%
    1343:  FAIL  test_agent_routes:9 route: unauthorized should fail                    6%
    1344:  FAIL  test_agent_routes:26 route: create agent                               6%
    1345:  FAIL  test_agent_routes:43 route: create agent with instructions             7%
    1346:  ─────────────────────── route: unauthorized should fail ────────────────────────
    1347:  Failed at tests/test_agent_routes.py                                          
    ...
    
    1468:  │ │              name = '_dsn'                                           │ │  
    1469:  │ │              self = TestArgumentResolver(                            │ │  
    1470:  │ │                     │   test=Test(                                   │ │  
    1471:  │ │                     │   │   fn=<function _ at 0x7f3528f0d120>,       │ │  
    1472:  │ │                     │   │   module_name='test_agent_routes',         │ │  
    1473:  │ │                     │   │   id='4aa8c04072754e61b972228274ebc28b',   │ │  
    1474:  │ │                     │   │   marker=None,                             │ │  
    1475:  │ │                     │   │   description='route: unauthorized should  │ │  
    1476:  │ │                     fail',                                           │ │  
    ...
    
    1595:  │ │ self = <anyio._backends._asyncio.BlockingPortal object at            │ │  
    1596:  │ │        0x7f3527de7620>                                               │ │  
    1597:  │ ╰──────────────────────────────────────────────────────────────────────╯ │  
    1598:  │                                                                          │  
    1599:  │ /home/runner/.local/share/uv/python/cpython-3.12.8-linux-x86_64-gnu/lib/ │  
    1600:  │ python3.12/concurrent/futures/_base.py:456 in result                     │  
    1601:  │                                                                          │  
    1602:  │   453 │   │   │   │   if self._state in [CANCELLED, CANCELLED_AND_NOTIFI │  
    1603:  │   454 │   │   │   │   │   raise CancelledError()                         │  
    1604:  │   455 │   │   │   │   elif self._state == FINISHED:                      │  
    1605:  │ ❱ 456 │   │   │   │   │   return self.__get_result()                     │  
    1606:  │   457 │   │   │   │   else:                                              │  
    1607:  │   458 │   │   │   │   │   raise TimeoutError()                           │  
    ...
    
    1639:  │   221 │   │   except self._cancelled_exc_class:                          │  
    1640:  │                                                                          │  
    1641:  │ ╭─────────────────────────────── locals ───────────────────────────────╮ │  
    1642:  │ │                args = ()                                             │ │  
    1643:  │ │                func = <bound method TestClient.wait_startup of       │ │  
    1644:  │ │                       <starlette.testclient.TestClient object at     │ │  
    1645:  │ │                       0x7f3527d4a9f0>>                               │ │  
    1646:  │ │              future = <Future at 0x7f3527d9aff0 state=finished       │ │  
    1647:  │ │                       raised ValueError>                             │ │  
    ...
    
    1651:  │ │               scope = None                                           │ │  
    1652:  │ │                self = <anyio._backends._asyncio.BlockingPortal       │ │  
    1653:  │ │                       object at 0x7f3527de7620>                      │ │  
    1654:  │ ╰──────────────────────────────────────────────────────────────────────╯ │  
    1655:  │                                                                          │  
    1656:  │ /home/runner/work/julep/julep/agents-api/.venv/lib/python3.12/site-packa │  
    1657:  │ ges/starlette/testclient.py:774 in wait_startup                          │  
    1658:  │                                                                          │  
    1659:  │   771 │   │   │   "lifespan.startup.failed",                             │  
    1660:  │   772 │   │   )                                                          │  
    1661:  │   773 │   │   if message["type"] == "lifespan.startup.failed":           │  
    1662:  │ ❱ 774 │   │   │   await receive()                                        │  
    1663:  │   775 │                                                                  │  
    1664:  │   776 │   async def wait_shutdown(self) -> None:                         │  
    1665:  │   777 │   │   async def receive() -> typing.Any:                         │  
    1666:  │                                                                          │  
    1667:  │ ╭─────────────────────────────── locals ───────────────────────────────╮ │  
    1668:  │ │ message = {                                                          │ │  
    1669:  │ │           │   'type': 'lifespan.startup.failed',                     │ │  
    ...
    
    1688:  │ │ message = None                                                       │ │  
    1689:  │ │    self = <starlette.testclient.TestClient object at 0x7f3527d4a9f0> │ │  
    1690:  │ ╰──────────────────────────────────────────────────────────────────────╯ │  
    1691:  │                                                                          │  
    1692:  │ /home/runner/.local/share/uv/python/cpython-3.12.8-linux-x86_64-gnu/lib/ │  
    1693:  │ python3.12/concurrent/futures/_base.py:449 in result                     │  
    1694:  │                                                                          │  
    1695:  │   446 │   │   │   │   if self._state in [CANCELLED, CANCELLED_AND_NOTIFI │  
    1696:  │   447 │   │   │   │   │   raise CancelledError()                         │  
    ...
    
    1732:  │   221 │   │   except self._cancelled_exc_class:                          │  
    1733:  │                                                                          │  
    1734:  │ ╭─────────────────────────────── locals ───────────────────────────────╮ │  
    1735:  │ │                args = ()                                             │ │  
    1736:  │ │                func = <bound method TestClient.lifespan of           │ │  
    1737:  │ │                       <starlette.testclient.TestClient object at     │ │  
    1738:  │ │                       0x7f3527d4a9f0>>                               │ │  
    1739:  │ │              future = <Future at 0x7f3527d9bec0 state=finished       │ │  
    1740:  │ │                       raised ValueError>                             │ │  
    ...
    
    1847:  │ │           waiting_senders=OrderedDict()), _closed=False),            │ │  
    1848:  │ │           receive_stream=MemoryObjectReceiveStream(_state=MemoryObj… │ │  
    1849:  │ │           buffer=deque([]), open_send_channels=1,                    │ │  
    1850:  │ │           open_receive_channels=1, waiting_receivers=OrderedDict(),  │ │  
    1851:  │ │           waiting_senders=OrderedDict()), _closed=False))>           │ │  
    1852:  │ ╰──────────────────────────────────────────────────────────────────────╯ │  
    1853:  │                                                                          │  
    1854:  │ /home/runner/work/julep/julep/agents-api/.venv/lib/python3.12/site-packa │  
    1855:  │ ges/starlette/middleware/errors.py:152 in __call__                       │  
    ...
    
    1875:  │ │   scope = {                                                          │ │  
    1876:  │ │           │   'type': 'lifespan',                                    │ │  
    1877:  │ │           │   'state': {},                                           │ │  
    1878:  │ │           │   'app': <fastapi.applications.FastAPI object at         │ │  
    1879:  │ │           0x7f352af36f00>,                                           │ │  
    1880:  │ │           │   'router': <fastapi.routing.APIRouter object at         │ │  
    1881:  │ │           0x7f352a75f7a0>                                            │ │  
    1882:  │ │           }                                                          │ │  
    1883:  │ │    self = <starlette.middleware.errors.ServerErrorMiddleware object  │ │  
    ...
    
    2105:  │ ges/starlette/routing.py:693 in lifespan                                 │  
    2106:  │                                                                          │  
    2107:  │   690 │   │   app: typing.Any = scope.get("app")                         │  
    2108:  │   691 │   │   await receive()                                            │  
    2109:  │   692 │   │   try:                                                       │  
    2110:  │ ❱ 693 │   │   │   async with self.lifespan_context(app) as maybe_state:  │  
    2111:  │   694 │   │   │   │   if maybe_state is not None:                        │  
    2112:  │   695 │   │   │   │   │   if "state" not in scope:                       │  
    2113:  │   696 │   │   │   │   │   │   raise RuntimeError('The server does not su │  
    ...
    
    2149:  │ /home/runner/.local/share/uv/python/cpython-3.12.8-linux-x86_64-gnu/lib/ │  
    2150:  │ python3.12/contextlib.py:210 in __aenter__                               │  
    2151:  │                                                                          │  
    2152:  │   207 │   │   # they are only needed for recreation, which is not possib │  
    2153:  │   208 │   │   del self.args, self.kwds, self.func                        │  
    2154:  │   209 │   │   try:                                                       │  
    2155:  │ ❱ 210 │   │   │   return await anext(self.gen)                           │  
    2156:  │   211 │   │   except StopAsyncIteration:                                 │  
    2157:  │   212 │   │   │   raise RuntimeError("generator didn't yield") from None │  
    ...
    
    2183:  │ /home/runner/.local/share/uv/python/cpython-3.12.8-linux-x86_64-gnu/lib/ │  
    2184:  │ python3.12/contextlib.py:210 in __aenter__                               │  
    2185:  │                                                                          │  
    2186:  │   207 │   │   # they are only needed for recreation, which is not possib │  
    2187:  │   208 │   │   del self.args, self.kwds, self.func                        │  
    2188:  │   209 │   │   try:                                                       │  
    2189:  │ ❱ 210 │   │   │   return await anext(self.gen)                           │  
    2190:  │   211 │   │   except StopAsyncIteration:                                 │  
    2191:  │   212 │   │   │   raise RuntimeError("generator didn't yield") from None │  
    ...
    
    2217:  │ /home/runner/.local/share/uv/python/cpython-3.12.8-linux-x86_64-gnu/lib/ │  
    2218:  │ python3.12/contextlib.py:210 in __aenter__                               │  
    2219:  │                                                                          │  
    2220:  │   207 │   │   # they are only needed for recreation, which is not possib │  
    2221:  │   208 │   │   del self.args, self.kwds, self.func                        │  
    2222:  │   209 │   │   try:                                                       │  
    2223:  │ ❱ 210 │   │   │   return await anext(self.gen)                           │  
    2224:  │   211 │   │   except StopAsyncIteration:                                 │  
    2225:  │   212 │   │   │   raise RuntimeError("generator didn't yield") from None │  
    ...
    
    2251:  │ /home/runner/.local/share/uv/python/cpython-3.12.8-linux-x86_64-gnu/lib/ │  
    2252:  │ python3.12/contextlib.py:210 in __aenter__                               │  
    2253:  │                                                                          │  
    2254:  │   207 │   │   # they are only needed for recreation, which is not possib │  
    2255:  │   208 │   │   del self.args, self.kwds, self.func                        │  
    2256:  │   209 │   │   try:                                                       │  
    2257:  │ ❱ 210 │   │   │   return await anext(self.gen)                           │  
    2258:  │   211 │   │   except StopAsyncIteration:                                 │  
    2259:  │   212 │   │   │   raise RuntimeError("generator didn't yield") from None │  
    ...
    
    2285:  │ /home/runner/.local/share/uv/python/cpython-3.12.8-linux-x86_64-gnu/lib/ │  
    2286:  │ python3.12/contextlib.py:210 in __aenter__                               │  
    2287:  │                                                                          │  
    2288:  │   207 │   │   # they are only needed for recreation, which is not possib │  
    2289:  │   208 │   │   del self.args, self.kwds, self.func                        │  
    2290:  │   209 │   │   try:                                                       │  
    2291:  │ ❱ 210 │   │   │   return await anext(self.gen)                           │  
    2292:  │   211 │   │   except StopAsyncIteration:                                 │  
    2293:  │   212 │   │   │   raise RuntimeError("generator didn't yield") from None │  
    ...
    
    2319:  │ /home/runner/.local/share/uv/python/cpython-3.12.8-linux-x86_64-gnu/lib/ │  
    2320:  │ python3.12/contextlib.py:210 in __aenter__                               │  
    2321:  │                                                                          │  
    2322:  │   207 │   │   # they are only needed for recreation, which is not possib │  
    2323:  │   208 │   │   del self.args, self.kwds, self.func                        │  
    2324:  │   209 │   │   try:                                                       │  
    2325:  │ ❱ 210 │   │   │   return await anext(self.gen)                           │  
    2326:  │   211 │   │   except StopAsyncIteration:                                 │  
    2327:  │   212 │   │   │   raise RuntimeError("generator didn't yield") from None │  
    ...
    
    2353:  │ /home/runner/.local/share/uv/python/cpython-3.12.8-linux-x86_64-gnu/lib/ │  
    2354:  │ python3.12/contextlib.py:210 in __aenter__                               │  
    2355:  │                                                                          │  
    2356:  │   207 │   │   # they are only needed for recreation, which is not possib │  
    2357:  │   208 │   │   del self.args, self.kwds, self.func                        │  
    2358:  │   209 │   │   try:                                                       │  
    2359:  │ ❱ 210 │   │   │   return await anext(self.gen)                           │  
    2360:  │   211 │   │   except StopAsyncIteration:                                 │  
    2361:  │   212 │   │   │   raise RuntimeError("generator didn't yield") from None │  
    ...
    
    2387:  │ /home/runner/.local/share/uv/python/cpython-3.12.8-linux-x86_64-gnu/lib/ │  
    2388:  │ python3.12/contextlib.py:210 in __aenter__                               │  
    2389:  │                                                                          │  
    2390:  │   207 │   │   # they are only needed for recreation, which is not possib │  
    2391:  │   208 │   │   del self.args, self.kwds, self.func                        │  
    2392:  │   209 │   │   try:                                                       │  
    2393:  │ ❱ 210 │   │   │   return await anext(self.gen)                           │  
    2394:  │   211 │   │   except StopAsyncIteration:                                 │  
    2395:  │   212 │   │   │   raise RuntimeError("generator didn't yield") from None │  
    ...
    
    2421:  │ /home/runner/.local/share/uv/python/cpython-3.12.8-linux-x86_64-gnu/lib/ │  
    2422:  │ python3.12/contextlib.py:210 in __aenter__                               │  
    2423:  │                                                                          │  
    2424:  │   207 │   │   # they are only needed for recreation, which is not possib │  
    2425:  │   208 │   │   del self.args, self.kwds, self.func                        │  
    2426:  │   209 │   │   try:                                                       │  
    2427:  │ ❱ 210 │   │   │   return await anext(self.gen)                           │  
    2428:  │   211 │   │   except StopAsyncIteration:                                 │  
    2429:  │   212 │   │   │   raise RuntimeError("generator didn't yield") from None │  
    ...
    
    2455:  │ /home/runner/.local/share/uv/python/cpython-3.12.8-linux-x86_64-gnu/lib/ │  
    2456:  │ python3.12/contextlib.py:210 in __aenter__                               │  
    2457:  │                                                                          │  
    2458:  │   207 │   │   # they are only needed for recreation, which is not possib │  
    2459:  │   208 │   │   del self.args, self.kwds, self.func                        │  
    2460:  │   209 │   │   try:                                                       │  
    2461:  │ ❱ 210 │   │   │   return await anext(self.gen)                           │  
    2462:  │   211 │   │   except StopAsyncIteration:                                 │  
    2463:  │   212 │   │   │   raise RuntimeError("generator didn't yield") from None │  
    ...
    
    2489:  │ /home/runner/.local/share/uv/python/cpython-3.12.8-linux-x86_64-gnu/lib/ │  
    2490:  │ python3.12/contextlib.py:210 in __aenter__                               │  
    2491:  │                                                                          │  
    2492:  │   207 │   │   # they are only needed for recreation, which is not possib │  
    2493:  │   208 │   │   del self.args, self.kwds, self.func                        │  
    2494:  │   209 │   │   try:                                                       │  
    2495:  │ ❱ 210 │   │   │   return await anext(self.gen)                           │  
    2496:  │   211 │   │   except StopAsyncIteration:                                 │  
    2497:  │   212 │   │   │   raise RuntimeError("generator didn't yield") from None │  
    ...
    
    2560:  │ ╰──────────────────────────────────────────────────────────────────────╯ │  
    2561:  │                                                                          │  
    2562:  │ /home/runner/work/julep/julep/agents-api/.venv/lib/python3.12/site-packa │  
    2563:  │ ges/asyncpg/pool.py:361 in __init__                                      │  
    2564:  │                                                                          │  
    2565:  │    358 │   │   │   │   'min_size is expected to be greater or equal to z │  
    2566:  │    359 │   │                                                             │  
    2567:  │    360 │   │   if min_size > max_size:                                   │  
    2568:  │ ❱  361 │   │   │   raise ValueError('min_size is greater than max_size') │  
    2569:  │    362 │   │                                                             │  
    2570:  │    363 │   │   if max_queries <= 0:                                      │  
    2571:  │    364 │   │   │   raise ValueError('max_queries is expected to be great │  
    ...
    
    2585:  │ │                        max_size = 4                                  │ │  
    2586:  │ │                        min_size = 10                                 │ │  
    2587:  │ │                           reset = None                               │ │  
    2588:  │ │                            self = <asyncpg.pool.Pool object at       │ │  
    2589:  │ │                                   0x7f3527d8ef80>                    │ │  
    2590:  │ │                           setup = None                               │ │  
    2591:  │ ╰──────────────────────────────────────────────────────────────────────╯ │  
    2592:  ╰──────────────────────────────────────────────────────────────────────────╯  
    2593:  ValueError: min_size is greater than max_size                                 
    ...
    
    2670:  │ │         │   }                                                        │ │  
    2671:  │ │         )                                                            │ │  
    2672:  │ │  self = TestArgumentResolver(                                        │ │  
    2673:  │ │         │   test=Test(                                               │ │  
    2674:  │ │         │   │   fn=<function _ at 0x7f3528f0d120>,                   │ │  
    2675:  │ │         │   │   module_name='test_agent_routes',                     │ │  
    2676:  │ │         │   │   id='4aa8c04072754e61b972228274ebc28b',               │ │  
    2677:  │ │         │   │   marker=None,                                         │ │  
    2678:  │ │         │   │   description='route: unauthorized should fail',       │ │  
    ...
    
    2797:  │ │      resolved_args = {}                                              │ │  
    2798:  │ │               self = TestArgumentResolver(                           │ │  
    2799:  │ │                      │   test=Test(                                  │ │  
    2800:  │ │                      │   │   fn=<function _ at 0x7f3528f0d120>,      │ │  
    2801:  │ │                      │   │   module_name='test_agent_routes',        │ │  
    2802:  │ │                      │   │   id='4aa8c04072754e61b972228274ebc28b',  │ │  
    2803:  │ │                      │   │   marker=None,                            │ │  
    2804:  │ │                      │   │   description='route: unauthorized should │ │  
    2805:  │ │                      fail',                                          │ │  
    ...
    
    2830:  │ ╰──────────────────────────────────────────────────────────────────────╯ │  
    2831:  │                                                                          │  
    2832:  │ /home/runner/work/julep/julep/agents-api/.venv/lib/python3.12/site-packa │  
    2833:  │ ges/ward/testing.py:637 in _resolve_single_arg                           │  
    2834:  │                                                                          │  
    2835:  │   634 │   │   │   else:                                                  │  
    2836:  │   635 │   │   │   │   fixture.resolved_val = arg(**args_to_inject)       │  
    2837:  │   636 │   │   except (Exception, SystemExit) as e:                       │  
    2838:  │ ❱ 637 │   │   │   raise FixtureError(f"Unable to resolve fixture '{fixtu │  
    ...
    
    2951:  │ │              name = '_dsn'                                           │ │  
    2952:  │ │              self = TestArgumentResolver(                            │ │  
    2953:  │ │                     │   test=Test(                                   │ │  
    2954:  │ │                     │   │   fn=<function _ at 0x7f3528f0d120>,       │ │  
    2955:  │ │                     │   │   module_name='test_agent_routes',         │ │  
    2956:  │ │                     │   │   id='4aa8c04072754e61b972228274ebc28b',   │ │  
    2957:  │ │                     │   │   marker=None,                             │ │  
    2958:  │ │                     │   │   description='route: unauthorized should  │ │  
    2959:  │ │                     fail',                                           │ │  
    ...
    
    2978:  │ │                     │   │   timer=<ward._testing._Timer object at    │ │  
    2979:  │ │                     0x7f3527906990>,                                 │ │  
    2980:  │ │                     │   │   tags=[]                                  │ │  
    2981:  │ │                     │   ),                                           │ │  
    2982:  │ │                     │   iteration=0                                  │ │  
    2983:  │ │                     )                                                │ │  
    2984:  │ ╰──────────────────────────────────────────────────────────────────────╯ │  
    2985:  ╰──────────────────────────────────────────────────────────────────────────╯  
    2986:  FixtureError: Unable to resolve fixture 'client'                              
    2987:  ───────────────────────────── route: create agent ──────────────────────────────
    2988:  Failed at tests/test_agent_routes.py                                          
    ...
    
    3235:  │ │ self = <anyio._backends._asyncio.BlockingPortal object at            │ │  
    3236:  │ │        0x7f3527d98560>                                               │ │  
    3237:  │ ╰──────────────────────────────────────────────────────────────────────╯ │  
    3238:  │                                                                          │  
    3239:  │ /home/runner/.local/share/uv/python/cpython-3.12.8-linux-x86_64-gnu/lib/ │  
    3240:  │ python3.12/concurrent/futures/_base.py:456 in result                     │  
    3241:  │                                                                          │  
    3242:  │   453 │   │   │   │   if self._state in [CANCELLED, CANCELLED_AND_NOTIFI │  
    3243:  │   454 │   │   │   │   │   raise CancelledError()                         │  
    3244:  │   455 │   │   │   │   elif self._state == FINISHED:                      │  
    3245:  │ ❱ 456 │   │   │   │   │   return self.__get_result()                     │  
    3246:  │   457 │   │   │   │   else:                                              │  
    3247:  │   458 │   │   │   │   │   raise TimeoutError()                           │  
    ...
    
    3279:  │   221 │   │   except self._cancelled_exc_class:                          │  
    3280:  │                                                                          │  
    3281:  │ ╭─────────────────────────────── locals ───────────────────────────────╮ │  
    3282:  │ │                args = ()                                             │ │  
    3283:  │ │                func = <bound method TestClient.wait_startup of       │ │  
    3284:  │ │                       <starlette.testclient.TestClient object at     │ │  
    3285:  │ │                       0x7f3527d99f10>>                               │ │  
    3286:  │ │              future = <Future at 0x7f3527d98f80 state=finished       │ │  
    3287:  │ │                       raised ValueError>                             │ │  
    ...
    
    3291:  │ │               scope = None                                           │ │  
    3292:  │ │                self = <anyio._backends._asyncio.BlockingPortal       │ │  
    3293:  │ │                       object at 0x7f3527d98560>                      │ │  
    3294:  │ ╰──────────────────────────────────────────────────────────────────────╯ │  
    3295:  │                                                                          │  
    3296:  │ /home/runner/work/julep/julep/agents-api/.venv/lib/python3.12/site-packa │  
    3297:  │ ges/starlette/testclient.py:774 in wait_startup                          │  
    3298:  │                                                                          │  
    3299:  │   771 │   │   │   "lifespan.startup.failed",                             │  
    3300:  │   772 │   │   )                                                          │  
    3301:  │   773 │   │   if message["type"] == "lifespan.startup.failed":           │  
    3302:  │ ❱ 774 │   │   │   await receive()                                        │  
    3303:  │   775 │                                                                  │  
    3304:  │   776 │   async def wait_shutdown(self) -> None:                         │  
    3305:  │   777 │   │   async def receive() -> typing.Any:                         │  
    3306:  │                                                                          │  
    3307:  │ ╭─────────────────────────────── locals ───────────────────────────────╮ │  
    3308:  │ │ message = {                                                          │ │  
    3309:  │ │           │   'type': 'lifespan.startup.failed',                     │ │  
    ...
    
    3328:  │ │ message = None                                                       │ │  
    3329:  │ │    self = <starlette.testclient.TestClient object at 0x7f3527d99f10> │ │  
    3330:  │ ╰──────────────────────────────────────────────────────────────────────╯ │  
    3331:  │                                                                          │  
    3332:  │ /home/runner/.local/share/uv/python/cpython-3.12.8-linux-x86_64-gnu/lib/ │  
    3333:  │ python3.12/concurrent/futures/_base.py:449 in result                     │  
    3334:  │                                                                          │  
    3335:  │   446 │   │   │   │   if self._state in [CANCELLED, CANCELLED_AND_NOTIFI │  
    3336:  │   447 │   │   │   │   │   raise CancelledError()                         │  
    ...
    
    3372:  │   221 │   │   except self._cancelled_exc_class:                          │  
    3373:  │                                                                          │  
    3374:  │ ╭─────────────────────────────── locals ───────────────────────────────╮ │  
    3375:  │ │                args = ()                                             │ │  
    3376:  │ │                func = <bound method TestClient.lifespan of           │ │  
    3377:  │ │                       <starlette.testclient.TestClient object at     │ │  
    3378:  │ │                       0x7f3527d99f10>>                               │ │  
    3379:  │ │              future = <Future at 0x7f3527d98980 state=finished       │ │  
    3380:  │ │                       raised ValueError>                             │ │  
    ...
    
    3487:  │ │           waiting_senders=OrderedDict()), _closed=False),            │ │  
    3488:  │ │           receive_stream=MemoryObjectReceiveStream(_state=MemoryObj… │ │  
    3489:  │ │           buffer=deque([]), open_send_channels=1,                    │ │  
    3490:  │ │           open_receive_channels=1, waiting_receivers=OrderedDict(),  │ │  
    3491:  │ │           waiting_senders=OrderedDict()), _closed=False))>           │ │  
    3492:  │ ╰──────────────────────────────────────────────────────────────────────╯ │  
    3493:  │                                                                          │  
    3494:  │ /home/runner/work/julep/julep/agents-api/.venv/lib/python3.12/site-packa │  
    3495:  │ ges/starlette/middleware/errors.py:152 in __call__                       │  
    ...
    
    3515:  │ │   scope = {                                                          │ │  
    3516:  │ │           │   'type': 'lifespan',                                    │ │  
    3517:  │ │           │   'state': {},                                           │ │  
    3518:  │ │           │   'app': <fastapi.applications.FastAPI object at         │ │  
    3519:  │ │           0x7f352af36f00>,                                           │ │  
    3520:  │ │           │   'router': <fastapi.routing.APIRouter object at         │ │  
    3521:  │ │           0x7f352a75f7a0>                                            │ │  
    3522:  │ │           }                                                          │ │  
    3523:  │ │    self = <starlette.middleware.errors.ServerErrorMiddleware object  │ │  
    ...
    
    3745:  │ ges/starlette/routing.py:693 in lifespan                                 │  
    3746:  │                                                                          │  
    3747:  │   690 │   │   app: typing.Any = scope.get("app")                         │  
    3748:  │   691 │   │   await receive()                                            │  
    3749:  │   692 │   │   try:                                                       │  
    3750:  │ ❱ 693 │   │   │   async with self.lifespan_context(app) as maybe_state:  │  
    3751:  │   694 │   │   │   │   if maybe_state is not None:                        │  
    3752:  │   695 │   │   │   │   │   if "state" not in scope:                       │  
    3753:  │   696 │   │   │   │   │   │   raise RuntimeError('The server does not su │  
    ...
    
    3789:  │ /home/runner/.local/share/uv/python/cpython-3.12.8-linux-x86_64-gnu/lib/ │  
    3790:  │ python3.12/contextlib.py:210 in __aenter__                               │  
    3791:  │                                                                          │  
    3792:  │   207 │   │   # they are only needed for recreation, which is not possib │  
    3793:  │   208 │   │   del self.args, self.kwds, self.func                        │  
    3794:  │   209 │   │   try:                                                       │  
    3795:  │ ❱ 210 │   │   │   return await anext(self.gen)                           │  
    3796:  │   211 │   │   except StopAsyncIteration:                                 │  
    3797:  │   212 │   │   │   raise RuntimeError("generator didn't yield") from None │  
    ...
    
    3823:  │ /home/runner/.local/share/uv/python/cpython-3.12.8-linux-x86_64-gnu/lib/ │  
    3824:  │ python3.12/contextlib.py:210 in __aenter__                               │  
    3825:  │                                                                          │  
    3826:  │   207 │   │   # they are only needed for recreation, which is not possib │  
    3827:  │   208 │   │   del self.args, self.kwds, self.func                        │  
    3828:  │   209 │   │   try:                                                       │  
    3829:  │ ❱ 210 │   │   │   return await anext(self.gen)                           │  
    3830:  │   211 │   │   except StopAsyncIteration:                                 │  
    3831:  │   212 │   │   │   raise RuntimeError("generator didn't yield") from None │  
    ...
    
    3857:  │ /home/runner/.local/share/uv/python/cpython-3.12.8-linux-x86_64-gnu/lib/ │  
    3858:  │ python3.12/contextlib.py:210 in __aenter__                               │  
    3859:  │                                                                          │  
    3860:  │   207 │   │   # they are only needed for recreation, which is not possib │  
    3861:  │   208 │   │   del self.args, self.kwds, self.func                        │  
    3862:  │   209 │   │   try:                                                       │  
    3863:  │ ❱ 210 │   │   │   return await anext(self.gen)                           │  
    3864:  │   211 │   │   except StopAsyncIteration:                                 │  
    3865:  │   212 │   │   │   raise RuntimeError("generator didn't yield") from None │  
    ...
    
    3891:  │ /home/runner/.local/share/uv/python/cpython-3.12.8-linux-x86_64-gnu/lib/ │  
    3892:  │ python3.12/contextlib.py:210 in __aenter__                               │  
    3893:  │                                                                          │  
    3894:  │   207 │   │   # they are only needed for recreation, which is not possib │  
    3895:  │   208 │   │   del self.args, self.kwds, self.func                        │  
    3896:  │   209 │   │   try:                                                       │  
    3897:  │ ❱ 210 │   │   │   return await anext(self.gen)                           │  
    3898:  │   211 │   │   except StopAsyncIteration:                                 │  
    3899:  │   212 │   │   │   raise RuntimeError("generator didn't yield") from None │  
    ...
    
    3925:  │ /home/runner/.local/share/uv/python/cpython-3.12.8-linux-x86_64-gnu/lib/ │  
    3926:  │ python3.12/contextlib.py:210 in __aenter__                               │  
    3927:  │                                                                          │  
    3928:  │   207 │   │   # they are only needed for recreation, which is not possib │  
    3929:  │   208 │   │   del self.args, self.kwds, self.func                        │  
    3930:  │   209 │   │   try:                                                       │  
    3931:  │ ❱ 210 │   │   │   return await anext(self.gen)                           │  
    3932:  │   211 │   │   except StopAsyncIteration:                                 │  
    3933:  │   212 │   │   │   raise RuntimeError("generator didn't yield") from None │  
    ...
    
    3959:  │ /home/runner/.local/share/uv/python/cpython-3.12.8-linux-x86_64-gnu/lib/ │  
    3960:  │ python3.12/contextlib.py:210 in __aenter__                               │  
    3961:  │                                                                          │  
    3962:  │   207 │   │   # they are only needed for recreation, which is not possib │  
    3963:  │   208 │   │   del self.args, self.kwds, self.func                        │  
    3964:  │   209 │   │   try:                                                       │  
    3965:  │ ❱ 210 │   │   │   return await anext(self.gen)                           │  
    3966:  │   211 │   │   except StopAsyncIteration:                                 │  
    3967:  │   212 │   │   │   raise RuntimeError("generator didn't yield") from None │  
    ...
    
    3993:  │ /home/runner/.local/share/uv/python/cpython-3.12.8-linux-x86_64-gnu/lib/ │  
    3994:  │ python3.12/contextlib.py:210 in __aenter__                               │  
    3995:  │                                                                          │  
    3996:  │   207 │   │   # they are only needed for recreation, which is not possib │  
    3997:  │   208 │   │   del self.args, self.kwds, self.func                        │  
    3998:  │   209 │   │   try:                                                       │  
    3999:  │ ❱ 210 │   │   │   return await anext(self.gen)                           │  
    4000:  │   211 │   │   except StopAsyncIteration:                                 │  
    4001:  │   212 │   │   │   raise RuntimeError("generator didn't yield") from None │  
    ...
    
    4027:  │ /home/runner/.local/share/uv/python/cpython-3.12.8-linux-x86_64-gnu/lib/ │  
    4028:  │ python3.12/contextlib.py:210 in __aenter__                               │  
    4029:  │                                                                          │  
    4030:  │   207 │   │   # they are only needed for recreation, which is not possib │  
    4031:  │   208 │   │   del self.args, self.kwds, self.func                        │  
    4032:  │   209 │   │   try:                                                       │  
    4033:  │ ❱ 210 │   │   │   return await anext(self.gen)                           │  
    4034:  │   211 │   │   except StopAsyncIteration:                                 │  
    4035:  │   212 │   │   │   raise RuntimeError("generator didn't yield") from None │  
    ...
    
    4061:  │ /home/runner/.local/share/uv/python/cpython-3.12.8-linux-x86_64-gnu/lib/ │  
    4062:  │ python3.12/contextlib.py:210 in __aenter__                               │  
    4063:  │                                                                          │  
    4064:  │   207 │   │   # they are only needed for recreation, which is not possib │  
    4065:  │   208 │   │   del self.args, self.kwds, self.func                        │  
    4066:  │   209 │   │   try:                                                       │  
    4067:  │ ❱ 210 │   │   │   return await anext(self.gen)                           │  
    4068:  │   211 │   │   except StopAsyncIteration:                                 │  
    4069:  │   212 │   │   │   raise RuntimeError("generator didn't yield") from None │  
    ...
    
    4095:  │ /home/runner/.local/share/uv/python/cpython-3.12.8-linux-x86_64-gnu/lib/ │  
    4096:  │ python3.12/contextlib.py:210 in __aenter__                               │  
    4097:  │                                                                          │  
    4098:  │   207 │   │   # they are only needed for recreation, which is not possib │  
    4099:  │   208 │   │   del self.args, self.kwds, self.func                        │  
    4100:  │   209 │   │   try:                                                       │  
    4101:  │ ❱ 210 │   │   │   return await anext(self.gen)                           │  
    4102:  │   211 │   │   except StopAsyncIteration:                                 │  
    4103:  │   212 │   │   │   raise RuntimeError("generator didn't yield") from None │  
    ...
    
    4129:  │ /home/runner/.local/share/uv/python/cpython-3.12.8-linux-x86_64-gnu/lib/ │  
    4130:  │ python3.12/contextlib.py:210 in __aenter__                               │  
    4131:  │                                                                          │  
    4132:  │   207 │   │   # they are only needed for recreation, which is not possib │  
    4133:  │   208 │   │   del self.args, self.kwds, self.func                        │  
    4134:  │   209 │   │   try:                                                       │  
    4135:  │ ❱ 210 │   │   │   return await anext(self.gen)                           │  
    4136:  │   211 │   │   except StopAsyncIteration:                                 │  
    4137:  │   212 │   │   │   raise RuntimeError("generator didn't yield") from None │  
    ...
    
    4200:  │ ╰──────────────────────────────────────────────────────────────────────╯ │  
    4201:  │                                                                          │  
    4202:  │ /home/runner/work/julep/julep/agents-api/.venv/lib/python3.12/site-packa │  
    4203:  │ ges/asyncpg/pool.py:361 in __init__                                      │  
    4204:  │                                                                          │  
    4205:  │    358 │   │   │   │   'min_size is expected to be greater or equal to z │  
    4206:  │    359 │   │                                                             │  
    4207:  │    360 │   │   if min_size > max_size:                                   │  
    4208:  │ ❱  361 │   │   │   raise ValueError('min_size is greater than max_size') │  
    4209:  │    362 │   │                                                             │  
    4210:  │    363 │   │   if max_queries <= 0:                                      │  
    4211:  │    364 │   │   │   raise ValueError('max_queries is expected to be great │  
    ...
    
    4225:  │ │                        max_size = 4                                  │ │  
    4226:  │ │                        min_size = 10                                 │ │  
    4227:  │ │                           reset = None                               │ │  
    4228:  │ │                            self = <asyncpg.pool.Pool object at       │ │  
    4229:  │ │                                   0x7f3527d8c640>                    │ │  
    4230:  │ │                           setup = None                               │ │  
    4231:  │ ╰──────────────────────────────────────────────────────────────────────╯ │  
    4232:  ╰──────────────────────────────────────────────────────────────────────────╯  
    4233:  ValueError: min_size is greater than max_size                                 
    ...
    
    4611:  │ ╰──────────────────────────────────────────────────────────────────────╯ │  
    4612:  │                                                                          │  
    4613:  │ /home/runner/work/julep/julep/agents-api/.venv/lib/python3.12/site-packa │  
    4614:  │ ges/ward/testing.py:637 in _resolve_single_arg                           │  
    4615:  │                                                                          │  
    4616:  │   634 │   │   │   else:                                                  │  
    4617:  │   635 │   │   │   │   fixture.resolved_val = arg(**args_to_inject)       │  
    4618:  │   636 │   │   except (Exception, SystemExit) as e:                       │  
    4619:  │ ❱ 637 │   │   │   raise FixtureError(f"Unable to resolve fixture '{fixtu │  
    ...
    
    4758:  │ │                     │   │   timer=<ward._testing._Timer object at    │ │  
    4759:  │ │                     0x7f3527de4dd0>,                                 │ │  
    4760:  │ │                     │   │   tags=[]                                  │ │  
    4761:  │ │                     │   ),                                           │ │  
    4762:  │ │                     │   iteration=0                                  │ │  
    4763:  │ │                     )                                                │ │  
    4764:  │ ╰──────────────────────────────────────────────────────────────────────╯ │  
    4765:  ╰──────────────────────────────────────────────────────────────────────────╯  
    4766:  FixtureError: Unable to resolve fixture 'client'                              
    4767:  ──────────────────── route: create agent with instructions ─────────────────────
    4768:  Failed at tests/test_agent_routes.py                                          
    ...
    
    5016:  │ │ self = <anyio._backends._asyncio.BlockingPortal object at            │ │  
    5017:  │ │        0x7f3527d21c10>                                               │ │  
    5018:  │ ╰──────────────────────────────────────────────────────────────────────╯ │  
    5019:  │                                                                          │  
    5020:  │ /home/runner/.local/share/uv/python/cpython-3.12.8-linux-x86_64-gnu/lib/ │  
    5021:  │ python3.12/concurrent/futures/_base.py:456 in result                     │  
    5022:  │                                                                          │  
    5023:  │   453 │   │   │   │   if self._state in [CANCELLED, CANCELLED_AND_NOTIFI │  
    5024:  │   454 │   │   │   │   │   raise CancelledError()                         │  
    5025:  │   455 │   │   │   │   elif self._state == FINISHED:                      │  
    5026:  │ ❱ 456 │   │   │   │   │   return self.__get_result()                     │  
    5027:  │   457 │   │   │   │   else:                                              │  
    5028:  │   458 │   │   │   │   │   raise TimeoutError()                           │  
    ...
    
    5060:  │   221 │   │   except self._cancelled_exc_class:                          │  
    5061:  │                                                                          │  
    5062:  │ ╭─────────────────────────────── locals ───────────────────────────────╮ │  
    5063:  │ │                args = ()                                             │ │  
    5064:  │ │                func = <bound method TestClient.wait_startup of       │ │  
    5065:  │ │                       <starlette.testclient.TestClient object at     │ │  
    5066:  │ │                       0x7f3527d980b0>>                               │ │  
    5067:  │ │              future = <Future at 0x7f3528ebb4a0 state=finished       │ │  
    5068:  │ │                       raised ValueError>                             │ │  
    ...
    
    5072:  │ │               scope = None                                           │ │  
    5073:  │ │                self = <anyio._backends._asyncio.BlockingPortal       │ │  
    5074:  │ │                       object at 0x7f3527d21c10>                      │ │  
    5075:  │ ╰──────────────────────────────────────────────────────────────────────╯ │  
    5076:  │                                                                          │  
    5077:  │ /home/runner/work/julep/julep/agents-api/.venv/lib/python3.12/site-packa │  
    5078:  │ ges/starlette/testclient.py:774 in wait_startup                          │  
    5079:  │                                                                          │  
    5080:  │   771 │   │   │   "lifespan.startup.failed",                             │  
    5081:  │   772 │   │   )                                                          │  
    5082:  │   773 │   │   if message["type"] == "lifespan.startup.failed":           │  
    5083:  │ ❱ 774 │   │   │   await receive()                                        │  
    5084:  │   775 │                                                                  │  
    5085:  │   776 │   async def wait_shutdown(self) -> None:                         │  
    5086:  │   777 │   │   async def receive() -> typing.Any:                         │  
    5087:  │                                                                          │  
    5088:  │ ╭─────────────────────────────── locals ───────────────────────────────╮ │  
    5089:  │ │ message = {                                                          │ │  
    5090:  │ │           │   'type': 'lifespan.startup.failed',                     │ │  
    ...
    
    5109:  │ │ message = None                                                       │ │  
    5110:  │ │    self = <starlette.testclient.TestClient object at 0x7f3527d980b0> │ │  
    5111:  │ ╰──────────────────────────────────────────────────────────────────────╯ │  
    5112:  │                                                                          │  
    5113:  │ /home/runner/.local/share/uv/python/cpython-3.12.8-linux-x86_64-gnu/lib/ │  
    5114:  │ python3.12/concurrent/futures/_base.py:449 in result                     │  
    5115:  │                                                                          │  
    5116:  │   446 │   │   │   │   if self._state in [CANCELLED, CANCELLED_AND_NOTIFI │  
    5117:  │   447 │   │   │   │   │   raise CancelledError()                         │  
    ...
    
    5153:  │   221 │   │   except self._cancelled_exc_class:                          │  
    5154:  │                                                                          │  
    5155:  │ ╭─────────────────────────────── locals ───────────────────────────────╮ │  
    5156:  │ │                args = ()                                             │ │  
    5157:  │ │                func = <bound method TestClient.lifespan of           │ │  
    5158:  │ │                       <starlette.testclient.TestClient object at     │ │  
    5159:  │ │                       0x7f3527d980b0>>                               │ │  
    5160:  │ │              future = <Future at 0x7f3527d22ed0 state=finished       │ │  
    5161:  │ │                       raised ValueError>                             │ │  
    ...
    
    5268:  │ │           waiting_senders=OrderedDict()), _closed=False),            │ │  
    5269:  │ │           receive_stream=MemoryObjectReceiveStream(_state=MemoryObj… │ │  
    5270:  │ │           buffer=deque([]), open_send_channels=1,                    │ │  
    5271:  │ │           open_receive_channels=1, waiting_receivers=OrderedDict(),  │ │  
    5272:  │ │           waiting_senders=OrderedDict()), _closed=False))>           │ │  
    5273:  │ ╰──────────────────────────────────────────────────────────────────────╯ │  
    5274:  │                                                                          │  
    5275:  │ /home/runner/work/julep/julep/agents-api/.venv/lib/python3.12/site-packa │  
    5276:  │ ges/starlette/middleware/errors.py:152 in __call__                       │  
    ...
    
    5296:  │ │   scope = {                                                          │ │  
    5297:  │ │           │   'type': 'lifespan',                                    │ │  
    5298:  │ │           │   'state': {},                                           │ │  
    5299:  │ │           │   'app': <fastapi.applications.FastAPI object at         │ │  
    5300:  │ │           0x7f352af36f00>,                                           │ │  
    5301:  │ │           │   'router': <fastapi.routing.APIRouter object at         │ │  
    5302:  │ │           0x7f352a75f7a0>                                            │ │  
    5303:  │ │           }                                                          │ │  
    5304:  │ │    self = <starlette.middleware.errors.ServerErrorMiddleware object  │ │  
    ...
    
    5526:  │ ges/starlette/routing.py:693 in lifespan                                 │  
    5527:  │                                                                          │  
    5528:  │   690 │   │   app: typing.Any = scope.get("app")                         │  
    5529:  │   691 │   │   await receive()                                            │  
    5530:  │   692 │   │   try:                                                       │  
    5531:  │ ❱ 693 │   │   │   async with self.lifespan_context(app) as maybe_state:  │  
    5532:  │   694 │   │   │   │   if maybe_state is not None:                        │  
    5533:  │   695 │   │   │   │   │   if "state" not in scope:                       │  
    5534:  │   696 │   │   │   │   │   │   raise RuntimeError('The server does not su │  
    ...
    
    5570:  │ /home/runner/.local/share/uv/python/cpython-3.12.8-linux-x86_64-gnu/lib/ │  
    5571:  │ python3.12/contextlib.py:210 in __aenter__                               │  
    5572:  │                                                                          │  
    5573:  │   207 │   │   # they are only needed for recreation, which is not possib │  
    5574:  │   208 │   │   del self.args, self.kwds, self.func                        │  
    5575:  │   209 │   │   try:                                                       │  
    5576:  │ ❱ 210 │   │   │   return await anext(self.gen)                           │  
    5577:  │   211 │   │   except StopAsyncIteration:                                 │  
    5578:  │   212 │   │   │   raise RuntimeError("generator didn't yield") from None │  
    ...
    
    5604:  │ /home/runner/.local/share/uv/python/cpython-3.12.8-linux-x86_64-gnu/lib/ │  
    5605:  │ python3.12/contextlib.py:210 in __aenter__                               │  
    5606:  │                                                                          │  
    5607:  │   207 │   │   # they are only needed for recreation, which is not possib │  
    5608:  │   208 │   │   del self.args, self.kwds, self.func                        │  
    5609:  │   209 │   │   try:                                                       │  
    5610:  │ ❱ 210 │   │   │   return await anext(self.gen)                           │  
    5611:  │   211 │   │   except StopAsyncIteration:                                 │  
    5612:  │   212 │   │   │   raise RuntimeError("generator didn't yield") from None │  
    ...
    
    5638:  │ /home/runner/.local/share/uv/python/cpython-3.12.8-linux-x86_64-gnu/lib/ │  
    5639:  │ python3.12/contextlib.py:210 in __aenter__                               │  
    5640:  │                                                                          │  
    5641:  │   207 │   │   # they are only needed for recreation, which is not possib │  
    5642:  │   208 │   │   del self.args, self.kwds, self.func                        │  
    5643:  │   209 │   │   try:                                                       │  
    5644:  │ ❱ 210 │   │   │   return await anext(self.gen)                           │  
    5645:  │   211 │   │   except StopAsyncIteration:                                 │  
    5646:  │   212 │   │   │   raise RuntimeError("generator didn't yield") from None │  
    ...
    
    5672:  │ /home/runner/.local/share/uv/python/cpython-3.12.8-linux-x86_64-gnu/lib/ │  
    5673:  │ python3.12/contextlib.py:210 in __aenter__                               │  
    5674:  │                                                                          │  
    5675:  │   207 │   │   # they are only needed for recreation, which is not possib │  
    5676:  │   208 │   │   del self.args, self.kwds, self.func                        │  
    5677:  │   209 │   │   try:                                                       │  
    5678:  │ ❱ 210 │   │   │   return await anext(self.gen)                           │  
    5679:  │   211 │   │   except StopAsyncIteration:                                 │  
    5680:  │   212 │   │   │   raise RuntimeError("generator didn't yield") from None │  
    ...
    
    5706:  │ /home/runner/.local/share/uv/python/cpython-3.12.8-linux-x86_64-gnu/lib/ │  
    5707:  │ python3.12/contextlib.py:210 in __aenter__                               │  
    5708:  │                                                                          │  
    5709:  │   207 │   │   # they are only needed for recreation, which is not possib │  
    5710:  │   208 │   │   del self.args, self.kwds, self.func                        │  
    5711:  │   209 │   │   try:                                                       │  
    5712:  │ ❱ 210 │   │   │   return await anext(self.gen)                           │  
    5713:  │   211 │   │   except StopAsyncIteration:                                 │  
    5714:  │   212 │   │   │   raise RuntimeError("generator didn't yield") from None │  
    ...
    
    5740:  │ /home/runner/.local/share/uv/python/cpython-3.12.8-linux-x86_64-gnu/lib/ │  
    5741:  │ python3.12/contextlib.py:210 in __aenter__                               │  
    5742:  │                                                                          │  
    5743:  │   207 │   │   # they are only needed for recreation, which is not possib │  
    5744:  │   208 │   │   del self.args, self.kwds, self.func                        │  
    5745:  │   209 │   │   try:                                                       │  
    5746:  │ ❱ 210 │   │   │   return await anext(self.gen)                           │  
    5747:  │   211 │   │   except StopAsyncIteration:                                 │  
    5748:  │   212 │   │   │   raise RuntimeError("generator didn't yield") from None │  
    ...
    
    5774:  │ /home/runner/.local/share/uv/python/cpython-3.12.8-linux-x86_64-gnu/lib/ │  
    5775:  │ python3.12/contextlib.py:210 in __aenter__                               │  
    5776:  │                                                                          │  
    5777:  │   207 │   │   # they are only needed for recreation, which is not possib │  
    5778:  │   208 │   │   del self.args, self.kwds, self.func                        │  
    5779:  │   209 │   │   try:                                                       │  
    5780:  │ ❱ 210 │   │   │   return await anext(self.gen)                           │  
    5781:  │   211 │   │   except StopAsyncIteration:                                 │  
    5782:  │   212 │   │   │   raise RuntimeError("generator didn't yield") from None │  
    ...
    
    5808:  │ /home/runner/.local/share/uv/python/cpython-3.12.8-linux-x86_64-gnu/lib/ │  
    5809:  │ python3.12/contextlib.py:210 in __aenter__                               │  
    5810:  │                                                                          │  
    5811:  │   207 │   │   # they are only needed for recreation, which is not possib │  
    5812:  │   208 │   │   del self.args, self.kwds, self.func                        │  
    5813:  │   209 │   │   try:                                                       │  
    5814:  │ ❱ 210 │   │   │   return await anext(self.gen)                           │  
    5815:  │   211 │   │   except StopAsyncIteration:                                 │  
    5816:  │   212 │   │   │   raise RuntimeError("generator didn't yield") from None │  
    ...
    
    5842:  │ /home/runner/.local/share/uv/python/cpython-3.12.8-linux-x86_64-gnu/lib/ │  
    5843:  │ python3.12/contextlib.py:210 in __aenter__                               │  
    5844:  │                                                                          │  
    5845:  │   207 │   │   # they are only needed for recreation, which is not possib │  
    5846:  │   208 │   │   del self.args, self.kwds, self.func                        │  
    5847:  │   209 │   │   try:                                                       │  
    5848:  │ ❱ 210 │   │   │   return await anext(self.gen)                           │  
    5849:  │   211 │   │   except StopAsyncIteration:                                 │  
    5850:  │   212 │   │   │   raise RuntimeError("generator didn't yield") from None │  
    ...
    
    5876:  │ /home/runner/.local/share/uv/python/cpython-3.12.8-linux-x86_64-gnu/lib/ │  
    5877:  │ python3.12/contextlib.py:210 in __aenter__                               │  
    5878:  │                                                                          │  
    5879:  │   207 │   │   # they are only needed for recreation, which is not possib │  
    5880:  │   208 │   │   del self.args, self.kwds, self.func                        │  
    5881:  │   209 │   │   try:                                                       │  
    5882:  │ ❱ 210 │   │   │   return await anext(self.gen)                           │  
    5883:  │   211 │   │   except StopAsyncIteration:                                 │  
    5884:  │   212 │   │   │   raise RuntimeError("generator didn't yield") from None │  
    ...
    
    5910:  │ /home/runner/.local/share/uv/python/cpython-3.12.8-linux-x86_64-gnu/lib/ │  
    5911:  │ python3.12/contextlib.py:210 in __aenter__                               │  
    5912:  │                                                                          │  
    5913:  │   207 │   │   # they are only needed for recreation, which is not possib │  
    5914:  │   208 │   │   del self.args, self.kwds, self.func                        │  
    5915:  │   209 │   │   try:                                                       │  
    5916:  │ ❱ 210 │   │   │   return await anext(self.gen)                           │  
    5917:  │   211 │   │   except StopAsyncIteration:                                 │  
    5918:  │   212 │   │   │   raise RuntimeError("generator didn't yield") from None │  
    ...
    
    5981:  │ ╰──────────────────────────────────────────────────────────────────────╯ │  
    5982:  │                                                                          │  
    5983:  │ /home/runner/work/julep/julep/agents-api/.venv/lib/python3.12/site-packa │  
    5984:  │ ges/asyncpg/pool.py:361 in __init__                                      │  
    5985:  │                                                                          │  
    5986:  │    358 │   │   │   │   'min_size is expected to be greater or equal to z │  
    5987:  │    359 │   │                                                             │  
    5988:  │    360 │   │   if min_size > max_size:                                   │  
    5989:  │ ❱  361 │   │   │   raise ValueError('min_size is greater than max_size') │  
    5990:  │    362 │   │                                                             │  
    5991:  │    363 │   │   if max_queries <= 0:                                      │  
    5992:  │    364 │   │   │   raise ValueError('max_queries is expected to be great │  
    ...
    
    6006:  │ │                        max_size = 4                                  │ │  
    6007:  │ │                        min_size = 10                                 │ │  
    6008:  │ │                           reset = None                               │ │  
    6009:  │ │                            self = <asyncpg.pool.Pool object at       │ │  
    6010:  │ │                                   0x7f3527d8fb80>                    │ │  
    6011:  │ │                           setup = None                               │ │  
    6012:  │ ╰──────────────────────────────────────────────────────────────────────╯ │  
    6013:  ╰──────────────────────────────────────────────────────────────────────────╯  
    6014:  ValueError: min_size is greater than max_size                                 
    ...
    
    6394:  │ ╰──────────────────────────────────────────────────────────────────────╯ │  
    6395:  │                                                                          │  
    6396:  │ /home/runner/work/julep/julep/agents-api/.venv/lib/python3.12/site-packa │  
    6397:  │ ges/ward/testing.py:637 in _resolve_single_arg                           │  
    6398:  │                                                                          │  
    6399:  │   634 │   │   │   else:                                                  │  
    6400:  │   635 │   │   │   │   fixture.resolved_val = arg(**args_to_inject)       │  
    6401:  │   636 │   │   except (Exception, SystemExit) as e:                       │  
    6402:  │ ❱ 637 │   │   │   raise FixtureError(f"Unable to resolve fixture '{fixtu │  
    ...
    
    6542:  │ │                     │   │   timer=<ward._testing._Timer object at    │ │  
    6543:  │ │                     0x7f3527db9310>,                                 │ │  
    6544:  │ │                     │   │   tags=[]                                  │ │  
    6545:  │ │                     │   ),                                           │ │  
    6546:  │ │                     │   iteration=0                                  │ │  
    6547:  │ │                     )                                                │ │  
    6548:  │ ╰──────────────────────────────────────────────────────────────────────╯ │  
    6549:  ╰──────────────────────────────────────────────────────────────────────────╯  
    6550:  FixtureError: Unable to resolve fixture 'client'                              
    6551:  ────────────────────────────────────────────────────────────────────────────────
    6552:  ╭──────────── Results ─────────────╮
    6553:  │  12  Tests Encountered           │
    6554:  │   9  Passes             (75.0%)  │
    6555:  │   3  Failures           (25.0%)  │
    6556:  ╰──────────────────────────────────╯
    6557:  ─────────────────────────── FAILED in 51.05 seconds ────────────────────────────
    6558:  ##[error]Process completed with exit code 1.
    

    ✨ CI feedback usage guide:

    The CI feedback tool (/checks) automatically triggers when a PR has a failed check.
    The tool analyzes the failed checks and provides several feedbacks:

    • Failed stage
    • Failed test name
    • Failure summary
    • Relevant error logs

    In addition to being automatically triggered, the tool can also be invoked manually by commenting on a PR:

    /checks "https://github.com/{repo_name}/actions/runs/{run_number}/job/{job_number}"
    

    where {repo_name} is the name of the repository, {run_number} is the run number of the failed check, and {job_number} is the job number of the failed check.

    Configuration options

    • `enable_auto_checks_feedbac...

    Copy link
    Contributor

    @ellipsis-dev ellipsis-dev bot left a comment

    Choose a reason for hiding this comment

    The reason will be displayed to describe this comment to others. Learn more.

    👍 Looks good to me! Incremental review on c9e9e87 in 31 seconds

    More details
    • Looked at 88 lines of code in 4 files
    • Skipped 0 files when reviewing.
    • Skipped posting 1 drafted comments based on config settings.
    1. agents-api/agents_api/autogen/Docs.py:153
    • Draft comment:
      Ensure that the logic handling the confidence parameter can accommodate negative values, as the range has been expanded to include them. This change is also present in other files like integrations-service/integrations/autogen/Docs.py and typespec/docs/models.tsp.
    • Reason this comment was not posted:
      Confidence changes required: 50%
      The change in the confidence parameter range from 0.0 to -1.0 is consistent across multiple files. This change should be verified for correctness, as it might affect the logic that depends on this parameter.

    Workflow ID: wflow_SuC1OR7grtoOtGhm


    You can customize Ellipsis with 👍 / 👎 feedback, review rules, user-specific overrides, quiet mode, and more.

    @Ahmad-mtos Ahmad-mtos merged commit 1e7cd34 into dev Jan 13, 2025
    16 of 20 checks passed
    @Ahmad-mtos Ahmad-mtos deleted the x/vector-search branch January 13, 2025 08:37
    Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
    Projects
    None yet
    Development

    Successfully merging this pull request may close these issues.

    1 participant