aiassistant

package module
v0.0.0-...-4388f4f Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 18, 2026 License: MIT Imports: 17 Imported by: 0

README

Willknow

🤖 AI-powered debugging and diagnostics library for Go applications.

项目动机

在 AI 时代,程序出现问题时不应该还需要人工去排查。Willknow 让你的程序自带 AI 助手,用户可以直接向 AI 咨询程序问题,AI 会自动分析代码和日志,快速定位问题原因。

特性

  • 零配置集成:只需几行代码即可为你的 Go 程序添加 AI 助手
  • 多模型支持:支持 15+ AI 模型(Claude, DeepSeek, Qwen, Moonshot, GLM 等)
  • 智能诊断:AI 可以读取源代码和日志文件,自动分析问题
  • 代码索引:自动生成代码摘要索引,支持语义搜索代码文件
  • Web 界面:优美的聊天界面,支持实时对话
  • 容器化优先:为 Docker/Kubernetes 部署优化
  • 支持多种日志格式:自动识别文本日志和 JSON 日志
  • 自定义模型:支持公司内部部署的 OpenAI Compatible 模型

快速开始

1. 安装
go get github.com/willknow-ai/willknow-go
2. 集成到你的程序
package main

import (
    "net/http"
    "os"

    aiassistant "github.com/willknow-ai/willknow-go"
)

func main() {
    // 启动 AI 助手(独立 goroutine)
    go func() {
        assistant, err := aiassistant.New(aiassistant.Config{
            SourcePath: "/app/source",              // 源码路径
            LogFiles:   []string{"/var/log/app.log"}, // 可选,留空自动检测
            Port:       8888,                       // AI 助手端口
            Provider:   "anthropic",                // 或 "deepseek"
            APIKey:     os.Getenv("AI_API_KEY"),
        })

        if err != nil {
            panic(err)
        }

        assistant.Start()
    }()

    // 你的正常业务代码
    http.HandleFunc("/", handler)
    http.ListenAndServe(":8080", nil)
}
3. 创建 Dockerfile
FROM golang:1.21 AS builder
WORKDIR /src
COPY . .
RUN go build -o /app/myapp

FROM alpine:latest
WORKDIR /app
COPY --from=builder /app/myapp .
COPY --from=builder /src /app/source  # 复制源码供 AI 分析
RUN mkdir -p /var/log
CMD ["./myapp"]
4. 运行
# 构建镜像
docker build -t myapp .

# 运行容器(需要 AI API Key)
docker run -p 8080:8080 -p 8888:8888 \
  -e AI_API_KEY=your-api-key \
  -e AI_PROVIDER=anthropic \
  myapp
5. 使用 AI 助手
  1. 打开浏览器访问 http://localhost:8888
  2. 当程序出错时,复制 RequestID
  3. 在 AI 助手中输入:"RequestID xxx 出错了,帮我分析"
  4. AI 会自动查看日志和代码,给出诊断结果

示例程序

完整的示例程序已移至独立仓库:willknow-go-examples

可用示例
1. Basic Example - 调试助手

最简单的入门示例,展示 Willknow 作为调试助手的核心功能。

特性:

  • 日志分析和错误诊断
  • 代码阅读和搜索
  • 基于 RequestID 的问题排查
git clone https://github.com/willknow-ai/willknow-go-examples.git
cd willknow-go-examples/basic
export AI_API_KEY=your-key
go run main.go
2. Agent API Example - AI Agent

展示 Willknow 作为 AI Agent,通过自然语言调用你的应用 API。

特性:

  • OpenAPI 自动发现
  • 自然语言 API 调用
  • 多轮对话支持
  • 外部 AI 系统集成
cd willknow-go-examples/agent-api
export AI_API_KEY=your-key
go run main.go

访问:

工作原理

