Skip to content

Commit d144d4c

Browse files
init
0 parents  commit d144d4c

18 files changed

Lines changed: 4030 additions & 0 deletions

File tree

README.md

Lines changed: 216 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,216 @@
1+
# Court Table AI - Multi-Agent Debate System
2+
3+
A web-based application for managing AI agents and facilitating automatic debates/discussions between agents using a "Round Robin with Timeout" schema to generate the best answers for users.
4+
5+
## Features
6+
7+
- **Multi-Agent Management**: Configure and manage AI agents with different providers (Ollama, OpenAI, Anthropic, Google Gemini)
8+
- **Debate Engine**: Orchestrates discussions between multiple AI agents in a round-robin format
9+
- **Moderator Support**: Optional AI moderator to guide discussions, provide opening/closing remarks, and maintain discourse quality
10+
- **Multi-Provider Support**: Native support for OpenAI, Anthropic Claude, Google Gemini, Ollama, and custom OpenAI-compatible APIs
11+
- **Real-time Updates**: Server-Sent Events (SSE) for live debate updates
12+
- **Web Dashboard**: Clean, responsive UI built with HTML, HTMX, and Tailwind CSS
13+
- **History Tracking**: Complete discussion history with agent responses and timestamps
14+
- **Agent Health Checks**: Ping agents to verify connectivity
15+
16+
## Technology Stack
17+
18+
- **Backend**: Go (Golang) with Echo framework
19+
- **Frontend**: HTML5/HTMX, Tailwind CSS, Vanilla JavaScript
20+
- **Database**: SQLite for lightweight, local data storage
21+
- **AI Integration**: REST API supporting OpenAI format and Ollama API
22+
23+
## Quick Start
24+
25+
### Prerequisites
26+
27+
- Go 1.24+ installed
28+
- An AI provider (Ollama, OpenAI, or OpenAI-compatible API)
29+
30+
### Installation
31+
32+
1. Clone the repository:
33+
```bash
34+
git clone <repository-url>
35+
cd CourtTableAI
36+
```
37+
38+
2. Install dependencies:
39+
```bash
40+
go mod tidy
41+
```
42+
43+
3. Build and run:
44+
```bash
45+
go build cmd/main.go cmd/renderer.go
46+
./main.exe # on Windows
47+
# or
48+
./main # on Unix systems
49+
```
50+
51+
4. Open your browser and navigate to `http://localhost:8080`
52+
53+
## Usage
54+
55+
### 1. Add AI Agents
56+
57+
1. Go to the **Agents** page
58+
2. Click **Add New Agent**
59+
3. Fill in the agent details:
60+
- **Name**: Display name for the agent
61+
- **Provider URL**: API endpoint (e.g., `http://localhost:11434` for Ollama)
62+
- **API Token**: Authentication token (if required)
63+
- **Model Name**: Model to use (e.g., `llama2`, `gpt-3.5-turbo`)
64+
- **Timeout**: Response timeout in seconds
65+
66+
4. Test the connection with **Test Connection**
67+
68+
### 2. Start a Discussion
69+
70+
1. Go to the **Discussions** page
71+
2. Click **Start New Discussion**
72+
3. Enter the discussion topic
73+
4. Select the agents to participate
74+
5. Optionally select a **Moderator** to guide the discussion
75+
6. Click **Start Discussion**
76+
77+
The debate engine will:
78+
- Send the topic to the first agent
79+
- If a moderator is selected, they will provide opening remarks
80+
- Pass responses from one agent to the next as context
81+
- Moderator provides interim commentary between agent responses
82+
- Moderator summarizes each round and provides closing remarks
83+
- Handle timeouts and errors gracefully
84+
- Generate a final summary
85+
86+
### 3. Monitor Discussions
87+
88+
- View real-time updates on the discussion detail page
89+
- See agent responses, timestamps, and response times
90+
- Retry failed agent responses
91+
- Stop running discussions
92+
- View discussion history
93+
94+
## API Endpoints
95+
96+
### Agents
97+
- `GET /api/agents` - List all agents
98+
- `POST /api/agents` - Create new agent
99+
- `GET /api/agents/:id` - Get agent details
100+
- `PUT /api/agents/:id` - Update agent
101+
- `DELETE /api/agents/:id` - Delete agent
102+
- `POST /api/agents/:id/ping` - Test agent connectivity
103+
104+
### Discussions
105+
- `GET /api/discussions` - List all discussions
106+
- `POST /api/discussions` - Create new discussion
107+
- `GET /api/discussions/:id` - Get discussion details with logs
108+
- `POST /api/discussions/:id/stop` - Stop running discussion
109+
- `POST /api/discussions/:id/retry/:agentId` - Retry failed agent response
110+
111+
### Real-time Updates
112+
- `GET /api/discussions/:id/stream` - Server-Sent Events stream
113+
114+
## Database Schema
115+
116+
### Agents Table
117+
```sql
118+
CREATE TABLE agents (
119+
id INTEGER PRIMARY KEY AUTOINCREMENT,
120+
name TEXT NOT NULL UNIQUE,
121+
provider_url TEXT NOT NULL,
122+
api_token TEXT NOT NULL,
123+
model_name TEXT NOT NULL,
124+
timeout_seconds INTEGER DEFAULT 30,
125+
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
126+
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
127+
);
128+
```
129+
130+
### Discussions Table
131+
```sql
132+
CREATE TABLE discussions (
133+
id INTEGER PRIMARY KEY AUTOINCREMENT,
134+
topic TEXT NOT NULL,
135+
final_summary TEXT,
136+
status TEXT DEFAULT 'running',
137+
agent_ids TEXT NOT NULL,
138+
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
139+
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
140+
);
141+
```
142+
143+
### Discussion Logs Table
144+
```sql
145+
CREATE TABLE discussion_logs (
146+
id INTEGER PRIMARY KEY AUTOINCREMENT,
147+
discussion_id INTEGER NOT NULL,
148+
agent_id INTEGER NOT NULL,
149+
content TEXT,
150+
status TEXT NOT NULL,
151+
response_time INTEGER DEFAULT 0,
152+
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
153+
FOREIGN KEY (discussion_id) REFERENCES discussions(id) ON DELETE CASCADE,
154+
FOREIGN KEY (agent_id) REFERENCES agents(id) ON DELETE CASCADE
155+
);
156+
```
157+
158+
## Supported AI Providers
159+
160+
### Ollama
161+
- **Provider URL**: `http://localhost:11434`
162+
- **Model Name**: Any model available in Ollama (e.g., `llama2`, `mistral`)
163+
164+
### OpenAI Compatible APIs
165+
- **Provider URL**: API endpoint (e.g., `https://api.openai.com/v1`)
166+
- **API Token**: Your API key
167+
- **Model Name**: `gpt-3.5-turbo`, `gpt-4`, etc.
168+
169+
## Configuration
170+
171+
The application uses a SQLite database file (`court_table_ai.db`) that will be created automatically on first run.
172+
173+
## Development
174+
175+
### Project Structure
176+
177+
```
178+
CourtTableAI/
179+
├── cmd/
180+
│ ├── main.go # Application entry point
181+
│ └── renderer.go # Template renderer
182+
├── pkg/
183+
│ ├── database/ # Database operations
184+
│ ├── handlers/ # HTTP handlers
185+
│ ├── models/ # Data models
186+
│ └── orchestrator/ # Debate engine and agent client
187+
├── static/ # Static files (CSS, JS)
188+
├── templates/ # HTML templates
189+
├── go.mod # Go module file
190+
└── go.sum # Go dependencies
191+
```
192+
193+
### Running in Development Mode
194+
195+
```bash
196+
go run cmd/main.go cmd/renderer.go
197+
```
198+
199+
## License
200+
201+
This project is open source and available under the [MIT License](LICENSE).
202+
203+
## Contributing
204+
205+
1. Fork the repository
206+
2. Create a feature branch
207+
3. Make your changes
208+
4. Add tests if applicable
209+
5. Submit a pull request
210+
211+
## Support
212+
213+
For issues and questions:
214+
1. Check the existing issues
215+
2. Create a new issue with detailed information
216+
3. Include logs and configuration details

