Skip to content

Commit 957facc

Browse files
committed
update README
1 parent 4d41530 commit 957facc

File tree

8 files changed

+990
-50
lines changed

8 files changed

+990
-50
lines changed

README.md

Lines changed: 31 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,34 @@
22
<img src="docs/polaris.png" width="150">
33
</h1>
44

5-
# polaris: A Distributed AI Agent Framework for Function Calling
5+
# `polaris`: A Distributed AI Agent Framework for Function Calling
66

77
[![MIT License](https://img.shields.io/github/license/octu0/polaris)](https://github.com/octu0/polaris/blob/master/LICENSE)
88
[![GoDoc](https://pkg.go.dev/badge/github.com/octu0/polaris)](https://pkg.go.dev/github.com/octu0/polaris)
99
[![Go Report Card](https://goreportcard.com/badge/github.com/octu0/polaris)](https://goreportcard.com/report/github.com/octu0/polaris)
1010
[![Releases](https://img.shields.io/github/v/release/octu0/polaris)](https://github.com/octu0/polaris/releases)
1111

12-
`polaris` is a Go framework designed for building **distributed AI agents**.
13-
These agents act like sidecars, running alongside your applications or directly on servers to expose system capabilities and local resources (like log files or metrics) as secure Function Calls.
12+
`polaris` is a Go framework for building **distributed AI agents**.
13+
These agents run as lightweight sidecars alongside your applications, securely exposing system capabilities and local resources (like logs or metrics) via **Function Calling**. This enables AI models (such as Google's Vertex AI Gemini) to intelligently interact with your distributed infrastructure through a unified polaris interface, simplifying complex coordination. The framework is designed for **parallel execution** to handle demanding workloads.
14+
15+
## Why `polaris` ?
16+
17+
Building robust server-side Function Calling, especially in distributed systems, presents significant hurdles:
18+
19+
- **Schema Management Complexity:** Keeping function definitions consistent across multiple services is challenging.
20+
- **Coordination Difficulties:** Orchestrating interactions between services (RPC) often requires complex transport logic and boilerplate code.
21+
- **Integration Friction:** Adding Function Calling capabilities to existing services can demand substantial code modifications.
22+
23+
`polaris` is a distributed AI agent framework designed to simplify this.
24+
It offers a novel approach focused on ease of use and intelligent coordination:
25+
26+
- **Centralized `registry` Cluster:** Provides a highly available, central point for managing function schemas and discovering services, eliminating synchronization headaches.
27+
- **Lightweight Sidecar Agents:** `polaris` agents run alongside your applications as sidecars. This minimizes the need for direct code integration into your existing services.
28+
- **Context-Aware Execution:** The sidecar model allows agents to directly access local context, such as logs or metrics. This enables smarter Function Calling – for example, an agent can analyze local server logs and metrics simultaneously to diagnose an issue.
29+
- **Efficient Operation:** Currently leverages Gemini for its reasoning, requiring minimal computational resources on the agent side.
30+
31+
**In essence, `polaris` enables "AI-driven RPC"** – using the power of Function Calling to intelligently orchestrate procedure calls across your distributed system, simplifying development and unlocking new possibilities for AI agent collaboration.
1432

15-
This allows AI models (such as Google's Vertex AI Gemini) to intelligently interact with your distributed infrastructure through a unified, simplified Function Calling interface provided by `polaris` agents. The framework is built for parallel execution to handle demanding workloads.
1633

1734
## Features
1835

@@ -105,21 +122,21 @@ tool := Tool{
105122
Description: "FuncDesc",
106123
Parameters: Object{
107124
Properties: Properties{
108-
"param1": String{Description: "desc param1", Required: true},
109-
"param2": Int{Description: "desc param2", Required: true},
125+
"param1": String{ Description: "desc param1", Required: true },
126+
"param2": Int{ Description: "desc param2", Required: true },
110127
"param3": ObjectArray{
111128
Description: "desc param3",
112129
Items: Properties{
113-
"param4": String{Description: "desc param4"},
114-
"param5": Bool{Description: "desc param5"},
130+
"param4": String{ Description: "desc param4" },
131+
"param5": Bool{ Description: "desc param5" },
115132
},
116133
},
117134
},
118135
},
119136
Response: Object{
120137
Properties: Properties{
121-
"result1": String{Description: "result1", Required: true},
122-
"result2": String{Description: "result2"},
138+
"result1": String{ Description: "result1", Required: true },
139+
"result2": String{ Description: "result2" },
123140
},
124141
},
125142
}
@@ -339,6 +356,10 @@ func main() {
339356
}
340357
```
341358

359+
## Other Examples
360+
361+
See [_example](https://github.com/octu0/polaris/tree/master/_example) for examples of other cases.
362+
342363
## Dependencies
343364

344365
Using `polaris`, AI orchestration capabilities, requires bellow:

_example/agent-schema/README.md

Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
# `agent-schema` Example:
2+
3+
This example demonstrates how to define and use JSON Schema for AI tool outputs in `polaris`. By using `UseJSONOutput` with tool definitions, you can ensure that AI inference outputs conform to your specified schema structure.
4+
5+
## Overview
6+
7+
The `agent-schema` example showcases how to:
8+
9+
- Define tools with structured JSON Schema responses
10+
- Use AI inference to generate outputs that match these schemas
11+
- Create a seamless integration between AI models and structured data
12+
13+
This approach allows you to leverage AI capabilities while maintaining control over the output format, making it easier to process and use the results in your applications.
14+
15+
## Prerequisites
16+
17+
Before running this example, you need to set up the following environment variables for Google Cloud Platform authentication:
18+
19+
```bash
20+
export GOOGLE_CLOUD_PROJECT=your_project_id
21+
export GOOGLE_CLOUD_LOCATION=your_gcp_project_location
22+
export GOOGLE_APPLICATION_CREDENTIALS=/path/to/credential.json
23+
```
24+
25+
These environment variables are required to authenticate with Google Cloud and access the Gemini AI model used in this example.
26+
27+
## Components
28+
29+
This example consists of three main components:
30+
31+
### 1. Registry Server (`registry.go`)
32+
33+
The registry server acts as a central hub for registering and managing tools. It binds to a local address and port, allowing clients and agents to connect.
34+
35+
```go
36+
registry, err := polaris.CreateRegistry(
37+
polaris.WithBind("127.0.0.1", 4222),
38+
)
39+
```
40+
41+
### 2. Agent Implementation (`agents.go`)
42+
43+
The agent implementation defines several tools with specific JSON schemas for their responses:
44+
45+
- `getWeather`: Returns weather information for a specified city
46+
- `getFortune`: Provides a fortune-telling result
47+
- `getCurrentDate`: Returns the current date information
48+
49+
Each tool uses `polaris.UseJSONOutput(myTool.Response)` to ensure that the AI model's output conforms to the defined schema.
50+
51+
### 3. Client Application (`client.go`)
52+
53+
The client application connects to the registry, creates a session with the AI model, and sends a prompt to get information about today's conditions, including fortune and weather.
54+
55+
## Key Features
56+
57+
### JSON Schema Definition for AI Outputs
58+
59+
The core feature of this example is the ability to define JSON schemas for AI outputs using `UseJSONOutput`. This ensures that the AI model generates responses that match your expected structure.
60+
61+
For example, in the `getWeather` tool:
62+
63+
```go
64+
myTool, _ := conn.Tool(toolName)
65+
gen, err := polaris.GenerateJSON(
66+
ctx,
67+
polaris.UseModel("gemini-2.5-pro-exp-03-25"),
68+
polaris.UseSystemInstruction(
69+
polaris.AddTextSystemInstruction("Output must be in Japanese."),
70+
),
71+
polaris.UseJSONOutput(myTool.Response),
72+
polaris.UseTemperature(0.5),
73+
)
74+
```
75+
76+
The `UseJSONOutput(myTool.Response)` parameter tells the AI model to generate output that conforms to the schema defined in `myTool.Response`.
77+
78+
### Structured AI Responses
79+
80+
By using JSON schemas, you can ensure that AI responses are structured and predictable, making them easier to process in your application logic. This approach bridges the gap between free-form AI outputs and structured data requirements.
81+
82+
## Usage
83+
84+
To run this example:
85+
86+
1. Set up the required environment variables as described in the Prerequisites section.
87+
88+
2. Start the registry server:
89+
```bash
90+
go run registry.go
91+
```
92+
93+
3. In a separate terminal, start the agent:
94+
```bash
95+
go run agents.go
96+
```
97+
98+
4. In another terminal, run the client:
99+
```bash
100+
go run client.go
101+
```
102+
103+
The client will send a prompt to the AI model, which will use the registered tools to generate structured responses about today's fortune and weather in Tokyo.
104+
105+
## Code Explanation
106+
107+
### Tool Definition with Response Schema
108+
109+
Each tool is defined with a specific response schema that the AI model must follow:
110+
111+
```go
112+
conn.RegisterTool(polaris.Tool{
113+
Name: toolName,
114+
Description: "get weather by city",
115+
Parameters: polaris.Object{
116+
Properties: polaris.Properties{
117+
"cityName": polaris.String{
118+
Description: "cityName",
119+
Default: "tokyo",
120+
Required: true,
121+
},
122+
},
123+
},
124+
Response: polaris.Object{
125+
Properties: polaris.Properties{
126+
"temperature": polaris.Int{
127+
Description: "estimated maximum temperatures",
128+
Required: true,
129+
},
130+
"sky_condition": polaris.String{
131+
Description: "sky condition",
132+
Required: true,
133+
},
134+
},
135+
},
136+
Handler: func(c *polaris.Ctx) error {
137+
// Handler implementation
138+
},
139+
})
140+
```
141+
142+
### AI Inference with Schema Enforcement
143+
144+
The `GenerateJSON` function is used to create an AI inference function that enforces the output schema:
145+
146+
```go
147+
gen, err := polaris.GenerateJSON(
148+
ctx,
149+
polaris.UseModel("gemini-2.5-pro-exp-03-25"),
150+
polaris.UseSystemInstruction(
151+
polaris.AddTextSystemInstruction("Output must be in Japanese."),
152+
),
153+
polaris.UseJSONOutput(myTool.Response),
154+
polaris.UseTemperature(0.5),
155+
)
156+
```
157+
158+
This ensures that the AI model's output will match the structure defined in `myTool.Response`, allowing for seamless integration between AI capabilities and structured data requirements.
159+
160+
## Benefits
161+
162+
Using JSON schemas for AI outputs provides several benefits:
163+
164+
1. **Predictability**: Ensures that AI outputs follow a consistent structure
165+
2. **Validation**: Automatically validates that outputs contain required fields
166+
3. **Integration**: Makes it easier to integrate AI capabilities into existing systems
167+
4. **Type Safety**: Provides type information for downstream processing
168+
169+
This approach allows you to leverage the power of AI while maintaining the structure and predictability needed for production applications.

_example/agent-schema/agents.go

Lines changed: 26 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -12,29 +12,6 @@ import (
1212
"github.com/pkg/errors"
1313
)
1414

15-
func main() {
16-
conn, err := polaris.Connect(polaris.ConnectAddress("127.0.0.1", "4222"))
17-
if err != nil {
18-
panic(err)
19-
}
20-
defer conn.Close()
21-
22-
ctx, cancel := signal.NotifyContext(context.Background(), syscall.SIGTERM, syscall.SIGINT)
23-
defer cancel()
24-
25-
if err := registerWeatherAgent(ctx, conn); err != nil {
26-
panic(err)
27-
}
28-
if err := registerFortuneAgent(ctx, conn); err != nil {
29-
panic(err)
30-
}
31-
if err := registerCurrentDate(ctx, conn); err != nil {
32-
panic(err)
33-
}
34-
35-
<-ctx.Done()
36-
}
37-
3815
func registerWeatherAgent(ctx context.Context, conn *polaris.Conn) error {
3916
toolName := "getWeather"
4017
return conn.RegisterTool(polaris.Tool{
@@ -63,14 +40,14 @@ func registerWeatherAgent(ctx context.Context, conn *polaris.Conn) error {
6340
},
6441
Handler: func(c *polaris.Ctx) error {
6542
log.Printf("function call: %s", toolName)
66-
t, _ := conn.Tool(toolName)
43+
myTool, _ := conn.Tool(toolName)
6744
gen, err := polaris.GenerateJSON(
6845
ctx,
6946
polaris.UseModel("gemini-2.5-pro-exp-03-25"),
7047
polaris.UseSystemInstruction(
7148
polaris.AddTextSystemInstruction("Output must be in Japanese."),
7249
),
73-
polaris.UseJSONOutput(t.Response),
50+
polaris.UseJSONOutput(myTool.Response),
7451
polaris.UseTemperature(0.5),
7552
)
7653
if err != nil {
@@ -131,6 +108,7 @@ func registerFortuneAgent(ctx context.Context, conn *polaris.Conn) error {
131108
if err != nil {
132109
return errors.WithStack(err)
133110
}
111+
134112
resp, err := gen(`
135113
Perform a simple, omikuji-style fortune telling for today.
136114
Give a rndom luck level ('Great luck', 'Good luck', 'Small luck') and a short positive message.
@@ -179,3 +157,26 @@ func registerCurrentDate(ctx context.Context, conn *polaris.Conn) error {
179157
},
180158
})
181159
}
160+
161+
func main() {
162+
conn, err := polaris.Connect(polaris.ConnectAddress("127.0.0.1", "4222"))
163+
if err != nil {
164+
panic(err)
165+
}
166+
defer conn.Close()
167+
168+
ctx, cancel := signal.NotifyContext(context.Background(), syscall.SIGTERM, syscall.SIGINT)
169+
defer cancel()
170+
171+
if err := registerWeatherAgent(ctx, conn); err != nil {
172+
panic(err)
173+
}
174+
if err := registerFortuneAgent(ctx, conn); err != nil {
175+
panic(err)
176+
}
177+
if err := registerCurrentDate(ctx, conn); err != nil {
178+
panic(err)
179+
}
180+
181+
<-ctx.Done()
182+
}

0 commit comments

Comments
 (0)