[RSPEED-2267] Convert service commands to return structured output#225
[RSPEED-2267] Convert service commands to return structured output#225subpop wants to merge 10 commits into
Conversation
980c7eb to
f256b00
Compare
owtaylor
left a comment
There was a problem hiding this comment.
I'm not quite sure how to to approach turning systemctl status into structured objects:
A) Parse the output, turn that into objects
B) Use lower-level API to obtain the information, reimplemen* the "summarization" of systemctl status inside our code.
C) Expose the low-level data sources, let the model parse through what it needs
A) is ugly and fragile. B) is ugly. C) will definitely lead to underperformance.
B) is probably best ,but considering how well trained models are on actual systemctl status output, I'm a bit skeptical about structured objects at all as applied to this tool. (It's also possible to have a tool return structured content and freeform content ... but I don't think that really helps things here.)
Should we bother returning structured content for this tool then? Maybe the best thing for this tool in particular is to return the true expected output of |
@samdoran - what do you think? |
|
There are a couple of main things we want to accomplish:
These tools currently return nicely formatted text for display on a screen, but that text is never seen by a human. It may be helpful to send that formatted text to an LLM, but I doubt these specific formatting functions are swaying the accuracy of the LLM response and are therefore unnecessary. One advantage of using Pydantic models for return types is that it provides validation of the returned data as well as control over how fields are serialized to JSON. For these particular tools, I don't think we need that capability since the output is mostly lines of text. It may be the case that using Pydantic models for the return type, which is used to generate the return schema, may help the LLM make better use of the data that are returned, but I don't have a way to prove that. For these tools, it's probably fine to just return the unaltered stdout. |
|
I can see a pattern where it makes sense to return the unaltered stdout from a command, but that makes the most sense when the calling model has decided which command to run. Since our tools are abstracting the commands away from the model, we should be returning the most predictable data structure to a "list_services" function. So by that reasoning, I can see how we should convert these tools. Making up a data structure for the output of |
f256b00 to
3da57ae
Compare
3da57ae to
760e3c4
Compare
760e3c4 to
5096992
Compare
Codecov Report❌ Patch coverage is
Flags with carried forward coverage won't be shown. Click here to find out more.
... and 16 files with indirect coverage changes 🚀 New features to boost your workflow:
|
|
Ok. I patched up the get_service_status tool to return the plain string output of |
So that tests can pass even when sshd.service is not installed.
62ee8df to
df69257
Compare
|
For team members: test commit |
|
For team members: test commit |
Modified the test for nonexistent services to ensure it correctly raises ToolError when no log entries are found.
|
For team members: test commit |
owtaylor
left a comment
There was a problem hiding this comment.
get_service_logs() and get_service_status() look good to me, but I have a bit of a hesititation about list_services.
| sub-state, and description. | ||
|
|
||
| Returns: | ||
| list[dict[str, str]]: A list of dictionaries containing information about each service. |
There was a problem hiding this comment.
So the arguments I know of for doing the structured data conversion are:
A) Not having to maintain fragile formatters. Accomplished, though we could just also pass through the data.
B) Accomodating models that want to "code mode" transform the data programatically. Not accomplished - what is in this list[dict[str, str]]? (Maybe the model would first write a script to extract a few sample lines, but it's annoying to make them do it.)
I think we should do:
class ServiceStatus(BaseModel):
unit: str
load: str
active: str
sub: str
description: str
service_status_list_adapter = TypeAdapter(List[User])
...
return service_status_list_adapter.validate_json(stdout)(systemd documents: "The list of possible LOAD, ACTIVE, and SUB states is not constant and new systemd releases may both add and remove values", so we probably shouldn't try use enums - a competent model will understand these mysterious load/active/sub values in terms of its systemd knowledge)
Refactor service-related tools to return structured data instead of plain text. This includes converting the output of
list_services,get_service_status, andget_service_logsinto JSON. Convertget_service_statusto usesystemctl showinstead of the human-readably focusedsystemctl status. Implement a parser for thesystemctl showcommand to facilitate this structured output.