-
-
Notifications
You must be signed in to change notification settings - Fork 220
feat: add events #413
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
base: main
Are you sure you want to change the base?
feat: add events #413
Conversation
|
What do you think of main...feat/evented-telemetry |
|
@sixlive sorry for the long comment 😃 TLDR I like this solution better for several reason. List of reasons: 1. Keep firing events and telemetry separateOnce you have events in place telemetry can be a separate package, so users can decide what to take from events and how to implement telemetry. 2. Less verbose implementationEverything about tracing is implemented in $spanId = Str::uuid()->toString();
$parentSpanId = Context::get('prism.telemetry.current_span_id');
$rootSpanId = Context::get('prism.telemetry.root_span_id') ?? $spanId;
Context::add('prism.telemetry.current_span_id', $spanId);
Context::add('prism.telemetry.parent_span_id', $parentSpanId);
Event::dispatch(new ToolCallStarted(...));this Trace::start('tool', () => event(new ToolCallStarted(...));3. NestingI like to keep each call separate, in your implementation, in case tools are used, the first 4. Level of nestingYou are manually managing only two levels
5. DataI tried to collect all important data, and some things still need to be adjusted, to make it available in the fired events so that it's up to the Listener to decide what to use. |
Preview deployments for prism ⚡️
Commit: Deployment ID: Static site name: |
|
I have been following this for a while, and yeah, my primary case would be tracking costs and responses as well(as would most AI users do id assume and there is big lack of such functionality in php land ), so I also prefer @MrCrayon approach |
|
@sixlive let me know what you think about this PR. Tests are failing for Laravel 11 lowest because they are running on |
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 dont know if I like the configuration method approach for this. I think I'd rather like to just return a base client with the middleware defined and then let the providers can customize the client as needed.
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 submitted a PR #427 just for the client trait using a baseClient where we can add middlewares and the rest of configuration happens in provider client. Is that what you meant?
I separated in another PR because I refactored exceptions that were scattered in all handlers and that added a lot of noise that I'd like to keep separate from this PR.
// Provider class
protected function client(array $options = [], array $retry = [], ?string $baseUrl = null): PendingRequest
{
return $this->baseClient()
// configuration for that provider
->baseUrl($baseUrl ?? $this->url);
}|
Yeah man, I think I dig this |
I think we can just bump the minimum version in |
|
@sixlive is it ok if I rebase? |
|
Yeah, go for it |
1e5c764 to
73d90dd
Compare
- Add Trace class that uses Laravel Context to keep track of operations stack - Add events - Add middlewares to trace http request and response. - Streams are traced with a `StreamWrapper` to keep stream intact. - Tracing of all not nested Prism operations is done in shared `PendingRequest` classes. - Tracing of tool calls is done in `CallsTools` if called or where tools are called. - Removed "'Maximum tool call" Exception in Anthropic Stream Handler and implemented `shouldContinue` check that does not raise an exception. - Added `$step` property in Anthropic Stream Handler so that we are not passing `$depth` everywhere. - Remove `isToolUseFinish` in `handleMessageStop`for ANthropic Stream Handler - Added `Content-Type` headers for Gemini and OpenAI stream tests, `Content-type` is used in client middleware to recognize if it's a streamed response or normal.
v11.31 minumum is needed to use Context::popHidden()
89678fd to
7fe99bf
Compare
|
Thanks for the work on this! 🙌 |
I'd be happy to assist as well. Would be a major feature, perhaps appropriate for a v1 release 👀 |
|
Would love to see this added. Until then is there any way to know what's happening in the tool call loop? In the example below I'd like some observability into what's being search, what the results are, what the LLM thought about the results, whether a new query is being submitted, etc. I don't need streaming, but I also don't want to wait for the entire task to complete before getting an update. |
Description
This PR introduces the following events:
Each event is fired with some data in relative to the operation, all events have a
traceproperty composed by:[ 'traceId' => Str::uuid()->toString(), 'parentTraceId' => self::getParentId(), 'traceName' => $operation, 'startTime' => microtime(true), 'endTime' => null, ];traceIdis maintained across operation and passed as parent for nested operations, as example:traceId1parentTraceId1,traceId2parentTraceId1,traceId2traceId1Implementation
This PR seats on top of #386.
Contextis used throughTraceclass.StreamWrapperis used.PendingRequestclasses, except when tool are invoked.PrismRequestCompletedis fired inside Text/Stream provider Handler class andPrismRequestStartedis fired if another operation starts based on max steps allowed.CallsToolsif called or directly in Text/Stream provider Handler class if it's managed there.Anthropic
I made some specific changes in Anthropic handler:
shouldContinuecheck that does not raise an exception.$stepproperty in Stream Handler so that we are not passing$deptheverywhere.isToolUseFinishinhandleMessageStopfor Stream Handler.Other provideres
Currently all other providers are tracked only in
PendingRequest, if tools are used for this providers they are going to be nested in the current PrismRequest not separate.This is just because I used Anthropic as test, there should be no problem changing all other Text/Stream Handlers.
Tests
Added
Content-Typeheaders for Gemini and OpenAI stream tests,Content-typeis used in client middleware to recognize if it's a streamed response or normal.Use
A Listener should be implemented like:
A trace that includes all run can be created before calling prism like:
TODO