Multpile llm logs -f are now ANDed together, closes #889

This commit is contained in:
Simon Willison 2025-04-06 22:22:30 -07:00
parent d4a54bb7a8
commit b011ed8352
3 changed files with 35 additions and 15 deletions

View file

@ -113,6 +113,8 @@ llm logs -c -f 0d6e368f9bc21f8db78c01e192ecf925841a957d8b991f5bf9f6239aa4d81815
```
This accepts URLs, file paths, aliases, and hash IDs.
Multiple `-f` options will return responses that used **all** of the specified fragments.
Fragments are returned by `llm logs --json` as well. By default these are truncated but you can add the `-e/--expand` option to show the full content of each fragment.
```bash

View file

@ -1302,23 +1302,30 @@ def logs_list(
fragment_hashes = [
fragment.id() for fragment in resolve_fragments(db, fragments)
]
frags = ", ".join(f":f{i}" for i in range(len(fragments)))
response_ids_sql = f"""
select response_id from prompt_fragments
where fragment_id in (
select fragments.id from fragments
where hash in ({frags})
)
union
select response_id from system_fragments
where fragment_id in (
select fragments.id from fragments
where hash in ({frags})
)
"""
where_bits.append(f"responses.id in ({response_ids_sql})")
exists_clauses = []
for i, fragment_hash in enumerate(fragment_hashes):
exists_clause = f"""
exists (
select 1 from prompt_fragments
where prompt_fragments.response_id = responses.id
and prompt_fragments.fragment_id in (
select fragments.id from fragments
where hash = :f{i}
)
union
select 1 from system_fragments
where system_fragments.response_id = responses.id
and system_fragments.fragment_id in (
select fragments.id from fragments
where hash = :f{i}
)
)
"""
exists_clauses.append(exists_clause)
sql_params["f{}".format(i)] = fragment_hash
where_bits.append(" AND ".join(exists_clauses))
schema_id = None
if schema:
schema_id = make_schema_id(schema)[0]

View file

@ -560,6 +560,17 @@ def fragments_fixture(user_path):
},
],
),
# Testing for AND condition
(
["hash1", "hash4"],
[
{
"name": "both_fragments",
"prompt_fragments": ["hash1", "hash2"],
"system_fragments": ["hash3", "hash4"],
},
],
),
),
)
def test_logs_fragments(fragments_fixture, fragment_refs, expected):