┌─────────────────────────────────────────────┐
│          Docker 容器                         │
│  ┌──────────────┐      ┌─────────────────┐ │
│  │ 你的程序      │      │ AI 助手库        │ │
│  │              │      │                 │ │
│  │ 打印日志 ────┼─────→│ /var/log/       │ │
│  └──────────────┘      │                 │ │
│                        │ Web UI :8888    │ │
│  ┌──────────────┐      │ ┌─────────────┐ │ │
│  │ 源码          │←─────┼─│ 代码分析     │ │ │
│  │ /app/source/ │      │ │ 日志查询     │ │ │
│  └──────────────┘      │ └─────────────┘ │ │
│                        └─────────────────┘ │
└─────────────────────────────────────────────┘

AI 助手提供的工具:

  • search_code_index:语义搜索代码文件(基于 LLM 生成的摘要)
  • read_file:读取源代码文件
  • grep:搜索代码内容
  • glob:查找文件
  • read_logs:根据 RequestID 或关键词查询日志

架构设计

整体架构
┌─────────────────────────────────────────────────────────┐
│                    用户浏览器                             │
│  ┌─────────────────────────────────────────────────┐   │
│  │  Web UI (HTML/JS) - localhost:8888              │   │
│  │  - 聊天界面                                      │   │
│  │  - WebSocket 连接                                │   │
│  └─────────────────────────────────────────────────┘   │
└─────────────────┬───────────────────────────────────────┘
                  │ WebSocket
                  ↓
┌─────────────────────────────────────────────────────────┐
│              AI Assistant (Go Server)                   │
│                                                          │
│  ┌──────────────────────────────────────────────────┐  │
│  │  server.go - HTTP/WebSocket Server               │  │
│  │  - 处理 WebSocket 连接                            │  │
│  │  - 管理会话状态                                   │  │
│  │  - 协调 AI 对话流程                               │  │
│  └──────────────────────────────────────────────────┘  │
│                      ↓                                   │
│  ┌──────────────────────────────────────────────────┐  │
│  │  provider (AI 服务商层)                          │  │
│  │  ├─ Anthropic Provider (Claude)                  │  │
│  │  └─ OpenAI Compatible Provider (15+ 模型)       │  │
│  └──────────────────────────────────────────────────┘  │
│                      ↓                                   │
│  ┌──────────────────────────────────────────────────┐  │
│  │  tools (工具层)                                   │  │
│  │  ├─ read_file  (读取源码)                        │  │
│  │  ├─ grep       (搜索代码)                        │  │
│  │  ├─ glob       (查找文件)                        │  │
│  │  └─ read_logs  (查询日志)                        │  │
│  └──────────────────────────────────────────────────┘  │
└─────────────────────────────────────────────────────────┘
用户询问处理流程

以 "RequestID abc123 出错了,帮我分析" 为例:

1. 前端发送消息
// 浏览器通过 WebSocket 发送用户消息
ws.send(JSON.stringify({
    content: "RequestID abc123 出错了,帮我分析"
}));
2. 后端接收并创建会话
// server.go: 接收消息,添加到会话历史
session.messages = append(session.messages, provider.Message{
    Role: "user",
    Content: []provider.ContentBlock{
        {Type: "text", Text: "RequestID abc123 出错了,帮我分析"},
    },
})
3. 多轮对话循环
// 允许最多 10 轮工具调用
for turn := 0; turn < 10; turn++ {
    // 调用 AI Provider
    response := provider.SendMessage(
        session.messages,  // 完整对话历史
        tools,             // 可用工具列表
        systemPrompt,      // 系统提示词
    )

    // 处理响应
    if response.Type == "text" {
        // 发送文字回复给前端
        conn.WriteJSON(response.Text)
    } else if response.Type == "tool_use" {
        // AI 决定使用工具
        result := toolRegistry.Execute(response.ToolName, response.Params)
        // 将工具结果添加到会话,继续下一轮
    }
}
4. 实际执行示例
👤 用户: "RequestID abc123 出错了,帮我分析"

🤖 Turn 1: AI 决定使用 read_logs(query="abc123")
🔧 工具执行: 返回相关日志
   [ERROR] Database connection timeout

