-
Couldn't load subscription status.
- Fork 38
{server/agui, examples, docs}: support agui #379
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
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #379 +/- ##
====================================================
+ Coverage 58.42422% 74.94735% +16.52313%
====================================================
Files 97 142 +45
Lines 12286 21367 +9081
====================================================
+ Hits 7178 16014 +8836
+ Misses 4608 4457 -151
- Partials 500 896 +396
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
| @@ -0,0 +1,37 @@ | |||
| module trpc.group/trpc-go/trpc-agent-go/server/agui | |||
|
|
|||
| go 1.24.4 | |||
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.
注意下go 版本
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.
AGUI GO SDK 使用了 go1.24.4,因此给 agui 打了个 gomod
https://github.com/ag-ui-protocol/ag-ui/pull/339/files#diff-5b94013923af92d1340c95388546e1783d73fdc13ca8d17b6f5e7e05e0d2b0ba
server/agui/runner/runner.go
Outdated
| } | ||
|
|
||
| // New wraps a trpc-agent-go runner with AG-UI specific translation logic. | ||
| func New(r trunner.Runner, opt ...Option) Runner { |
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.
这个还要单独封装一个runner吗,如果用户自己创建runner,并添加memory和session,这个和用户的不是有冲突?
是不是反过来,和memory,session一样,通过runner传入
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.
这里封装的 AGUI Runner 不会和用户自定义的 Runner 产生冲突,原因:
- New 接收用户自定义的 Runner,memory/session 逻辑由用户在自己的 Runner 中实现,AG-UI Runner 相当于 Wrap 了自定义 Runner,只做事件翻译,不会覆盖 memory/session 逻辑。
- AGUI Runner 与 Runner 的 Option 类型不互通,不支持传入 memory/session
之所以抽象出 AGUI Runner 接口,是为了让用户根据需要换成本地实现(例如 mock AGUI 事件输出)。
examples/agui/client/bubbletea/ui.go
Outdated
| "github.com/charmbracelet/bubbles/spinner" | ||
| "github.com/charmbracelet/bubbles/textinput" | ||
| "github.com/charmbracelet/bubbles/viewport" | ||
| tea "github.com/charmbracelet/bubbletea" |
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.
这个是什么,会不会有点不好理解
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.
bubbletea是 CLI 开发框架,这个 example 演示了 client 如何自己解析 AGUI 协议。
另外,还使用 CopilotKit 开发了一个 web ui 作为 client,在另一个 example。
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.
UPDATE:移除了 bubbletea,提供了最小样例
examples/agui/server/default/main.go
Outdated
| if err != nil { | ||
| log.Fatalf("failed to create AG-UI server: %v", err) | ||
| } | ||
| if err := server.Serve(context.Background()); err != nil { |
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.
ip port要如何设置、
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.
通过 WithAddress 和 WithPath 设置,在 example 中显式写出来了
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.
UPDATE
address(ipport)在http.ListenAndServe(*address, server.Handler())中指定,见最新的 server example
server/agui/event/event.go
Outdated
| } | ||
|
|
||
| // NewBridge creates a new event bridge. | ||
| func NewBridge(threadID, runID string) Bridge { |
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.
Bridge 这些相关的看上去可以放到 internal
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.
agui 有一种 custom event 类型,抽象出 Bridge interface 可以让用户自行处理自定义 event 的转换
server/agui/agui.go
Outdated
| } | ||
|
|
||
| // New creates a AG-UI server instance. | ||
| func New(agent agent.Agent, opt ...Option) (*Server, 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.
除了这个 agui.New 之外,service package 和 runner package 这些是不是都可以放到 internal?
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.
agui 协议没有规定 transport,框架提供了 sse 实现,也可以有 websocket/私有协议 实现,所以抽象出 service interface,支持协议扩展。
server/agui/options.go
Outdated
| } | ||
|
|
||
| // WithSessionService sets the session service. | ||
| func WithSessionService(svc session.Service) Option { |
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.
这里不太好,trpc-agent-go 的 runner 还有其他 option,不只有 session service 的 option,你要在这里一一复刻一遍吗?
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.
去除WithSessionService了,使用WithRunnerOptions统一设置 runner 的 option
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.
为什么不考虑在原来的runner里面去传入ag-ui相关的东西?
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.
- AGUI要启动一个服务,如果通过通过 runner 传递的话,拿不到 HTTP handler
- AGUI 与 A2A/DebugServer 类似,都是向外提供服务,放在 server 下面,使用方法应该相近
server/agui/service/sse/sse.go
Outdated
| } | ||
|
|
||
| // Serve starts the SSE service and listens on the address. | ||
| func (s *sse) Serve(ctx context.Context) 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.
serve 这里可以考虑监听 ctx.Done 来对 server 做 shutdown 操作
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.
否则传入的 ctx 就没有什么用了
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.
刚才更新了,去除了 Serve/Close 方法,改用 Handler 方法,能够让用户显式与 trpc 结合
examples/agui/server/default/main.go
Outdated
| llmagent.WithGenerationConfig(generationConfig), | ||
| llmagent.WithInstruction("You are a helpful assistant."), | ||
| ) | ||
| server, err := agui.New(agent, agui.WithPath(*path)) |
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.
除了 example 这里用户会使用到的导出方法以外,其他的都要考虑下是否可以放到 internal 中
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.
导出符号整理如下:
- package agui
- DefaultNewService 变量:service 创建的工厂函数,用于匿名导入覆盖;
- package adapter
- RunAgentInput 结构体:AG-UI 协议的请求包,自定义 UserIDResolver/TranslatorFactory 时需要用到
- package runner
- Options 结构体、NewOptions 工厂函数、WithUserIDResolver、WithTranslatorFactory Option。
- package service
- Service 接口:用于自定义通信协议;
- Options 结构体、WithPath Option
- package sse
- New 方法:用于创建 sse 服务
- package translate
- Translator 接口与 New 构造器:用于自定义翻译器。
| o(&opts) | ||
| } | ||
| s := &sse{ | ||
| path: opts.Path, |
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.
opts.Path 需要判空兜底默认 /,否则 HandleFunc 那里会 panic
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.
done,默认使用"/"
| } | ||
|
|
||
| // handle handles an AG-UI run request. | ||
| func (s *sse) handle(w http.ResponseWriter, r *http.Request) { |
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.
需要过滤下 http method,只支持 GET POST
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.
以及 OPTIONS(给 CORS 用)
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.
done
examples/agui/README.md
Outdated
| pnpm dev | ||
| ``` | ||
|
|
||
| 3. Ask a question such as `Calculate 2*(10+11)` and watch the live event stream in the terminal. A full transcript example is documented in [`client/copilotkit/README.md`](client/bubblecopilotkittea/README.md). |
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.
这个路径和实际的不符
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.
fix
| } | ||
|
|
||
| // New creates a new event translator. | ||
| func New(threadID, runID string) Translator { |
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.
threadID 指的是啥,go 又没thread
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.
RunAgentInput 是 AGUI协议规定的请求包格式,这些字段都是 AGUI 协议规定的。
其中,ThreadID和RunID分别对应了框架的SessionID和InvcationID
| // RunAgentInput represents the parameters for an AG-UI run request. | ||
| type RunAgentInput struct { | ||
| // ThreadID is the ID of the conversation thread, which is the session ID. | ||
| ThreadID string `json:"threadId"` |
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.
为啥不叫session id
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.
RunAgentInput 是 AGUI协议规定的请求包格式,这些字段都是 AGUI 协议规定的。
其中,ThreadID和RunID分别对应了框架的SessionID和InvcationID
| llmagent.WithModel(modelInstance), | ||
| llmagent.WithGenerationConfig(generationConfig), | ||
| llmagent.WithInstruction("You are a helpful assistant."), | ||
| ) |
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.
这里有个问题,如果要传入session,或者memory,要怎么做呢?
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.
通过 WithRunnerOptions 传入,例如:
// 创建 AG-UI 服务
server, err := agui.New(
agent,
agui.WithPath("/agui"), // 指定 HTTP 路由
agui.WithRunnerOptions(runner.WithSessionService(sessionService)), // 注入 Session Service
)文档新增了 Runner 示例
docs/mkdocs/zh/agui.md
Outdated
| // 创建 Agent | ||
| agent := newAgent() | ||
| // 创建 AG-UI 服务,指定 HTTP 路由 | ||
| server, err := agui.New(agent, agui.WithPath("/agui")) |
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.
debugserver:https://github.com/trpc-group/trpc-agent-go/blob/main/server/debug/server.go#L47 New的是server,传入了runner
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.
agui.New 改成了传入 runner
| ) | ||
|
|
||
| // options holds the options for the AG-UI server. | ||
| type options struct { |
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.
这些还需要保留吗
| // | ||
| // | ||
|
|
||
| package runner |
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.
这个还要保留吗
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.
需要的,用户自定义事件需要用到 option,所以要导出。倘若把 Runner option 放到 agui option中,则会有循环依赖的问题。
暂时没有自定义 Runner 实现的需求,所以 Runner 接口定义放到 internal/runner 了。
No description provided.