cmd/main.go

Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
package main
2+
3+
import (
4+
"court-table-ai/pkg/database"
5+
"court-table-ai/pkg/handlers"
6+
"court-table-ai/pkg/orchestrator"
7+
"html/template"
8+
"io"
9+
"log"
10+
"strings"
11+
12+
"github.com/labstack/echo/v4"
13+
"github.com/labstack/echo/v4/middleware"
14+
)
15+
16+
type TemplateRenderer struct {
17+
templates *template.Template
18+
}
19+
20+
func (t *TemplateRenderer) Render(w io.Writer, name string, data interface{}, c echo.Context) error {
21+
return t.templates.ExecuteTemplate(w, name, data)
22+
}
23+
24+
func loadTemplates() *template.Template {
25+
templ := template.New("").Funcs(template.FuncMap{
26+
"len": func(v interface{}) int {
27+
switch val := v.(type) {
28+
case []interface{}:
29+
return len(val)
30+
case string:
31+
return len(val)
32+
case []string:
33+
return len(val)
34+
case []int64:
35+
return len(val)
36+
case map[string]interface{}:
37+
return len(val)
38+
default:
39+
return 0
40+
}
41+
},
42+
"substr": func(s string, start int, length ...int) string {
43+
if start < 0 {
44+
start = 0
45+
}
46+
if start >= len(s) {
47+
return ""
48+
}
49+
end := len(s)
50+
if len(length) > 0 && start+length[0] < len(s) {
51+
end = start + length[0]
52+
}
53+
return s[start:end]
54+
},
55+
"upper": func(s string) string {
56+
return strings.ToUpper(s)
57+
},
58+
"eq": func(a, b interface{}) bool {
59+
return a == b
60+
},
61+
"ne": func(a, b interface{}) bool {
62+
return a != b
63+
},
64+
"gt": func(a, b interface{}) bool {
65+
switch a.(type) {
66+
case int:
67+
return a.(int) > b.(int)
68+
case int64:
69+
return a.(int64) > b.(int64)
70+
case float64:
71+
return a.(float64) > b.(float64)
72+
}
73+
return false
74+
},
75+
"lt": func(a, b interface{}) bool {
76+
switch a.(type) {
77+
case int:
78+
return a.(int) < b.(int)
79+
case int64:
80+
return a.(int64) < b.(int64)
81+
case float64:
82+
return a.(float64) < b.(float64)
83+
}
84+
return false
85+
},
86+
"getProviderType": func(url string) string {
87+
if strings.Contains(url, "openai.com") {
88+
return "OpenAI"
89+
} else if strings.Contains(url, "anthropic.com") {
90+
return "Anthropic"
91+
} else if strings.Contains(url, "googleapis.com") {
92+
return "Google"
93+
} else if strings.Contains(url, "localhost:11434") || strings.Contains(url, "ollama") {
94+
return "Ollama"
95+
} else {
96+
return "Custom"
97+
}
98+
},
99+
})
100+
101+
return template.Must(templ.ParseGlob("templates/*.html"))
102+
}
103+
104+
func main() {
105+
// Initialize database
106+
db, err := database.NewDB("court_table_ai.db")
107+
if err != nil {
108+
log.Fatal("Failed to connect to database:", err)
109+
}
110+
defer db.Close()
111+
112+
// Create tables
113+
if err := db.CreateTables(); err != nil {
114+
log.Fatal("Failed to create tables:", err)
115+
}
116+
117+
// Initialize debate engine
118+
debateEngine := orchestrator.NewDebateEngine(db)
119+
120+
// Initialize Echo
121+
e := echo.New()
122+
123+
// Middleware
124+
e.Use(middleware.Logger())
125+
e.Use(middleware.Recover())
126+
e.Use(middleware.CORS())
127+
128+
// Template renderer
129+
e.Renderer = &TemplateRenderer{
130+
templates: loadTemplates(),
131+
}
132+
133+
// Static files
134+
e.Static("/static", "static")
135+
136+
// Initialize handlers
137+
agentHandler := handlers.NewAgentHandler(db, debateEngine)
138+
discussionHandler := handlers.NewDiscussionHandler(db, debateEngine)
139+
sseHandler := handlers.NewSSEHandler(db, debateEngine)
140+
pageHandler := handlers.NewPageHandler(db)
141+
142+
// API Routes
143+
api := e.Group("/api")
144+
145+
// Agent routes
146+
api.POST("/agents", agentHandler.CreateAgent)
147+
api.GET("/agents", agentHandler.GetAgents)
148+
api.GET("/agents/:id", agentHandler.GetAgent)
149+
api.PUT("/agents/:id", agentHandler.UpdateAgent)
150+
api.DELETE("/agents/:id", agentHandler.DeleteAgent)
151+
api.POST("/agents/:id/ping", agentHandler.PingAgent)
152+
153+
// Discussion routes
154+
api.POST("/discussions", discussionHandler.CreateDiscussion)
155+
api.GET("/discussions", discussionHandler.GetDiscussions)
156+
api.GET("/discussions/:id", discussionHandler.GetDiscussion)
157+
api.POST("/discussions/:id/stop", discussionHandler.StopDiscussion)
158+
api.POST("/discussions/:id/retry/:agentId", discussionHandler.RetryAgent)
159+
160+
// SSE routes
161+
api.GET("/discussions/:id/stream", sseHandler.StreamDiscussion)
162+
163+
// Page routes
164+
e.GET("/", pageHandler.Dashboard)
165+
e.GET("/agents", pageHandler.AgentsPage)
166+
e.GET("/discussions", pageHandler.DiscussionsPage)
167+
e.GET("/discussions/:id", pageHandler.DiscussionDetail)
168+
169+
// Start server
170+
log.Println("Starting server on :8080")
171+
if err := e.Start(":8080"); err != nil {
172+
log.Fatal("Failed to start server:", err)
173+
}
174+
}

court_table_ai.db

44 KB
Binary file not shown.

0 commit comments

Comments
 (0)