🤖 Turn 2: AI 基于日志决定使用 read_file("main.go", 180-200)
🔧 工具执行: 返回源码片段

🤖 Turn 3: AI 分析完成,返回诊断结果
📨 "发现问题在 main.go:188,数据库连接超时..."

✅ 前端显示完整回复
核心组件
1. Provider 抽象层
type Provider interface {
    SendMessage(messages, tools, system) (*Response, error)
}
  • Anthropic Provider: Claude 专用 API 格式
  • OpenAI Compatible Provider: 支持 15+ 模型(DeepSeek, Qwen, GLM 等)
  • 格式自动转换,用户无感知切换
2. 工具注册系统
type Registry struct {
    tools map[string]ToolExecutor
}
  • 动态工具注册
  • 统一执行接口
  • AI 自主决定工具调用顺序
3. 会话管理
type Session struct {
    messages []provider.Message  // 完整对话历史
    mu       sync.Mutex          // 并发安全
}
  • 每个 WebSocket 连接独立会话
  • 完整保存对话历史
  • 支持上下文理解
数据流向
用户输入
  ↓
WebSocket 接收
  ↓
添加到会话历史
  ↓
┌─────────────────────────────────────┐
│         多轮对话循环                 │
│  ┌──────────────────────────────┐  │
│  │ 1. 发送历史 + 工具定义 → AI  │  │
│  └──────────────────────────────┘  │
│              ↓                      │
│  ┌──────────────────────────────┐  │
│  │ 2. AI 返回:文字 or 工具调用 │  │
│  └──────────────────────────────┘  │
│              ↓                      │
│         文字?    工具调用?           │
│          ↓           ↓              │
│    发送给前端    执行工具            │
│                      ↓              │
│              添加结果到历史           │
│                      ↓              │
│              继续下一轮 ──┐          │
│                          │          │
│  └───────────────────────┘          │
└─────────────────────────────────────┘
  ↓
发送 "done" 信号
关键设计特点
  1. AI 自主决策

    • AI 自主决定使用哪些工具
    • AI 决定调用次数和顺序
    • AI 决定何时结束对话
  2. 工具组合能力

    • 可以组合多个工具解决复杂问题
    • 先查日志,再读源码,最后分析
    • 每个工具的输出可以作为下一个工具的输入
  3. 流式用户体验

    • 实时推送 AI 思考过程
    • WebSocket 保持长连接
    • 即时显示文字回复
  4. 模型无关设计

    • 统一的 Provider 接口
    • 支持 Anthropic 和 15+ OpenAI Compatible 模型
    • 轻松扩展新模型
  5. 状态管理

    • 完整保存对话历史
    • 支持上下文理解
    • 并发安全的会话管理

这就是为什么 Willknow 能够智能地分析代码和日志,而不需要人工编写复杂的诊断逻辑!

配置选项

type Config struct {
    // 源码路径(容器内)
    // 默认:/app/source
    SourcePath string

    // 日志文件路径
    // 留空会在启动时让 AI 自动分析代码找到日志文件
    LogFiles []string

    // AI 助手 Web UI 端口
    // 默认:8888
    Port int

    // AI 提供商
    // 支持:anthropic, openai, deepseek, qwen, moonshot, glm, xai,
    //       minimax, baichuan, 01ai, groq, together, siliconflow, custom
    // 默认:anthropic
    Provider string

    // AI API Key(必填)
    APIKey string

    // AI 模型(可选)
    // 留空使用提供商的默认模型
    Model string

    // 自定义 API Endpoint(可选)
    // 用于公司内部部署的模型或代理
    // Provider="custom" 时必填
    BaseURL string
}
使用示例

使用 DeepSeek:

assistant, _ := aiassistant.New(aiassistant.Config{
    Provider: "deepseek",
    APIKey:   os.Getenv("DEEPSEEK_API_KEY"),
})

使用通义千问:

assistant, _ := aiassistant.New(aiassistant.Config{
    Provider: "qwen",
    APIKey:   os.Getenv("QWEN_API_KEY"),
})

使用公司内部模型:

