Skip to content

Conversation

@jfeser
Copy link
Contributor

@jfeser jfeser commented Nov 26, 2025

The sampling methods in #415 and #412 could be mostly implemented on top of a parallel sample operation. You get a little less parallelism, since you would wait for all voters to complete before scheduling new ones.

@jfeser
Copy link
Contributor Author

jfeser commented Nov 26, 2025

Unfortunately, adding type annotations to sample seems to crash mypy. I can figure out a workaround if we decide this is worth merging.

@jfeser
Copy link
Contributor Author

jfeser commented Dec 1, 2025

I think it would be better to implement this slightly differently, so converting to draft for now.

@jfeser jfeser marked this pull request as ready for review December 1, 2025 23:51
completed = futures.wait(tasks, return_when=futures.ALL_COMPLETED)
return [t.result() for t in completed.done]

return handler({Template.__call__: _template_call})(template)
Copy link
Contributor

Choose a reason for hiding this comment

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

what is the benefit of sample using the handler machinery here rather than directly retrieving the information from the template passed in?

Copy link
Contributor

Choose a reason for hiding this comment

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

and then recursively calling Template.__call__ to reuse the existing machinery? also should sample be a defop?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good idea.

try:
result = fwd()
except Exception as e:
lock.release()
Copy link
Contributor

Choose a reason for hiding this comment

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

if fwd() doesn't raise an exception this won't release the lock no?

with lock:
    return fwd()

Copy link
Contributor

Choose a reason for hiding this comment

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

also it might be good to have some test for this functionality, mocking the llm, just checking that we're doing concurrency correctly

Copy link
Contributor Author

Choose a reason for hiding this comment

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

if fwd() doesn't raise an exception this won't release the lock no?

with lock:
    return fwd()

We actually don't want to. If the tool call completes successfully, we keep the lock up to the point that we start another completion. Releasing the lock here allows the remaining threads to proceed as this thread dies. The fwd in the completion handler can fail safely because we don't hold the lock.

This raises a good point though: what should we do when one of the threads fails? Right now we reraise the exception from the failed thread and you get no samples. Maybe instead you should get the successful samples?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Agreed on tests.

return result

def _tool_call(*args, **kwargs):
lock.acquire()
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think this call to acquire isn't necessary.

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.

4 participants