Skip to content

Commit 988405e

Browse files
authored
[ai] Add GenerateTextStr convenience function, add examples, and support value types (#508)
## Summary - Add GenerateTextStr function for simple string-based prompts - Support both pointer and value types for all message types (SystemMessage, UserMessage, AssistantMessage, ToolMessage) and corresponding content blocks. - Add comprehensive test coverage for value type messages - Update README.md example to use new GenerateTextStr function - Add examples directory with basic usage ## How was it tested? Ran tests, ran example. ## Community Contribution License All community contributions in this pull request are licensed to the project maintainers under the terms of the [Apache 2 License](https://www.apache.org/licenses/LICENSE-2.0). By creating this pull request I represent that I have the right to license the contributions to the project maintainers under the Apache 2 License as stated in the [Community Contribution License](https://github.com/jetify-com/opensource/blob/main/CONTRIBUTING.md#community-contribution-license).
1 parent d7cd2e9 commit 988405e

15 files changed

Lines changed: 797 additions & 98 deletions

File tree

aisdk/ai/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ func main() {
9494
model := openai.NewLanguageModel("gpt-4o")
9595

9696
// Generate text
97-
response, err := ai.GenerateText(
97+
response, err := ai.GenerateTextStr(
9898
context.Background(),
9999
"Explain quantum computing in simple terms",
100100
ai.WithModel(model),
@@ -104,7 +104,7 @@ func main() {
104104
log.Fatal(err)
105105
}
106106

107-
fmt.Println(response.Text)
107+
// Do whatever you want with the response...
108108
}
109109
```
110110

aisdk/ai/ai.go

Lines changed: 39 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -6,35 +6,58 @@ import (
66
"go.jetify.com/ai/api"
77
)
88

9-
// GenerateText generates a text response for a given prompt using a language model.
9+
// GenerateText uses a language model to generate a text response from a given prompt.
10+
//
1011
// This function does not stream its output.
1112
//
1213
// It returns a [api.Response] containing the generated text, the results of
1314
// any tool calls, and additional information.
1415
//
15-
// It supports either a string argument, which will be converted to a
16-
// [api.UserMessage] with
17-
//
18-
// GenerateText(ctx, "Hello, world!")
19-
//
20-
// Or a series of [api.Message] arguments:
16+
// A prompt is a sequence of [api.Message]s:
2117
//
22-
// GenerateText(ctx,
23-
// UserMessage("Show me a picture of a cat"),
24-
// AssistantMessage(
25-
// "Here is a picture of a cat",
26-
// ImageBlock{URL: "https://example.com/cat.png"},
27-
// ),
28-
// )
18+
// GenerateText(ctx, []api.Message{
19+
// &api.UserMessage{
20+
// Content: []api.ContentBlock{
21+
// &api.TextBlock{Text: "Show me a picture of a cat"},
22+
// },
23+
// },
24+
// &api.AssistantMessage{
25+
// Content: []api.ContentBlock{
26+
// &api.TextBlock{Text: "Here is a picture of a cat"},
27+
// &api.ImageBlock{URL: "https://example.com/cat.png"},
28+
// },
29+
// },
30+
// })
2931
//
30-
// The last argument can optionally be a series of [api.CallOption] arguments:
32+
// The last argument can optionally be a series of [GenerateOption] arguments:
3133
//
32-
// GenerateText(ctx, "Hello, world!", WithMaxTokens(100))
34+
// GenerateText(ctx, messages, WithMaxTokens(100))
3335
func GenerateText(ctx context.Context, prompt []api.Message, opts ...GenerateOption) (api.Response, error) {
3436
config := buildGenerateConfig(opts)
3537
return generate(ctx, prompt, config)
3638
}
3739

40+
// GenerateTextStr uses a language model to generate a text response from a given string prompt.
41+
//
42+
// It is a convenience wrapper around GenerateText for simple string-based prompts.
43+
//
44+
// Example usage:
45+
//
46+
// GenerateTextStr(ctx, "Write a brief summary of the benefits of renewable energy")
47+
//
48+
// The function can optionally take [GenerateOption] arguments:
49+
//
50+
// GenerateTextStr(ctx, "Explain the key differences between REST and GraphQL APIs", WithMaxTokens(500))
51+
//
52+
// The string prompt is automatically converted to a [api.UserMessage] before
53+
// being passed to GenerateText.
54+
func GenerateTextStr(ctx context.Context, prompt string, opts ...GenerateOption) (api.Response, error) {
55+
msg := api.UserMessage{
56+
Content: []api.ContentBlock{api.TextBlock{Text: prompt}},
57+
}
58+
return GenerateText(ctx, []api.Message{msg}, opts...)
59+
}
60+
3861
func generate(ctx context.Context, prompt []api.Message, opts GenerateOptions) (api.Response, error) {
3962
return opts.Model.Generate(ctx, prompt, opts.CallOptions)
4063
}

aisdk/ai/api/llm_call_options.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ type CallOptions struct {
1717

1818
// StopSequences specifies sequences that will stop generation when produced.
1919
// Providers may have limits on the number of stop sequences.
20-
StopSequences []string `json:"stop_sequences,omitzero"`
20+
StopSequences []string `json:"stop_sequences,omitempty"`
2121

2222
// TopP controls nucleus sampling.
2323
// It is recommended to set either Temperature or TopP, but not both.
@@ -45,15 +45,15 @@ type CallOptions struct {
4545
Seed int `json:"seed,omitzero"`
4646

4747
// Tools that are available for the model to use.
48-
Tools []ToolDefinition `json:"tools,omitzero"`
48+
Tools []ToolDefinition `json:"tools,omitempty"`
4949

5050
// ToolChoice specifies how the model should select which tool to use.
5151
// Defaults to 'auto'.
5252
ToolChoice *ToolChoice `json:"tool_choice,omitzero"`
5353

5454
// Headers specifies additional HTTP headers to send with the request.
5555
// Only applicable for HTTP-based providers.
56-
Headers map[string]string `json:"headers,omitzero"`
56+
Headers map[string]string `json:"headers,omitempty"`
5757

5858
// ProviderMetadata contains additional provider-specific metadata.
5959
// The metadata is passed through to the provider from the AI SDK and enables

aisdk/ai/api/llm_language_model.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ type Response struct {
8181

8282
// Warnings is a list of warnings that occurred during the call,
8383
// e.g. unsupported settings.
84-
Warnings []CallWarning `json:"warnings,omitzero"`
84+
Warnings []CallWarning `json:"warnings,omitempty"`
8585
}
8686

8787
func (r Response) GetProviderMetadata() *ProviderMetadata { return r.ProviderMetadata }
@@ -136,7 +136,7 @@ func (u Usage) IsZero() bool {
136136
// RequestInfo contains optional request information for telemetry.
137137
type RequestInfo struct {
138138
// Body is the raw HTTP body that was sent to the provider
139-
Body []byte `json:"body,omitzero"`
139+
Body []byte `json:"body,omitempty"`
140140
}
141141

142142
// ResponseInfo contains optional response information for telemetry.
@@ -155,7 +155,7 @@ type ResponseInfo struct {
155155

156156
// Body is the raw HTTP body that was returned by the provider.
157157
// Not provided for streaming responses.
158-
Body []byte `json:"body,omitzero"`
158+
Body []byte `json:"body,omitempty"`
159159

160160
// Status is a status code and message. e.g. "200 OK"
161161
Status string `json:"status,omitzero"`

aisdk/ai/api/llm_prompt.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,7 @@ type ImageBlock struct {
226226
// Data contains the image data as raw bytes.
227227
// If this is set, also set the MimeType so that the AI SDK knows
228228
// how to interpret the data.
229-
Data []byte `json:"data,omitzero"`
229+
Data []byte `json:"data,omitempty"`
230230

231231
// MediaType is the IANA media type (mime type) of the image
232232
MediaType string `json:"media_type,omitzero"`
@@ -270,7 +270,7 @@ type FileBlock struct {
270270
// Data contains the file data as raw bytes.
271271
// If this is set, also set the MimeType so that the AI SDK knows
272272
// how to interpret the data.
273-
Data []byte `json:"data,omitzero"`
273+
Data []byte `json:"data,omitempty"`
274274

275275
// MediaType is the IANA media type (mime type) of the file.
276276
// It can support wildcards, e.g. `image/*` (in which case the provider needs to take appropriate action).
@@ -349,7 +349,7 @@ type ToolResultBlock struct {
349349
// This enables advanced tool results including images.
350350
// When this is used, the Result field should be ignored
351351
// (if the provider supports content).
352-
Content []ContentBlock `json:"content,omitzero"`
352+
Content []ContentBlock `json:"content,omitempty"`
353353

354354
// ProviderMetadata contains additional provider-specific metadata.
355355
// They are passed through to the provider from the AI SDK and enable

aisdk/ai/examples/README.md

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
# AI SDK Examples
2+
3+
This directory contains practical examples showing how to use the AI SDK for Go in real applications.
4+
5+
## Prerequisites
6+
7+
Set your API keys as environment variables:
8+
9+
```bash
10+
export OPENAI_API_KEY="your-openai-key-here"
11+
export ANTHROPIC_API_KEY="your-anthropic-key-here"
12+
```
13+
14+
Get your API keys from:
15+
- **OpenAI**: [platform.openai.com/api-keys](https://platform.openai.com/api-keys)
16+
- **Anthropic**: [console.anthropic.com](https://console.anthropic.com/)
17+
18+
## Examples
19+
20+
| Example | Description |
21+
|---------|-------------|
22+
| [**simple-text**](basic/simple-text/) | Generate text from a simple string prompt |
23+
24+
### More Examples Coming Soon
25+
26+
- **Conversation** - Multi-message conversations with context
27+
- **Streaming** - Stream responses in real-time
28+
- **Multi-modal** - Working with images and files
29+
- **Tools** - Function calling and tool usage
30+
- **Advanced** - Production patterns and error handling
31+
- **Real-world** - Complete application examples
32+
33+
34+
## How to Run
35+
36+
Each example is a standalone Go program:
37+
38+
```bash
39+
cd basic/simple-text
40+
go run main.go
41+
```
42+
43+
## Need Help?
44+
45+
- [API Documentation](https://pkg.go.dev/go.jetify.com/ai)
46+
- [Discord Community](https://discord.gg/jetify)
47+
- [GitHub Issues](https://github.com/jetify-com/ai/issues)
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
package main
2+
3+
import (
4+
"context"
5+
"log"
6+
7+
"github.com/k0kubun/pp/v3"
8+
"go.jetify.com/ai"
9+
"go.jetify.com/ai/api"
10+
"go.jetify.com/ai/provider/openai"
11+
)
12+
13+
func example() error {
14+
// Create a model
15+
model := openai.NewLanguageModel("gpt-4o-mini")
16+
17+
// Generate text
18+
response, err := ai.GenerateTextStr(
19+
context.Background(),
20+
"Explain what artificial intelligence is in simple terms",
21+
ai.WithModel(model),
22+
ai.WithMaxOutputTokens(100),
23+
)
24+
if err != nil {
25+
return err
26+
}
27+
28+
// Print the response:
29+
printResponse(response)
30+
31+
return nil
32+
}
33+
34+
func printResponse(response api.Response) {
35+
response.ProviderMetadata = nil
36+
response.Warnings = nil
37+
printer := pp.New()
38+
printer.SetOmitEmpty(true)
39+
printer.Print(response)
40+
}
41+
42+
func main() {
43+
if err := example(); err != nil {
44+
log.Fatal(err)
45+
}
46+
}

aisdk/ai/go.mod

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ go 1.24.0
44

55
require (
66
github.com/anthropics/anthropic-sdk-go v0.2.0-alpha.13
7+
github.com/k0kubun/pp/v3 v3.4.1
78
github.com/openai/openai-go v1.0.0
89
github.com/sashabaranov/go-openai v1.40.0
910
github.com/stretchr/testify v1.10.0
@@ -14,11 +15,15 @@ require (
1415
require (
1516
github.com/davecgh/go-spew v1.1.1 // indirect
1617
github.com/kr/text v0.2.0 // indirect
18+
github.com/mattn/go-colorable v0.1.14 // indirect
19+
github.com/mattn/go-isatty v0.0.20 // indirect
1720
github.com/pmezard/go-difflib v1.0.0 // indirect
1821
github.com/tidwall/gjson v1.14.4 // indirect
1922
github.com/tidwall/match v1.1.1 // indirect
2023
github.com/tidwall/pretty v1.2.1 // indirect
2124
github.com/tidwall/sjson v1.2.5 // indirect
25+
golang.org/x/sys v0.31.0 // indirect
26+
golang.org/x/text v0.23.0 // indirect
2227
gopkg.in/dnaeon/go-vcr.v4 v4.0.2 // indirect
2328
gopkg.in/yaml.v3 v3.0.1 // indirect
2429
)

aisdk/ai/go.sum

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,16 @@ github.com/anthropics/anthropic-sdk-go v0.2.0-alpha.13/go.mod h1:GJxtdOs9K4neo8G
33
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
44
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
55
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
6+
github.com/k0kubun/pp/v3 v3.4.1 h1:1WdFZDRRqe8UsR61N/2RoOZ3ziTEqgTPVqKrHeb779Y=
7+
github.com/k0kubun/pp/v3 v3.4.1/go.mod h1:+SiNiqKnBfw1Nkj82Lh5bIeKQOAkPy6Xw9CAZUZ8npI=
68
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
79
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
810
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
911
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
12+
github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE=
13+
github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
14+
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
15+
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
1016
github.com/openai/openai-go v1.0.0 h1:KtP+VfrgzX9dHwHrLwHeyWmS0jjm16N+753Vi7OwEYg=
1117
github.com/openai/openai-go v1.0.0/go.mod h1:g461MYGXEXBVdV5SaR/5tNzNbSfwTBBefwc+LlDCK0Y=
1218
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
@@ -31,6 +37,11 @@ go.jetify.com/pkg v0.0.0-20250602221042-f9c387a74b34 h1:moNpfamWyihzycLXKQneb3DD
3137
go.jetify.com/pkg v0.0.0-20250602221042-f9c387a74b34/go.mod h1:RLeG6AllDXfrqSzPz77HMQSXRv2ZM2YggPzt6J4Pz9g=
3238
go.jetify.com/sse v0.0.0-20250521180548-aeb6bc6de065 h1:qIfcJxr3QZG+bNZTONXjENzrsR3SeM7rP+hvpe9RFOE=
3339
go.jetify.com/sse v0.0.0-20250521180548-aeb6bc6de065/go.mod h1:zFADPn3Z0aZJe3+PbArGMGwe3oTwHxPZIwNILoRCmU8=
40+
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
41+
golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik=
42+
golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
43+
golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY=
44+
golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4=
3445
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
3546
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
3647
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=

0 commit comments

Comments
 (0)