assistant, _ := aiassistant.New(aiassistant.Config{
    Provider: "custom",
    BaseURL:  "http://internal-llm.company.com/v1",
    APIKey:   "internal-key",
    Model:    "company-model-v1",
})

最佳实践

  1. 日志格式:确保日志包含 RequestID,方便追踪
  2. 源码位置:在 Dockerfile 中复制源码到 /app/source
  3. API Key 安全:通过环境变量传递,不要硬编码
  4. 仅开发/测试环境:MVP 版本无认证,不建议生产环境使用

常见问题

Q: AI 助手找不到日志文件怎么办?

A: 手动指定 LogFiles 配置项,或在代码中明确配置日志路径。

Q: 支持哪些日志格式?

A: 支持文本日志和 JSON 日志,AI 会自动识别和解析。

Q: 如何在 Kubernetes 中使用?

A: 确保在 Deployment 中暴露 8888 端口,并通过 Secret 传递 API Key。

Q: 会暴露源代码吗?

A: MVP 版本无认证,只建议在开发/测试环境使用。生产环境需要额外的安全控制。

技术栈

  • 后端:Go 1.21+
  • AI 模型
    • Anthropic Claude (独立实现)
    • OpenAI Compatible (15+ 模型)
      • DeepSeek, 通义千问, 智谱 GLM, Moonshot, XAI Grok 等
      • 支持自定义内部模型
  • WebSocket:gorilla/websocket
  • 前端:原生 HTML/CSS/JavaScript

路线图

MVP (当前版本):

  • ✅ 基础 AI 对话功能
  • ✅ 代码和日志分析
  • ✅ 简单 Web UI
  • ✅ 认证和权限控制
  • ✅ 内置代码索引(基于 LLM 生成的文件摘要)

未来计划:

  • 外部向量数据库集成(Weaviate + Embedding API 实现语义搜索)
  • 支持更多语言(Python, Node.js 等)
  • 更强大的前端界面

贡献

欢迎提交 Issue 和 Pull Request!

许可证

MIT License

致谢

本项目灵感来源于 Claude Code 和现代 AI 辅助开发工具。

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type AgentCapability

type AgentCapability struct {
	Name        string `json:"name"`
	Description string `json:"description"`
}

AgentCapability describes a single capability

type AgentChatRequest

type AgentChatRequest struct {
	Message   string `json:"message"`
	SessionID string `json:"session_id"`
}

AgentChatRequest is the JSON body for POST /willknow/chat

type AgentChatResponse

type AgentChatResponse struct {
	Message   string `json:"message"`
	SessionID string `json:"session_id"`
}

AgentChatResponse is the JSON response for POST /willknow/chat

type AgentInfo

type AgentInfo struct {
	// Name is the agent's display name
	// Default: OpenAPI spec's info.title
	Name string

	// Description describes what this agent can do
	// Default: OpenAPI spec's info.description
	Description string
}

AgentInfo holds identity information for the agent discovery endpoint

type AgentInfoAuth

type AgentInfoAuth struct {
	Required bool   `json:"required"`
	Type     string `json:"type"` // "bearer", "none"
}

AgentInfoAuth describes authentication requirements

type AgentInfoResponse

type AgentInfoResponse struct {
	Name         string            `json:"name"`
	Description  string            `json:"description"`
	ChatEndpoint string            `json:"chat_endpoint"`
	Auth         AgentInfoAuth     `json:"authentication"`
	Capabilities []AgentCapability `json:"capabilities"`
}

AgentInfoResponse is the JSON response for /willknow/info

type Assistant

type Assistant struct {
	// contains filtered or unexported fields
}

Assistant is the main AI assistant instance

func New

func New(config Config) (*Assistant, error)

New creates a new AI Assistant instance

func (*Assistant) Start

func (a *Assistant) Start() error

Start starts the AI Assistant web server

type AuthConfig

