-
Notifications
You must be signed in to change notification settings - Fork 2
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
Query replay #45
base: main
Are you sure you want to change the base?
Query replay #45
Conversation
How about making this part of the language model (engine), e.g. as a wrapper?
Also, it would be nice to have a verification that only cached queries are made, and in the right order. |
Checks that query match are already there. I wanted to create a ReplayModel but it has some caveats:
|
do I understand correctly that
are two independent things @spirali? |
prompt: str | FormatStr, | ||
kwargs: dict = None, | ||
with_context=True, | ||
replay: Replay = None, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
typing should be Optional[Replay]
or Replay | None
class Replay: | ||
def __init__(self, context: Context): | ||
self.replays = {} | ||
for context in context.find_contexts(lambda ctx: ctx.kind == "query"): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
might be good to extract string constants like "query"
, "conf"
, "prompt"
etc into a constants module. it can reduce the risk of bugs from typos. it can also signal to future devs that these are keys which more than one module relies on
self.replays.setdefault(key, []) | ||
self.replays[key].append(context.result) | ||
for replay in self.replays.values(): | ||
replay.reverse() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the logic here assumes that future implementations of StorageBase.list
adhere to a certain order of listing contexts. This should be specified in the doc string of StorageBase.list
and tested in a unit test (if not there already)
|
||
|
||
@patch("interlab.lang_models.openai._make_openai_chat_query") | ||
def test_replay_model(_make_openai_chat_query): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nice test!
returning to this point by @gavento
calls to What are your thoughts about making replay easily available consistently across all methods which rely on LLM calls @spirali? PS: also wanted to say that I find the current implementation very clean and readable! just not sure what the best design will be in the longer run |
Major thought why not: separation of concerns.
I am against adding more functionality to it - I think it is bad design, and the functionality does not seem core to me (or, at least, I am not convinced it is the right way to do it), and bloating one function for it seems bad design for any future.
Prevalence of
So how about adding it as a wrapper around LLMs individually?
|
I am rewriting replay functionality from scratch. I want to make this functionality completely generic (any function / method call can be replayed, not necessarily only LLMs). I have some PoC but I would like to sanity check of the idea before finishing it. Here is how it should look at the end: def my_function(x, y):
return x + y
replay = Replay("my-replay-stream-name")
# Storing replay
with Context("root") as root:
replay(my_function)(1, 2)
# Using replay
replay = Replay("my-replay-stream-name", context=root)
with Context("root") as root:
replay(my_function)(2, 3) # Call my_function as it is not in cache
replay(my_function)(1, 2) # Recalls from cache
replay(my_function)(1, 2) # Call my_function as it is not in cache (2nd call)
# Wrapping any object, in replay log is stored also "self"
from langchain.llms import OpenAI
llm = replay(OpenAI(...))
llm.generate(["Tell me a joke."])
# Partial matching
replay(my_function, ignore_args=["y"])(2, 3) # Ignores argument "y" when trying to find matching call in cache Any comments? |
Thanks! Three comments:
|
I also want to pitch games/situations with storable state (pickle is fine) and meaningful steps where the state can be stored/restored ;-) |
|
Simple query caching
Fixes #40