-
Notifications
You must be signed in to change notification settings - Fork 66
ICE UI guide
Explanations of some less obvious features of ICE.
At the top of a trace page is a toolbar:
- The dropdown lists all the unique Python functions/methods called in the trace, along with a count of how many times each function was called. Selecting a function highlights that function, so its nodes will be shown with a yellow border for emphasis.
- "Expand" will expand parent nodes as needed to make all nodes of the highlighted function visible. It only expands nodes in addition to whatever's already expanded, it doesn't collapse anything. This can easily lead to an overwhelming state, so the "Collapse all" button is provided as a reset. This is different from simply collapsing the root node, which doesn't collapse any of its children, although of course that isn't immediately obvious.
- When the "Hide others" toggle is 'on', then nodes which are 'irrelevant' to the highlighted function are hidden, making the highlighted nodes closer together and easier to see. Specifically, only highlighted nodes and their ancestors/descendants remain visible, while other nodes 'on the side' are hidden.
With a little magic sprinkled in your Python code, you can make it easy to distinguish between the static and dynamic parts of f-strings. For example, here's part of the detail pane from a trace of the debate recipe:
The alternating colored text indicates some dynamic values that were interpolated into an f-string at runtime. In other words, they're the interesting parts!
Here's how part of the prompt in the screenshot above was created:
from fvalues import F
prompt = F(
f"""
You are {agent_name}. There are {turns_left} turns left in the debate. You are trying to win the debate using reason and evidence. Don't repeat yourself. No more than 1-2 sentences per turn.
{render_debate(debate, agent_name)}
You: "
"""
).strip()
Note how {agent_name}
and {turns_left}
correspond to colored text. That's pretty much all you have to do in most situations: wrap f-strings in fvalues.F
. The result is a subclass of str
that you can just like a regular str
, but it will store information about how it was constructed. Here's a couple more tips:
- It's important that the code says
F(f"...").strip()
rather thanF(f"...".strip())
, or the magic won't work. - Similarly, if you want to
join
a bunch of strings, useF(separator).join(my_strings)
rather than justseparator.join(my_strings)
. Otherwise you'll just end up with a plainstr
, even ifmy_strings
contains specialF
strings. - See the
fvalues
repo for more details.