type AuthConfig struct {
	// GetUser is called on every request to identify the current user.
	// - Set to a custom function to integrate with your existing auth system.
	//   If the function returns an error, the request is rejected with 401.
	// - Set to aiassistant.NoAuth to explicitly disable authentication.
	// - Leave nil (default) to use built-in password protection.
	GetUser GetUserFunc

	// Password is used only in password protection mode (when GetUser is nil).
	// If empty, willknow generates a random password and prints it to the console.
	// If set, uses this password.
	Password string
}

AuthConfig configures authentication for the AI assistant.

Three modes (in priority order):

  1. GetUser set to custom function → host system auth (highest priority)
  2. GetUser set to NoAuth → fully open, no authentication required
  3. GetUser not set (nil) → password protection mode (default)

type AuthManager

type AuthManager struct {
	// contains filtered or unexported fields
}

AuthManager handles authentication logic

type ChatMessage

type ChatMessage struct {
	Content string `json:"content"`
}

ChatMessage represents a chat message from the client

type ChatResponse

type ChatResponse struct {
	Type      string `json:"type"`                // "text", "error", "done", "session_info"
	Content   string `json:"content"`             // text content
	SessionID string `json:"sessionId,omitempty"` // session identifier
}

ChatResponse represents a response to the client

type Config

type Config struct {
	// SourcePath is the path to the application source code
	// Default: /app/source
	SourcePath string

	// LogFiles are the paths to log files
	// If empty, the assistant will try to auto-detect log files on startup
	LogFiles []string

	// Port is the port to run the web UI on
	// Default: 8888
	Port int

	// Provider is the AI provider to use
	// Supported: anthropic, openai, deepseek, qwen, moonshot, glm, xai, minimax, baichuan, 01ai, groq, together, siliconflow, custom
	// Default: anthropic
	Provider string

	// APIKey is the API key for the provider
	APIKey string

	// Model is the model to use
	// If empty, uses the provider's default model
	Model string

	// BaseURL is the custom API endpoint (for custom or self-hosted providers)
	// If empty, uses the provider's default endpoint
	// Required for Provider="custom"
	BaseURL string

	// Auth configures authentication for the AI assistant.
	// See AuthConfig for details on the three supported modes.
	Auth AuthConfig

	// EnableCodeIndex enables built-in code indexing using LLM-generated summaries.
	// When enabled, the assistant will scan source files at startup and build a searchable index.
	// The index is cached to ./code_index.json with 24-hour TTL.
	// Default: false (disabled)
	EnableCodeIndex bool

	// APISpec is the path to an OpenAPI spec file (YAML or JSON).
	// When configured, the assistant automatically becomes an AI agent capable of calling
	// the host system's APIs. This enables external AI systems to interact with the host
	// through a single natural-language chat interface (/willknow/chat).
	// Default: "" (disabled)
	APISpec string

	// HostBaseURL is the base URL for executing API calls when APISpec is configured.
	// Defaults to the first server URL in the OpenAPI spec.
	// Example: "http://localhost:8080"
	HostBaseURL string

	// AgentInfo describes this agent's identity for the /willknow/info discovery endpoint.
	// Defaults to values from the OpenAPI spec's info section.
	AgentInfo AgentInfo
}

Config holds the configuration for the AI Assistant

type GetUserFunc

type GetUserFunc func(r *http.Request) (*User, error)

GetUserFunc is the function signature for custom user authentication. Provided by the host application to integrate with its existing auth system.

var NoAuth GetUserFunc = func(r *http.Request) (*User, error) {
	return &User{ID: "anonymous", Name: "Anonymous"}, nil
}

NoAuth is a sentinel GetUserFunc that explicitly disables authentication. Use this when you want to allow unrestricted access to the assistant.

Example:

assistant, _ := aiassistant.New(aiassistant.Config{
    Auth: aiassistant.AuthConfig{GetUser: aiassistant.NoAuth},
})

type Session

type Session struct {
	ID   string
	User *User
	// contains filtered or unexported fields
}

Session manages a chat session

type User

type User struct {
	ID    string
	Name  string
	Email string
}

User represents an authenticated user

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL