Skip to content

Commit 9eaa7ca

Browse files
committed
Merge branch 'main' into feat-tool-email
2 parents 37d2b9d + 16307d7 commit 9eaa7ca

23 files changed

+5362
-599
lines changed

examples/openaiserver/README.md

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
# OpenAI Server Example
2+
3+
This example shows how to start the trpc-agent-go **OpenAI-compatible Server** that
4+
implements the OpenAI Chat Completions API standard.
5+
6+
## Prerequisites
7+
8+
- Go 1.21 or later
9+
- OpenAI API key (or compatible API key for the model you're using)
10+
11+
## Running the Server
12+
13+
```bash
14+
# From repository root
15+
cd examples/openaiserver
16+
17+
# Start the server with default settings (model: deepseek-chat, addr: :8080)
18+
go run .
19+
20+
# Start the server on custom port
21+
go run . -addr :9090
22+
23+
# Start the server with different model
24+
go run . -model gpt-4
25+
26+
# Start the server with custom model and port
27+
go run . -model gpt-4 -addr :9090
28+
```
29+
30+
### Command Line Options
31+
32+
- `-model`: Name of the model to use (default: "deepseek-chat")
33+
- `-addr`: Listen address (default: ":8080")
34+
35+
## Testing with curl
36+
37+
### Non-streaming Request
38+
39+
```bash
40+
curl http://localhost:8080/v1/chat/completions \
41+
-H "Content-Type: application/json" \
42+
-d '{
43+
"model": "deepseek-chat",
44+
"messages": [
45+
{"role": "user", "content": "What is 2 + 2?"}
46+
],
47+
"stream": false
48+
}'
49+
```
50+
51+
### Streaming Request
52+
53+
```bash
54+
curl http://localhost:8080/v1/chat/completions \
55+
-H "Content-Type: application/json" \
56+
-d '{
57+
"model": "deepseek-chat",
58+
"messages": [
59+
{"role": "user", "content": "What is 2 + 2?"}
60+
],
61+
"stream": true
62+
}'
63+
```
64+
65+
### Using Tools (Function Calling)
66+
67+
```bash
68+
curl http://localhost:8080/v1/chat/completions \
69+
-H "Content-Type: application/json" \
70+
-d '{
71+
"model": "deepseek-chat",
72+
"messages": [
73+
{"role": "user", "content": "Calculate 15 * 23"}
74+
],
75+
"stream": false
76+
}'
77+
```
78+
79+
## Testing with OpenAI SDK
80+
81+
You can use any OpenAI-compatible client library. Here's an example with Python:
82+
83+
```python
84+
from openai import OpenAI
85+
86+
# Point to your local server
87+
client = OpenAI(
88+
base_url="http://localhost:8080/v1",
89+
api_key="not-needed" # API key is not required for local server
90+
)
91+
92+
# Non-streaming
93+
response = client.chat.completions.create(
94+
model="deepseek-chat",
95+
messages=[
96+
{"role": "user", "content": "What is 2 + 2?"}
97+
]
98+
)
99+
print(response.choices[0].message.content)
100+
101+
# Streaming
102+
stream = client.chat.completions.create(
103+
model="deepseek-chat",
104+
messages=[
105+
{"role": "user", "content": "Tell me a story"}
106+
],
107+
stream=True
108+
)
109+
for chunk in stream:
110+
if chunk.choices[0].delta.content:
111+
print(chunk.choices[0].delta.content, end="", flush=True)
112+
```
113+
114+
## Features
115+
116+
- ✅ OpenAI Chat Completions API compatible
117+
- ✅ Streaming and non-streaming responses
118+
- ✅ Function calling (tools) support
119+
- ✅ Multi-turn conversations
120+
- ✅ Session management
121+
122+
## Available Tools
123+
124+
- **calculator**: Performs basic mathematical operations (add, subtract, multiply, divide)
125+
- **current_time**: Gets the current time and date for a specific timezone
126+
127+
---
128+
129+
Feel free to replace the agent logic in `main.go` or add more tools in `tools.go` as needed.
130+

examples/openaiserver/main.go

Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
//
2+
// Tencent is pleased to support the open source community by making trpc-agent-go available.
3+
//
4+
// Copyright (C) 2025 Tencent. All rights reserved.
5+
//
6+
// trpc-agent-go is licensed under the Apache License Version 2.0.
7+
//
8+
//
9+
10+
// Package main provides a standalone demo showcasing how to wire the
11+
// trpc-agent-go orchestration layer with an LLM agent that exposes two simple tools:
12+
// a calculator and a time query. It starts an HTTP server compatible with OpenAI API
13+
// for manual testing.
14+
//
15+
// This file demonstrates how to set up a simple LLM agent with custom tools
16+
// (calculator and time query) and expose it via an HTTP server compatible with the
17+
// OpenAI Chat Completions API. It is intended for manual testing and as a reference
18+
// for integrating tRPC agent orchestration with OpenAI-compatible clients.
19+
//
20+
// The example covers:
21+
// - Model and tool setup
22+
// - Agent configuration
23+
// - OpenAI-compatible HTTP server integration
24+
//
25+
// Usage:
26+
//
27+
// go run main.go
28+
// go run main.go -model gpt-4 -addr :8080
29+
//
30+
// The server will listen on :8080 by default and use deepseek-chat model.
31+
//
32+
// Author: Tencent, 2025
33+
//
34+
// -----------------------------------------------------------------------------
35+
package main
36+
37+
import (
38+
"flag"
39+
"net/http"
40+
41+
"trpc.group/trpc-go/trpc-agent-go/agent/llmagent"
42+
"trpc.group/trpc-go/trpc-agent-go/log"
43+
"trpc.group/trpc-go/trpc-agent-go/model"
44+
"trpc.group/trpc-go/trpc-agent-go/model/openai"
45+
openaiserver "trpc.group/trpc-go/trpc-agent-go/server/openai"
46+
"trpc.group/trpc-go/trpc-agent-go/tool"
47+
"trpc.group/trpc-go/trpc-agent-go/tool/function"
48+
)
49+
50+
const defaultListenAddr = ":8080"
51+
52+
// main is the entry point of the application.
53+
// It sets up an LLM agent with calculator and time tools,
54+
// and starts an HTTP server for OpenAI API compatibility.
55+
func main() {
56+
// Parse command-line flags for server address and model.
57+
modelName := flag.String("model", "deepseek-chat", "Name of the model to use")
58+
addr := flag.String("addr", defaultListenAddr, "Listen address")
59+
flag.Parse()
60+
61+
// --- Model and tools setup ---
62+
// Create the OpenAI model instance for LLM interactions.
63+
modelInstance := openai.New(*modelName)
64+
65+
// Create calculator tool for mathematical operations.
66+
calculatorTool := function.NewFunctionTool(
67+
calculate,
68+
function.WithName("calculator"),
69+
function.WithDescription(
70+
// Perform basic mathematical calculations (add, subtract, multiply, divide).
71+
"Perform basic mathematical calculations "+
72+
"(add, subtract, multiply, divide)",
73+
),
74+
)
75+
// Create time tool for timezone queries.
76+
timeTool := function.NewFunctionTool(
77+
getCurrentTime,
78+
function.WithName("current_time"),
79+
function.WithDescription(
80+
// Get the current time and date for a specific timezone.
81+
"Get the current time and date for a specific "+
82+
"timezone",
83+
),
84+
)
85+
86+
// Configure generation parameters for the LLM.
87+
genConfig := model.GenerationConfig{
88+
MaxTokens: intPtr(2000),
89+
Temperature: floatPtr(0.7),
90+
Stream: true,
91+
}
92+
93+
// Create the LLM agent with tools and configuration.
94+
agentName := "assistant"
95+
llmAgent := llmagent.New(
96+
agentName,
97+
llmagent.WithModel(modelInstance),
98+
llmagent.WithDescription(
99+
"A helpful AI assistant with calculator and time tools",
100+
),
101+
llmagent.WithInstruction(
102+
"Use tools when appropriate for calculations or time queries. "+
103+
"Be helpful and conversational.",
104+
),
105+
llmagent.WithGenerationConfig(genConfig),
106+
llmagent.WithTools(
107+
[]tool.Tool{calculatorTool, timeTool},
108+
),
109+
)
110+
111+
// Create the OpenAI server.
112+
server, err := openaiserver.New(
113+
openaiserver.WithAgent(llmAgent),
114+
openaiserver.WithBasePath("/v1"),
115+
openaiserver.WithModelName(*modelName),
116+
)
117+
if err != nil {
118+
log.Fatalf("failed to create OpenAI server: %v", err)
119+
}
120+
// Ensure server resources are cleaned up.
121+
defer server.Close()
122+
123+
// Start the HTTP server and handle requests.
124+
log.Infof(
125+
// Log the server listening address, model, and endpoint.
126+
"OpenAI-compatible server listening on %s (model: %s, endpoint: /v1/chat/completions)",
127+
*addr,
128+
*modelName,
129+
)
130+
// Start the HTTP server and handle requests.
131+
// This is a test server, so we don't need to use a more secure server.
132+
//nolint:gosec
133+
if err := http.ListenAndServe(*addr, server.Handler()); err != nil {
134+
log.Fatalf("server error: %v", err)
135+
}
136+
}
137+
138+
// intPtr returns a pointer to the given int value.
139+
func intPtr(i int) *int {
140+
return &i
141+
}
142+
143+
// floatPtr returns a pointer to the given float64 value.
144+
func floatPtr(f float64) *float64 {
145+
return &f
146+
}

examples/openaiserver/tools.go

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
//
2+
// Tencent is pleased to support the open source community by making trpc-agent-go available.
3+
//
4+
// Copyright (C) 2025 Tencent. All rights reserved.
5+
//
6+
// trpc-agent-go is licensed under the Apache License Version 2.0.
7+
//
8+
//
9+
10+
package main
11+
12+
import (
13+
"context"
14+
"strings"
15+
"time"
16+
)
17+
18+
// Constants for supported calculator operations.
19+
const (
20+
opAdd = "add"
21+
opSubtract = "subtract"
22+
opMultiply = "multiply"
23+
opDivide = "divide"
24+
)
25+
26+
// calculatorArgs holds the input for the calculator tool.
27+
type calculatorArgs struct {
28+
Operation string `json:"operation" jsonschema:"description=The operation to perform,enum=add,enum=subtract,enum=multiply,enum=divide,required"`
29+
A float64 `json:"a" jsonschema:"description=First number operand,required"`
30+
B float64 `json:"b" jsonschema:"description=Second number operand,required"`
31+
}
32+
33+
// calculatorResult holds the output for the calculator tool.
34+
type calculatorResult struct {
35+
Operation string `json:"operation"`
36+
A float64 `json:"a"`
37+
B float64 `json:"b"`
38+
Result float64 `json:"result"`
39+
}
40+
41+
// timeArgs holds the input for the time tool.
42+
type timeArgs struct {
43+
Timezone string `json:"timezone" jsonschema:"description=Timezone or leave empty for local,required"`
44+
}
45+
46+
// timeResult holds the output for the time tool.
47+
type timeResult struct {
48+
Timezone string `json:"timezone"`
49+
Time string `json:"time"`
50+
Date string `json:"date"`
51+
Weekday string `json:"weekday"`
52+
}
53+
54+
// Calculator tool implementation.
55+
// calculate performs the requested mathematical operation.
56+
// It supports add, subtract, multiply, and divide operations.
57+
func calculate(ctx context.Context, args calculatorArgs) (calculatorResult, error) {
58+
var result float64
59+
// Select operation based on input.
60+
switch strings.ToLower(args.Operation) {
61+
case opAdd:
62+
result = args.A + args.B
63+
case opSubtract:
64+
result = args.A - args.B
65+
case opMultiply:
66+
result = args.A * args.B
67+
case opDivide:
68+
if args.B != 0 {
69+
result = args.A / args.B
70+
}
71+
}
72+
return calculatorResult{
73+
Operation: args.Operation,
74+
A: args.A,
75+
B: args.B,
76+
Result: result,
77+
}, nil
78+
}
79+
80+
// Time tool implementation.
81+
// getCurrentTime returns the current time for the specified timezone.
82+
// If the timezone is invalid or empty, it defaults to local time.
83+
func getCurrentTime(ctx context.Context, args timeArgs) (timeResult, error) {
84+
loc := time.Local
85+
zone := args.Timezone
86+
// Attempt to load the specified timezone.
87+
if zone != "" {
88+
var err error
89+
loc, err = time.LoadLocation(zone)
90+
if err != nil {
91+
loc = time.Local
92+
}
93+
}
94+
now := time.Now().In(loc)
95+
return timeResult{
96+
Timezone: loc.String(),
97+
Time: now.Format("15:04:05"),
98+
Date: now.Format("2006-01-02"),
99+
Weekday: now.Weekday().String(),
100+
}, nil
101+
}
102+
103+
// This example demonstrates how to integrate tRPC agent orchestration
104+
// with LLM-based tools, providing a simple HTTP server compatible with
105+
// OpenAI API for manual testing. It is intended as a reference for
106+
// developers looking to build custom LLM agents with tool support in Go.
107+
//
108+
// The calculator tool supports basic arithmetic operations, while the
109+
// time tool provides current time information for a given timezone.
110+
//
111+
// The code is structured for clarity and ease of extension.

knowledge/default_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -810,7 +810,7 @@ func (m *mockQueryEnhancer) EnhanceQuery(ctx context.Context, req *query.Request
810810

811811
type mockReranker struct{}
812812

813-
func (m *mockReranker) Rerank(ctx context.Context, results []*reranker.Result) ([]*reranker.Result, error) {
813+
func (m *mockReranker) Rerank(ctx context.Context, query *reranker.Query, results []*reranker.Result) ([]*reranker.Result, error) {
814814
return results, nil
815815
}
816816

0 commit comments

Comments
 (0)