Neuron 基础设施(LLM / 记忆 / Embedding / HTTP)

July 10, 2026 · View on GitHub

封装 Neuron AI 在 Swoolefy 中的装配:Provider 工厂、会话记忆、协程 HTTP、Embedding、出站 URL 校验。

  • 配置:Config/neuron_ai.php(模版 src/Stubs/neuron_ai.conf.stub.phpcreate 命令自动复制)
  • 架构设计:SwoolefyAI.md §4.4 / §4.11
  • Chat History 文档:Neuron Chat History

目录结构

Neuron/
├── NeuronFactory.php            # boot/create Agent:Provider + MCP(不强制 Memory)
├── NeuronProviderFactory.php
├── Schema/
│   ├── chat_history.sql         # SQLChatHistory 热存储(使用前须建表)
│   └── chat_messages.sql        # SqlChatHistoryArchive 冷归档(使用前须建表)
├── Memory/
│   ├── ChatHistoryFactory.php       # Agent::chatHistory() 选用后端
│   ├── SqlChatHistory.php           # SQL 热存储(tenant + thread 隔离)
│   ├── ChatHistoryPdoResolver.php   # 组件容器解析 PDO
│   ├── RedisChatHistory.php         # Redis 热存储
│   ├── HotChatHistoryInterface.php
│   └── SqlChatHistoryArchive.php    # 可选:逐条冷归档
├── Http/
├── Embedding/
└── Tests/

核心原理

业务 Agent
  protected function chatHistory(): ChatHistoryInterface
      └─ ChatHistoryFactory::inMemory() | sql() | redis() | file()

NeuronFactory::create / boot
  ├─ applyProvider(节点 provider 别名或 default;baseUri 经 OutboundUrlGuard)
  ├─ setChatHistory(仅当 agentOptions['chatHistory'] 显式传入)
  ├─ addTool(mcpServers + tenantId / FrameworkContext)
  └─ attachMiddleware(agentOptions['middleware'] / ['globalMiddleware'])

会话记忆由 Agent 自身chatHistory() 中声明。Redis / SQL 后端连接失败会写入 SupportLog

Agent Middleware

Neuron Agent Middleware 对齐。Agent 子类可覆盖 middleware() / globalMiddleware();也可在 NeuronFactoryagentOptions 中追加:

use NeuronAI\Agent\Middleware\Summarization;
use NeuronAI\Agent\Nodes\ChatNode;
use NeuronAI\Agent\Nodes\StreamingNode;
use NeuronAI\Agent\Nodes\StructuredOutputNode;

$agent = $factory->create(MyAgent::class, $state, [
    'globalMiddleware' => [$recordingMiddleware],
    'middleware' => [
        // 实例,或 callable(Agent): WorkflowMiddleware(便于使用 boot 后的 Provider)
        ChatNode::class => [
            fn ($agent) => new Summarization($agent->resolveProvider(), maxTokens: 10000, messagesToKeep: 5),
        ],
        StreamingNode::class => [/* 同上实例 */],
        StructuredOutputNode::class => [/* 同上实例 */],
    ],
]);

演示接口:POST /api/v1/agent/middleware/chatAgentMiddlewareController)。

Provider Fallback

默认 Provider 可配置为 Neuron 官方 RouterProvider fallback chain。default_provider 永远作为主用 Provider;neuron.provider_fallback.order 非空时启用 fallback,并只声明备用 Provider 顺序:

'neuron' => [
    'default_provider' => 'deepseek',
    'provider_fallback' => [
        'order' => ['openai', 'anthropic'],
    ],
]

环境变量 NEURON_PROVIDER_FALLBACK_ORDER=openai,anthropic 可覆盖备用顺序;为空时不启用 RouterProvider。实际尝试顺序为 default_providerprovider_fallback.order...(自动去重)。Fallback 仅由 RouterProvider 默认策略处理瞬时错误(网络 / 超时、429、5xx);鉴权错误、参数错误等确定性错误不会切换。stream() 只会在首个 chunk 输出前失败时切换,输出开始后的错误会原样抛出。子 Provider 仍通过构造参数注入 NeuronHttpFactory::create();对 RouterProvider 调用 setHttpClient() 时,官方实现会转发给所有已注册 Provider。

Embedding(Phase A)

rag.embedding_dimension 须与各 vector_stores.*.dimension 一致。生产环境须配置 API Key;未配置且 allow_fake_embeddings=falseEmbeddingFactory::make() fail-fast 抛错。

本地 / 单测可设 NEURON_ALLOW_FAKE_EMBEDDINGS=1 或配置 allow_fake_embeddings: true(使用 FakeEmbeddingsProvider,维度与 embedding_dimension 对齐)。


RAG 环境变量(.env)

常量定义见 NeuronAiRagEnv.php。在 APP_PATH/.env 中配置,经 env() 读取;优先级.env 环境变量 > Config/neuron_ai.php > 下表默认值。

