Skip to content

Commit c65af77

Browse files
authored
craft the agent architecture (#1)
1 parent feab5ff commit c65af77

38 files changed

+4954
-3
lines changed

.github/workflows/build.yml

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
##
2+
## Build the main branch
3+
##
4+
name: build
5+
on:
6+
push:
7+
branches:
8+
- main
9+
- /refs/heads/main
10+
11+
jobs:
12+
13+
build:
14+
runs-on: ubuntu-latest
15+
steps:
16+
17+
- uses: actions/setup-go@v5
18+
with:
19+
go-version: "1.23"
20+
21+
- uses: actions/checkout@v4
22+
23+
- name: go build
24+
run: |
25+
go build ./...
26+
27+
- name: go test
28+
run: |
29+
go test -v -coverprofile=profile.cov $(go list ./... | grep -v /examples/)
30+
31+
- uses: shogo82148/actions-goveralls@v1
32+
continue-on-error: true
33+
with:
34+
path-to-profile: profile.cov
35+
36+
- uses: reecetech/version-increment@2023.10.2
37+
id: version
38+
with:
39+
scheme: semver
40+
increment: patch
41+
42+
- name: publish
43+
run: |
44+
git config user.name "GitHub Actions"
45+
git config user.email "github-actions@users.noreply.github.com"
46+
git tag ${{ steps.version.outputs.v-version }}
47+
git push origin -u ${{ steps.version.outputs.v-version }}
48+

.github/workflows/check-code.yml

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
##
2+
## Quality checks
3+
##
4+
name: check
5+
on:
6+
pull_request:
7+
types:
8+
- opened
9+
- synchronize
10+
11+
jobs:
12+
13+
code:
14+
runs-on: ubuntu-latest
15+
steps:
16+
17+
- uses: actions/setup-go@v5
18+
with:
19+
go-version: "1.23"
20+
21+
- uses: actions/checkout@v4
22+
23+
- uses: dominikh/staticcheck-action@v1.3.1
24+
with:
25+
install-go: false

.github/workflows/check-test.yml

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
##
2+
## Unit Tests
3+
##
4+
name: test
5+
on:
6+
pull_request:
7+
types:
8+
- opened
9+
- synchronize
10+
11+
jobs:
12+
13+
unit:
14+
runs-on: ubuntu-latest
15+
steps:
16+
17+
- uses: actions/setup-go@v5
18+
with:
19+
go-version: "1.23"
20+
21+
- uses: actions/checkout@v4
22+
23+
- name: go build
24+
run: |
25+
go build ./...
26+
27+
- name: go test
28+
run: |
29+
go test -v -coverprofile=profile.cov $(go list ./... | grep -v /examples/)
30+
31+
- uses: shogo82148/actions-goveralls@v1
32+
continue-on-error: true
33+
with:
34+
path-to-profile: profile.cov

LICENSE

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
MIT License
22

3-
Copyright (c) 2025 kshard
3+
Copyright (c) 2025 Dmitry Kolesnikov
44

55
Permission is hereby granted, free of charge, to any person obtaining a copy
66
of this software and associated documentation files (the "Software"), to deal

README.md

Lines changed: 235 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,235 @@
1-
# thinker
2-
https://arxiv.org/pdf/2304.03442
1+
<p align="center">
2+
<img src="./doc/thinker-3.svg" height="220" />
3+
<h3 align="center">thinker</h3>
4+
<p align="center"><strong>LLM generative agents for Golang</strong></p>
5+
6+
<p align="center">
7+
<!-- Version -->
8+
<a href="https://github.com/kshard/thinker/releases">
9+
<img src="https://img.shields.io/github/v/tag/kshard/thinker?label=version" />
10+
</a>
11+
<!-- Documentation -->
12+
<a href="https://pkg.go.dev/github.com/kshard/thinker">
13+
<img src="https://pkg.go.dev/badge/github.com/kshard/thinker" />
14+
</a>
15+
<!-- Build Status -->
16+
<a href="https://github.com/kshard/thinker/actions/">
17+
<img src="https://github.com/kshard/thinker/workflows/build/badge.svg" />
18+
</a>
19+
<!-- GitHub -->
20+
<a href="https://github.com/kshard/thinker">
21+
<img src="https://img.shields.io/github/last-commit/kshard/thinker.svg" />
22+
</a>
23+
<!-- Coverage -->
24+
<a href="https://coveralls.io/github/kshard/thinker?branch=main">
25+
<img src="https://coveralls.io/repos/github/kshard/thinker/badge.svg?branch=main" />
26+
</a>
27+
<!-- Go Card -->
28+
<a href="https://goreportcard.com/report/github.com/kshard/thinker">
29+
<img src="https://goreportcard.com/badge/github.com/kshard/thinker" />
30+
</a>
31+
</p>
32+
</p>
33+
34+
---
35+
36+
The library enables development of LLM-based generative agents for Golang.
37+
38+
## Inspiration
39+
40+
The generative agents autonomously generate output as a reaction on input, past expereince and current environment. Agents records obervations and reason over with natural language description, taking advantage of LLMs.
41+
42+
* [Generative Agents: Interactive Simulacra of Human Behavior](https://arxiv.org/pdf/2304.03442)
43+
* [LLM Reasoner and Automated Planner: A new NPC approach](https://arxiv.org/pdf/2501.10106)
44+
45+
In this library, an agent is defined as a side-effect function `ƒ: A ⟼ B`, which takes a Golang type `A` as input and autonomously produces an output `B`, while retaining memory of past experiences.
46+
47+
- [Inspiration](#inspiration)
48+
- [Getting started](#getting-started)
49+
- [Quick example](#quick-example)
50+
- [Agent Architecture](#agent-architecture)
51+
- [Commands \& Tools](#commands--tools)
52+
- [Chaining agents](#chaining-agents)
53+
- [How To Contribute](#how-to-contribute)
54+
- [commit message](#commit-message)
55+
- [bugs](#bugs)
56+
- [License](#license)
57+
58+
59+
## Getting started
60+
61+
The latest version of the library is available at `main` branch of this repository. All development, including new features and bug fixes, take place on the `main` branch using forking and pull requests as described in contribution guidelines. The stable version is available via Golang modules.
62+
63+
Running the examples you need access either to AWS Bedrock or OpenAI.
64+
65+
## Quick example
66+
67+
See ["Hello World"](./examples/helloworld/hw.go) application as the quick start. The example agent is `ƒ: string ⟼ string` that takes the sentence and returns the anagram.
68+
69+
```go
70+
package main
71+
72+
import (
73+
"context"
74+
"fmt"
75+
76+
// LLMs toolkit
77+
"github.com/kshard/chatter"
78+
"github.com/kshard/chatter/bedrock"
79+
80+
// Agents toolkit
81+
"github.com/kshard/thinker/agent"
82+
"github.com/kshard/thinker/codec"
83+
"github.com/kshard/thinker/memory"
84+
"github.com/kshard/thinker/reasoner"
85+
)
86+
87+
// This function is core in the example. It takes input (the sentence)
88+
// and generate prompt function that guides LLMs on how to create anagram.
89+
func anagram(expr string) (prompt chatter.Prompt, err error) {
90+
prompt.
91+
WithTask("Create anagram using the phrase: %s", expr).
92+
With(
93+
// instruct LLM about anagram generation
94+
chatter.Rules(
95+
"Strictly adhere to the following requirements when generating a response.",
96+
"The output must be the resulting anagram only.",
97+
),
98+
).
99+
With(
100+
// Gives the example of input and expected output
101+
chatter.Example{
102+
Input: "Madam Curie",
103+
Reply: "Radium came",
104+
},
105+
)
106+
107+
return
108+
}
109+
110+
func main() {
111+
// create instance of LLM client
112+
llm, err := bedrock.New(
113+
bedrock.WithLLM(bedrock.LLAMA3_1_70B_INSTRUCT),
114+
bedrock.WithRegion("us-west-2"),
115+
)
116+
if err != nil {
117+
panic(err)
118+
}
119+
120+
// We create an agent that takes string (sentence) and returns string (anagram).
121+
agt := agent.NewAutomata(llm,
122+
// Configures memory for the agent. Typically, memory retains all of
123+
// the agent's observations. Here, we use a void memory, meaning no
124+
// observations are retained.
125+
memory.NewVoid(),
126+
127+
// Configures the reasoner, which determines the agent's next actions and prompts.
128+
// Here, we use a void reasoner, meaning no reasoning is performed—the agent
129+
// simply returns the result.
130+
reasoner.NewVoid[string, string](),
131+
132+
// Configures the encoder to transform input of type A into a `chatter.Prompt`.
133+
// Here, we use an encoder that converts string expressions into prompt.
134+
codec.FromEncoder(anagram),
135+
136+
// Configure the decoder to transform output of LLM into type B.
137+
// Here, we use the identity decoder that returns LLMs output as-is.
138+
codec.DecoderID,
139+
)
140+
141+
// Evaluate expression and receive the result
142+
val, err := agt.Prompt(context.Background(), "a gentleman seating on horse")
143+
fmt.Printf("==> %v\n%+v\n", err, val)
144+
}
145+
```
146+
147+
## Agent Architecture
148+
149+
The `thinker` library provides toolkit for running agents with type-safe constraints. It is built on a pluggable architecture, allowing applications to define custom workflows. The diagram below emphasis core building blocks.
150+
151+
```mermaid
152+
%%{init: {'theme':'neutral'}}%%
153+
graph TD
154+
subgraph Interface
155+
A[Type A]
156+
B[Type B]
157+
end
158+
subgraph Memory
159+
S[Stream]
160+
end
161+
subgraph Commands
162+
C[Command]
163+
end
164+
subgraph Agent
165+
A --"01|input"--> E[Encoder]
166+
E --"02|prompt"--> G((Agent))
167+
G --"03|eval"--> L[LLM]
168+
G --"04|reply"--> D[Decoder]
169+
D -."05|exec".-> C
170+
C -."06|result".-> G
171+
G <--"07|observations" --> S
172+
G --"08|deduct"--> R[Reasoner]
173+
R <-."09|reflect".-> S
174+
R --"10|new goal"--> G
175+
D --"11|answer" --> B
176+
end
177+
```
178+
179+
[`Memory`](./memory.go) is core element of agents behaviour. It is a database that maintains a comprehensive record of an agent’s experience. It recalls observations and builds the context windows to be used for prompting.
180+
181+
[`Reasoner`](./reasoner.go) serves as the goal-setting component in the architecture. It evaluates the agent's current state, performing either deterministic or non-deterministic analysis of immediate results and past experiences. Based on this assessment, it determines whether the goal has been achieved and, if not, suggests the best new goal for the agent to pursue.
182+
183+
The type-safe agent interface `ƒ: A ⟼ B` is well-suited for composition and agent chaining. However, encoding and decoding application-specific types must be abstracted. To facilitate this, the library provides two key traits: [`Encoder`](./codec.go) for constructing prompts and [`Decoder`](./codec.go) for parsing and validating LLM responses.
184+
185+
The [rainbow example](./examples/rainbow/rainbow.go) demonstrates a simple agent that effectively utilizes the depicted agent architecture to solve a task.
186+
187+
### Commands & Tools
188+
189+
The `thinker` library enables the integration of external [tools and commands](./command.go) into the agent workflow. By design, a command is a function `Decoder[CmdOut]` that takes input from the LLM, executes it, validates and returns the output and any possible feedback - similary as you implement basic decoder.
190+
191+
When constructing a prompt, it is essential to include a section that "advertises" the available commands and the rules for using them. There is [a registry](./command/registry.go) that automates prompting and parsing of the response.
192+
193+
The [script example](./examples/script/script.go) demonstrates a simple agent that utilizes `bash` to generate and modify files on the local filesystem.
194+
195+
196+
### Chaining agents
197+
198+
The `thinker` library does not provide built-in mechanisms for chaining agents. Instead, it encourages the use of standard Go techniques either pure functional chaining or chaining of go routines (e.g. [golem/pipe](https://github.com/fogfish/golem)).
199+
200+
The [chain example](./examples/chain/chain.go) demostrates off-the-shelf techniques for agents chaining.
201+
202+
203+
## How To Contribute
204+
205+
The library is [MIT](LICENSE) licensed and accepts contributions via GitHub pull requests:
206+
207+
1. Fork it
208+
2. Create your feature branch (`git checkout -b my-new-feature`)
209+
3. Commit your changes (`git commit -am 'Added some feature'`)
210+
4. Push to the branch (`git push origin my-new-feature`)
211+
5. Create new Pull Request
212+
213+
The build and testing process requires [Go](https://golang.org) version 1.21 or later.
214+
215+
**build** and **test** library.
216+
217+
```bash
218+
git clone https://github.com/kshard/thinker
219+
cd thinker
220+
go test ./...
221+
```
222+
223+
### commit message
224+
225+
The commit message helps us to write a good release note, speed-up review process. The message should address two question what changed and why. The project follows the template defined by chapter [Contributing to a Project](http://git-scm.com/book/ch5-2.html) of Git book.
226+
227+
### bugs
228+
229+
If you experience any issues with the library, please let us know via [GitHub issues](https://github.com/kshard/chatter/issue). We appreciate detailed and accurate reports that help us to identity and replicate the issue.
230+
231+
232+
## License
233+
234+
[![See LICENSE](https://img.shields.io/github/license/kshard/thinker.svg?style=for-the-badge)](LICENSE)
235+

0 commit comments

Comments
 (0)