-
Notifications
You must be signed in to change notification settings - Fork 147
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
Low Level Solver API #82
Merged
Merged
Conversation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Baseline configuration with baseline implementation in a few places
This allows the types to flow from package.json
This is causing a failure in resolving dependencies which prevents yarn install from working.
(move it out of transcript view - it expects to receive events with resolve content)
…cript track changes/transcript for tool calls
…t_ai into feature/subtasks
dragonstyle
approved these changes
Aug 20, 2024
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.
This is an epic PR
max-kaufmann
pushed a commit
that referenced
this pull request
Sep 9, 2024
* initial work on subtasks * update readme * remove readme (it's now in the PR writeup) * skip tool store test if no openai * fix typo * correct message reading * correct type * Proof of concept for JSDoc Styles Baseline configuration with baseline implementation in a few places * Use yarn to manage preact / htm This allows the types to flow from package.json * Fully type util as proof of concept * Cleanup in utils * Proof of concept using types from log.d.ts * Rough in of transcript dump * Try to reign in type checking for prism here * update to latest prettier * Conditionally show transcript tab * Another solver rendering * Move transcript views * Including TZ information in timestamp * Tweaked step implementation * Add tools to model dump * Revise model event view (still WIP) * More structured transcript * A little more air * A little more tweaking * fix prettier complaint * trying updating yarn.lock * Attempt to force resolution * Remove `json-schema-to-typescript` This is causing a failure in resolving dependencies which prevents yarn install from working. * Improved state change view * Further fine tuning of appearance * Ensure store support too * More standard appearance * Fix content size * Improve appearance * Properly render objects and arrays in state changes * Improve grid appearance * Remove unused imports * Correct subtask inline display * Simplify state change event rendering * Fix prettier * Share event layout * Improve logger event view * add ScoreEvent * remove unused var * track state changes in transcript steps * remove subtask stuff from web_search for now * Improve state changes rendering * Remove logger event title for more compactness (also includes improvements to the transcript event view itself) * Add a scorer event handler * Improve subtask rendering * fix heading cursor * Improve Score Event View * merge from main * turn event into a base class * don't export event types * regen schema * fixup imports * revert event type changes * write schema to types dir * transcript events: no export and standard 'data' field * regen schema * fix transcript test * use pydantic 2.0 field_serialiser * Revert "transcript events: no export and standard 'data' field" This reverts commit 5f2b654. * use pydantic 2.0 field_serialiser * don't export events * remove unused import * log the full logging message * rename log method * drive transcript events into recorder * write through to trsc file * cleaner interface for transcript event forwarding * initial write to sqlite * Standardize font-size on rem * decorate the html tag for the logview so it can detect vscode immediately * Improve column allocation * Create Shared Fonts Object Move all things to a shared notion of fonts and styles that can be re-used easily. Use font scaling in vscode to achieve the correct appearance (now that we’re rem based we can just change the base font size). * Move summary stats into navbar * Restructure navbar into workspace * Improve progress bar appearance * Improve column sizing * Refactor tab appearance into navbar * Adjust correct/incorrect appearance * Baseline pill improvements * fix heading height in vscode * correct sidebar * Improve sidebar appearance (+prettier) * widen sidebar slightly * Sample Display Tweaks * Tweaks to config * initial work on content db * more comprehensive event walking * de-duplicate content in transcript events * Remove timestamps, correct prop name * Baseline implementation of evalevents resolving plus some prettier formatting * Correct content resolution * remove logging section of evallog (now covered in sample transcript) * Improve density when hosted in vscode at narrow short sizes * Revised appearance to grouped cards * formatting * A little more tweakage * generate_loop and tool_call steps * Fix lint issues * no srsly fix lint * resolve circular import * run prettier on event panel * Fix error w/specific logs * update test * Improve find band appearance * sample init event * Proof of concept state rendering * Relocate state code since it will grow * correct resolution of objects * lint and formatting * sample_init event * Add collapsible state to event panel, collapse certain panels * Subtask rough in * ensure we have vite * Correct merge + regen dist * add a watch command * correct formatting * correct build (investigating why my local build wasn’t flagging this) * include source maps * Add Sample Init, track state across transcript * fix lint * update dist * ensure nav-pills align bottom * correct lint * Add chat view to model * prettier * ran commands in wrong order * Improve sample init event (still mostly a dump of data) * Add all messages view * Simplify transcript view * Improvements to display * Chatview should show tool call even if no message * Improve state event display * Display choices in sampleinit event * Improve Score Event appearance * Tweak title results * More appearance tweakage * Improve tab appearance * Fix tab selection issue in subtask transcripts * Improved spacing * Fix scoring metadata layout * toolcall event * initial work on raw request/response for model event * Add placeholder tool event * initial work on raw model calls * log raw tool argument not converted * log raw model call for anthropic * format attribs notebook * raw model request for mistral * Add depth to cards (with basic impl) * remove map * ignore source map * Add baseline model raw view * Improve state appearance * Improve log display * fix formatting * properly default to messages if no transcript * add one last debug message * Disable build checking with note * Appearance refinement - only start indenting at second level step - create section component * raw capture for google * Don’t capture args when logging This is doing a lot of work which shouldn’t be happening in a log handler (and the value of the args is suspect anyhow). Causing an exception in certain environments. * Remove disused imports * record raw api calls for groq * Improve root solver display - break up root cards - add sample init step (synthetic) * raw api call recording * raw model access for cloudflare * raw model output for azureai * Improve subtask display * raw model capture for vertex * eliminate qualifying note on tool descriptions * improve setup display * Add ToolView * improved agents api docs * Tweaks * eliminate tool steps * hide agents api for now * agents api docs * Resolve the model call contents * Special case handling for sample init event title (no dupe title) * Improve logging event appearance * more tool docs * rename to agents api * remove bash prompt * Correct transcript icons * improve tab selection behavior * Improved model display * Correct font size in metadatagrid * initial work on tool transcript * more tool event work * schema updates * Refactor content resolution to the very top level (move it out of transcript view - it expects to receive events with resolve content) * Resolve the whole state object for events * remove generate_loop step type * Fix ruff errors * don’t force wrap in weird ways * Correct tool rendering for state events * Baseline visual diff implementation * Move tools to single transcript tab * Improve tool event output rendering * Don’t intend tool input / output * enable docs + add parallel execution * Fix prism coloring for js, python, json * show no output message if there is not tool output * allow event titles to wrap * Improve wrapping at small sizes (model event) * crossref to agents api article --------- Co-authored-by: aisi-inspect <[email protected]> Co-authored-by: Charles Teague <[email protected]> Co-authored-by: jjallaire-aisi <[email protected]>
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Overview
This PR implements several related new features aimed at improving the development and observability of complex agent evals. Taken together, these capabilities constitute a "low-level" Solver API that affords full control over execution and model interactions. This is intended to compliment the "high-level" Solver API which assumes a more linear model interaction history and relies on the default
generate()
function and tool use loop.Our goal is to identify the lower level capabilities common to agent evaluations and provide an inspect-native implementation of them. The hope is that this will enable both "bare metal" agent development (just using Inspect w/ no extra libraries) as well as free higher level agent abstractions built on inspect from many lower level concerns (e.g. state-tracking, observability, managing sub-agents, etc.). Ideally, core agents could be implemented using Inspect primitives only, and then be re-used in both bare-metal evals as well as evals that use additional abstractions from a dedicated agent library.
This PR is currently a draft pending implementation of log viewer features to visualise transcripts / state changes / events / etc.
Tool Use
Previously, tool use in Inspect required the use of the higher level
generate()
function passed to solvers. We've now refactored things so that its easy to code the equivalent of thegenerate()
function even when using lower-level direct interactions w/ LLMs. For example:This does everything that default
generate()
does (save for the outer loop). You could implement the outer loop as follows:One additional change made to facilitate implementing the equivalent of
generate()
is that when callingget_model()
with no parameters to get the "active" model, themodel
instance you get back will use the evaluation's defaultGenerateConfig
(e.g.temperature
,top_p
, etc.). Note that previously you needed to call the higher levelgenerate()
passed to Solvers to have this configuration applied.Store
The
Store
is intended as a replacement for reading/writing tostate.metadata
. It includes better facilities for default values and has a clean mechanism for use within tools. TheStore
is also designed to play well with Transcripts and Subtasks (both described below). The core of theStore
interface is:Basic views on the store's collection (e.g.
items()
,keys()
,values()
) are also provided. Note that theget()
method will automatically add thedefault
to the store if it doesn't exist.The
Store
can be accessed viaTaskState
as follows:It is also possible the access the
Store
for the current sample using thestore()
function. This is the mechanism for tools to read and write theStore
. For example:While there is no formal namespacing mechanism for the
Store
, this can be informally achieved using key prefixes as demonstrated above.See store.py for the full implementation of
Store
.Transcripts
The current Inspect logs only record the final state of the message history, which for complex evals that re-write the message history tells you very little about "what happened" during the execution of the sample. Transcripts are intended to provide a rich per-sample view of everything that occurred. Transcripts consist of a list of events, here are the core events that are recorded:
StateEvent
TaskState
that occur within aSolver
.ModelEvent
LoggerEvent
logger.warning("warn)
).StepEvent
Solver
but you can also add your own steps.The plan is to replace the default "Messages" view in the Inspect log viewer with a "Transcript" view that provides much better visibility into what actually occurred during execution. These are the core events, there are additionally
InfoEvent
,StepEvent
,StoreEvent
, andSubtaskEvent
which are described below.Custom Info
You can insert custom entries into the transcript via the Transcipt
info()
method (which creates anInfoEvent
). Access the transcript for the current sample using thetranscript()
function, for example:You can pass arbitrary JSON serialisable objects to
info()
(we will likely want to create a mechanism for rich display of this data within the log viewer):Grouping with Steps
You can create arbitrary groupings of transcript activity using the Transcript
step()
context manager. For example:There are two reasons that you might want to create steps:
StoreEvent
that records the changes (in JSON Patch format) that occurred.See transcript.py for the full implementation of
Transcript
.Subtasks
Subtasks provide a mechanism for creating isolated, re-usable units of execution. You might implement a complex tool using a subtask or might use them in a multi-agent evaluation. The main characteristics of sub-tasks are:
They run in their own async coroutine.
They have their own isolated
Transcript
They have their own isolated
Store
(no access to the sampleStore
).To create a subtask, declare an async function with the
@subtask
decorator. The function can take any arguments and return a value of any type. For example:Note that we add
links
to thestore
not because we strictly need to for our implementation, but because we want the links to be recorded as part of the transcript.Call the subtask as you would any async function:
A few things will occur automatically when you run a subtask:
New isolated
Store
andTranscript
objects will be created for the subtask (accessible via thestore()
andtranscript()
functions). Changes to theStore
that occur during execution will be recorded in aStoreEvent
.A
SubtaskEvent
will be added to the current transcript. The event will include the name of the subtask, its input and results, and a transcript of all events that occur within the subtask.You can also include one or more steps within a subtask.
Tool Subtasks
If a tool is entirely independent of other tools (i.e. it is not coordinating with other tools via changes to the
store
) you can make the tool itself a subtask. This would be beneficial if the tool had interactions (e.g. model calls, store changes, etc.) you want to record in a distinct transcript.To enclose a tool in a subtask, just add the
@subtask
decorator to the tool's execute function. For example, let's adapt theweb_search()
function above into a tool that also defines a subtask (note we also add amodel
parameter to customise what model is used for summarisation):Note that we've added the
name="web_search"
argument to@subtask
—this is because we've declared our function using the generic nameexecute()
and want to provide an alternative that is more readily understandable.See subtask.py for the full implementation of the
@subtask
decorator.