运行时也可直接调用静态方法,例如 NeuronAiRagEnv::milvusUri()

全局 RAG

变量名说明未配置时的默认值
RAG_VECTOR_STORE默认向量库别名(须与 neuron_ai.phprag.vector_stores 的 key 一致;可被节点 / Factory 的 storeAlias 覆盖)file(来自 neuron_ai.phpdefault_vector_store
RAG_FILE_STORE_PATHfile 驱动根目录;实际存储路径为 {path}/{tenantId}_{knowledgeBase}//tmp/swoolefy_rag
RAG_DEFAULT_TOP_K相似度检索默认返回条数5
RAG_EMBEDDING_MODELOpenAI Embedding 模型名(EmbeddingFactory 使用)text-embedding-3-small
RAG_EMBEDDING_DIMENSIONEmbedding 输出向量维度;须与各 vector_stores.*.dimension 一致1536
NEURON_ALLOW_FAKE_EMBEDDINGS无 API Key 时是否允许 FakeEmbeddings(1/true 开启);生产须为 falsefalse
RAG_REQUIRE_TENANT_ISOLATION是否强制多租户隔离:RAG 知识库前缀 {tenantId}_{kb}、Redis ChatHistory key 含 tenant;无 tenant 时 fail-fast(1/true 开启);生产须为 truetrue
NEURON_TENANT_IDCLI 入库 / 脚本场景的 tenant(等同 HTTP x-tenant-id;RAG CLI 亦支持 --tenant-id=
RAG_INGEST_MODERAG 入库模式:sync 同步写入;queue 调配置化 producer 写队列sync
RAG_INGEST_PRODUCER_CLASS队列 producer 类名,方法接收 RagIngestJob
RAG_INGEST_PRODUCER_METHODproducer 方法名push
RAG_INGEST_CONSUMER_CLASS队列 consumer 类名,方法接收 RagIngestJob, IngestionPipeline
RAG_INGEST_CONSUMER_METHODconsumer 方法名handle

Meilisearch(vector_stores.meilisearch

变量名说明未配置时的默认值
MEILISEARCH_HOSTMeilisearch HTTP 地址http://localhost:7700
MEILISEARCH_KEYAPI Key(Master Key)空(使用该驱动前须配置)
MEILISEARCH_EMBEDDERMeilisearch 内置 embedder 名称default
MEILISEARCH_DIMENSION向量维度1536

知识库名映射为 Meilisearch indexUid(经 TenantScope 加 tenant 前缀)。

PHPVector(vector_stores.phpvector

变量名说明未配置时的默认值
RAG_PHPVECTOR_PATH纯 PHP HNSW 存储根目录;路径为 {path}/{tenantId}_{knowledgeBase}//tmp/swoolefy_phpvector

composer require neuron-core/php-vector

MariaDB VECTOR(vector_stores.mariadb

变量名说明未配置时的默认值
RAG_MARIADB_COMPONENT数据库组件别名(对应 Config/component/database.phpdb
RAG_MARIADB_TABLE_NAME表名前缀;实际表名为 {table_name}_{tenantId}_{knowledgeBase}rag_documents

需 MariaDB ≥ 11.7 且支持 VECTOR 类型。

PostgreSQL pgvector(vector_stores.pgvector

变量名说明未配置时的默认值
RAG_PGVECTOR_COMPONENTPostgreSQL 数据库组件别名(对应 Config/component/database.phppg
RAG_PGVECTOR_TABLE_NAME表名前缀;实际表名为 {table_name}_{tenantId}_{knowledgeBase}rag_documents
RAG_PGVECTOR_DIMENSIONpgvector 向量维度;须与 RAG_EMBEDDING_DIMENSION 一致1536
RAG_PGVECTOR_METRIC距离度量:cosinel2ipcosine

需 PostgreSQL 已安装 pgvector 扩展。PgVectorStore 运行期不会自动创建扩展、表或索引;生产上线前须由迁移脚本 / DBA 预先执行 CREATE EXTENSION vector、建表和 HNSW 索引。

Pinecone(vector_stores.pinecone

变量名说明未配置时的默认值
PINECONE_API_KEYPinecone API Key空(使用该驱动前须配置)
PINECONE_INDEX_URL全局 Index URL空(使用该驱动前须配置)
PINECONE_API_VERSIONPinecone API 版本2025-04

知识库名映射为 Pinecone namespace(经 tenant 前缀隔离)。

Qdrant(vector_stores.qdrant

变量名说明未配置时的默认值
QDRANT_BASE_URLQdrant REST 根地址http://localhost:6333
QDRANT_API_KEYAPI Key(可选,视部署而定)
QDRANT_DIMENSIONCollection 向量维度1536

Collection URL 为 {base_url}/collections/{tenantId}_{knowledgeBase}/

Milvus(vector_stores.milvus

变量名说明未配置时的默认值
MILVUS_URIMilvus HTTP 端点(阿里云示例:http://c-xxxx.milvus.aliyuncs.com:19530http://localhost:19530
MILVUS_USER用户名(常与 MILVUS_PASSWORD 配对,阿里云常见)
MILVUS_PASSWORD密码
MILVUS_TOKENJWT / API Token;与 user+password 二选一(同时配置时 client 优先 token)
MILVUS_DB_NAMEMilvus 数据库名default
MILVUS_DIMENSIONCollection 向量维度;须与 RAG_EMBEDDING_DIMENSION 一致1536

知识库名映射为独立 Collection(经 tenant 前缀隔离);首次写入自动建表。

.env 示例

# 全局
RAG_VECTOR_STORE=file
RAG_FILE_STORE_PATH=/data/rag
RAG_EMBEDDING_MODEL=text-embedding-3-small
RAG_EMBEDDING_DIMENSION=1536
RAG_REQUIRE_TENANT_ISOLATION=1

# 生产:须配置真实 Embedding Key,且勿开 Fake
# NEURON_ALLOW_FAKE_EMBEDDINGS=0

# Milvus 生产示例
# RAG_VECTOR_STORE=milvus
# MILVUS_URI=http://c-xxxx.milvus.aliyuncs.com:19530
# MILVUS_USER=root
# MILVUS_PASSWORD=****
# MILVUS_DIMENSION=1536

# PostgreSQL pgvector 生产示例
# RAG_VECTOR_STORE=pgvector
# RAG_PGVECTOR_COMPONENT=pg
# RAG_PGVECTOR_TABLE_NAME=rag_documents
# RAG_PGVECTOR_DIMENSION=1536
# RAG_PGVECTOR_METRIC=cosine

CLI 入库脚本在无 HTTP 上下文时可额外设置 NEURON_TENANT_ID(或 --tenant-id=),与 x-tenant-id 请求头等效。


业务 Agent 示例

InMemory(单次请求,无持久化)

final class EphemeralChatAgent extends Agent
{
    protected function chatHistory(): ChatHistoryInterface
    {
        return ChatHistoryFactory::inMemory(50000);
    }
}

SQL 持久化多轮(SqlChatHistory)

使用前必须先执行 Schema/chat_history.sql 创建 chat_history 表(含 tenant_id / user_id / 软删 deleted_at)。

final class ChatAgent extends Agent
{
    public function __construct(
        private readonly string $threadId,
        private readonly \PDO $pdo,
        private readonly ?string $tenantId = null, // 缺省读 x-tenant-id
        private readonly ?string $userId = null,   // 缺省读 x-user-id
    ) {
        parent::__construct();
    }

    protected function chatHistory(): ChatHistoryInterface
    {
        return ChatHistoryFactory::sql(
            threadId: $this->threadId,
            pdo: $this->pdo,
            tenantId: $this->tenantId,
            userId: $this->userId,
        );
    }
}

// Controller
$pdo = ChatHistoryPdoResolver::resolve('db');
$agent = $neuronFactory->boot(new ChatAgent($threadId, $pdo), [
    'provider' => 'deepseek',
]);

建表脚本:src/Support/Neuron/Schema/chat_history.sql

-- 见 Schema/chat_history.sql(uk_tenant_thread + messages JSON)

SQL 冷归档(逐条消息,可选)

使用前必须先执行 Schema/chat_messages.sql 创建 chat_messages 表。

$archive = ChatHistoryFactory::archive($pdo, tenantId: 'tenant_a', userId: 'user_1');
$archive->archiveMessage($threadId, 'user', 'Hello');
$messages = $archive->listMessages($threadId, 50);

建表脚本:src/Support/Neuron/Schema/chat_messages.sql

Redis

protected function chatHistory(): ChatHistoryInterface
{
    return ChatHistoryFactory::redis($this->threadId, $redisConnection);
}

NeuronFactory

// 无参 Agent
$agent = $factory->create(ChatAgent::class, $state, ['provider' => 'openai']);

// 带构造参数的 Agent(自行决定 chatHistory)
$agent = $factory->boot(new ChatAgent($threadId, $pdo), ['provider' => 'deepseek']);

节点 MCP 工具加载时,NeuronFactory 会将 tenantId(节点 config 或 FrameworkContext::getTenantId())传给 McpFactory


安全与启动检查(Phase B)

neuron_ai.phpsecurity

配置说明
outbound_url_allowlistLLM Provider baseUri 与 MCP url 的 host 后缀白名单
allow_private_networks是否允许指向私网 / loopback(默认 false)

部署前调用 Swoolefy\Support\ProductionHealthCheck::run() 校验 Embedding、向量库别名、出站 URL 等。该检查也覆盖 Workflow 生产安全项:SWOOLEFY_ENV=prd 时要求 HITL 鉴权开启、WORKFLOW_HITL_API_KEY 已配置,并拦截过短的 Redis RunStore TTL。


运行测试

composer test:neuron
composer test:phase-a
composer test:phase-b