-
Notifications
You must be signed in to change notification settings - Fork 4
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
Add support for Assistant APIs #464
base: main
Are you sure you want to change the base?
Conversation
Thanks Paul! In general this looks good, our main concern is how to handle LLM providers which don't support these APIs (e.g. if the user has configured a custom OpenAI-compatible LLM backend other than OpenAI). We may need to add something to the health check response which checks whether these things exist, so that clients can degrade gracefully in those cases. |
I see @sd2k, that makes sense. Maybe I could extend the health API to add an grafana-llm-app/packages/grafana-llm-frontend/src/types.ts Lines 6 to 10 in d3ac328
|
Yep sounds like a plan. It could maybe go inside the |
Got it - thanks, will do 😄. |
fc3a43d
to
39ce3c2
Compare
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 looking good to me, thanks Paul! I've added a few suggestions inline but would like to get a second opinion on a few things, mostly:
- the go.mod change (I think this should at least be in a separate PR, and need to learn more about it first)
- the now-large
OpenAI
interface inllmclient
; perhaps it's worth splitting it
@csmarchbanks could you take a look at this when you have time?
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.
Removing this completely seems a bit scary, my knowledge of Go dependencies isn't strong enough to know how it would handle a breaking change (e.g. v2) in sashabaranov/go-openai though 🤔
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.
Perhaps we should consider this in a separate PR, unless it's really needed here?
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.
Yeah, what's the reason for this removal? I like specifying that we depend on >=1.15.3, <2.0.0. Are you running into import issues somewhere?
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.
@sd2k @csmarchbanks I got confused about why there were two go.mod
files - I didn't quite realise the client was a separate build product! I'll revert, sorry for the confusion.
// CreateAssistant creates an assistant using the given request. | ||
CreateAssistant(ctx context.Context, req AssistantRequest) (openai.Assistant, error) | ||
// RetrieveAssistant retrieves an assistant by ID. | ||
RetrieveAssistant(ctx context.Context, assistantID string) (openai.Assistant, error) | ||
// ListAssistants lists assistants. | ||
ListAssistants(ctx context.Context, limit *int, order *string, after *string, before *string) (openai.AssistantsList, error) | ||
// DeleteAssistant deletes an assistant by ID. | ||
DeleteAssistant(ctx context.Context, assistantID string) (openai.AssistantDeleteResponse, error) | ||
// CreateThread creates a new thread. | ||
CreateThread(ctx context.Context, req openai.ThreadRequest) (openai.Thread, error) | ||
// RetrieveThread retrieves a thread by ID. | ||
RetrieveThread(ctx context.Context, threadID string) (openai.Thread, error) | ||
// DeleteThread deletes a thread by ID. | ||
DeleteThread(ctx context.Context, threadID string) (openai.ThreadDeleteResponse, error) | ||
// CreateMessage creates a new message in a thread. | ||
CreateMessage(ctx context.Context, threadID string, request openai.MessageRequest) (msg openai.Message, err error) | ||
// ListMessages lists messages in a thread. | ||
ListMessages(ctx context.Context, threadID string, limit *int, order *string, after *string, before *string, runID *string) (openai.MessagesList, error) | ||
// RetrieveMessage retrieves a message in a thread. | ||
RetrieveMessage(ctx context.Context, threadID string, messageID string) (msg openai.Message, err error) | ||
// DeleteMessage deletes a message in a thread. | ||
DeleteMessage(ctx context.Context, threadID string, messageID string) (msg openai.MessageDeletionStatus, err error) | ||
// CreateRun creates a new run in a thread. | ||
CreateRun(ctx context.Context, threadID string, request openai.RunRequest) (run openai.Run, err error) | ||
// RetrieveRun retrieves a run in a thread. | ||
RetrieveRun(ctx context.Context, threadID string, runID string) (run openai.Run, err error) | ||
// CancelRun cancels a run in a thread. | ||
CancelRun(ctx context.Context, threadID string, runID string) (run openai.Run, err error) | ||
// SubmitToolOutputs submits tool outputs for a run in a thread. | ||
SubmitToolOutputs(ctx context.Context, threadID string, runID string, request openai.SubmitToolOutputsRequest) (response openai.Run, err error) |
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.
A niggling part of my brain thinks this should be a separate OpenAIAssistant
interface to avoid the OpenAI
interface becoming too big (and make it easier to mock for users in tests), particularly if users are importing and using this in their code already. WDYT?
I guess people would need to type switch though so maybe it's not worth it?
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.
I also think having a second interface could be nice. It would also allow us to check for features based on if the interface is implemented for a connection or not (in the case we add more first class implementations of this interface).
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.
Good point, will add this interface.
@@ -86,6 +98,7 @@ func (a *App) openAIHealth(ctx context.Context, req *backend.CheckHealthRequest) | |||
OK: true, | |||
Configured: a.settings.OpenAI.Configured(), | |||
Models: map[Model]openAIModelHealth{}, | |||
Assistant: openAIModelHealth{OK: false, Error: "Assistant not present"}, |
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.
Assistant: openAIModelHealth{OK: false, Error: "Assistant not present"}, | |
Assistant: openAIModelHealth{OK: false, Error: "Assistant not available"}, |
I kinda like available
more but this is very much personal preference!
if err == nil { | ||
d.Assistant.OK = true | ||
d.Assistant.Error = "" | ||
} |
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.
Perhaps we should append the error to the d.Assistant.Error
if it's non-nil, to make it easier for users to debug why the assistant isn't available.
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.
Good point, will do.
@@ -133,4 +133,6 @@ type LLMProvider interface { | |||
// ChatCompletionStream provides text completion in a chat-like interface with | |||
// tokens being sent as they are ready. | |||
ChatCompletionStream(context.Context, ChatCompletionRequest) (<-chan ChatCompletionStreamResponse, error) | |||
// ListAssistants lists assistants. |
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.
// ListAssistants lists assistants. | |
// ListAssistants lists assistants. | |
// | |
// This is used by the health check to determine whether the configured provider | |
// supports assistant APIs. |
@@ -128,6 +137,8 @@ function ShowOpenAIHealth({ openAI }: { openAI: OpenAIHealthDetails | boolean }) | |||
</li> | |||
))} | |||
</div> | |||
<b>Assistant: </b> | |||
{openAI.assistant.ok ? 'OK' : `Error: ${openAI.assistant.error}`} |
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.
{openAI.assistant.ok ? 'OK' : `Error: ${openAI.assistant.error}`} | |
{openAI.assistant.ok ? 'OK' : `Error: ${openAI.assistant.error}. The configured OpenAI provider may not offer assistants APIs.`} |
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.
Agree, this is a more precise description.
@@ -21,6 +21,8 @@ export interface OpenAIHealthDetails { | |||
// The health check attempts to call the OpenAI API with each | |||
// of a few models and records the result of each call here. | |||
models?: Record<string, OpenAIModelHealthDetails>; | |||
// Health details for the OpenAI assistant model. |
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.
// Health details for the OpenAI assistant model. | |
// Health details for the OpenAI assistant APIs. |
Relates to: #421
It would be great if the LLM plugin could support some Assistant features, so I've raised this PR to add support for
Assistant
s,Thread
s,Run
s andMessage
s.I've removed the
go.mod
file from thellmclient
so we support the latest version of http://github.com/sashabaranov/go-openai.Any feedback welcome as it is my first PR! 🙏
Health Check Scenarios
As previously - failure