承接 vlados/laravel-related-content 相关项目开发

从需求分析到上线部署,全程专人跟进,保证项目质量与交付效率

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

vlados/laravel-related-content

Composer 安装命令:

composer require vlados/laravel-related-content

包简介

Build related content links using vector embeddings and pgvector for Laravel

README 文档

README

Build related content links using vector embeddings and pgvector for Laravel.

Latest Version on Packagist

Features

  • 🔗 Pre-computed Related Links - Related content is calculated on save, not on every page load
  • 🚀 Fast Lookups - O(1) relationship queries instead of real-time similarity search
  • 🔄 Cross-Model Relationships - Find related content across different model types (Blog → Events → Questions)
  • 🧠 Multiple Embedding Providers - Support for OpenAI and Ollama
  • 📦 Queue Support - Process embeddings in the background
  • 🔍 Semantic Search - Search content by meaning, not just keywords

Requirements

  • PHP 8.3+
  • Laravel 11, 12, or 13
  • PostgreSQL with pgvector extension

Installation

1. Install pgvector extension in PostgreSQL

CREATE EXTENSION IF NOT EXISTS vector;

The migration runs this automatically, but CREATE EXTENSION requires a privileged database user. On managed Postgres (RDS, Cloud SQL, Supabase, etc.) enable the extension up front — as shown above or via the provider's dashboard — so the migration only needs to create the tables.

2. Install the package via Composer

composer require vlados/laravel-related-content

3. Publish the config and migrations

php artisan vendor:publish --tag="related-content-config"
php artisan vendor:publish --tag="related-content-migrations"
php artisan migrate

4. Configure your environment

# Embedding provider (openai or ollama)
RELATED_CONTENT_PROVIDER=openai

# OpenAI settings
OPENAI_API_KEY=your-api-key
OPENAI_EMBEDDING_MODEL=text-embedding-3-small
OPENAI_EMBEDDING_DIMENSIONS=1536

# Or Ollama settings
OLLAMA_BASE_URL=http://localhost:11434
OLLAMA_EMBEDDING_MODEL=nomic-embed-text

Usage

1. Add the trait to your models

use Vlados\LaravelRelatedContent\Concerns\HasRelatedContent;

class BlogPost extends Model
{
    use HasRelatedContent;

    /**
     * Define which fields should be embedded.
     */
    public function embeddableFields(): array
    {
        return ['title', 'excerpt', 'content'];
    }
}

2. Configure models for cross-model relationships

In config/related-content.php:

'models' => [
    \App\Models\BlogPost::class,
    \App\Models\Event::class,
    \App\Models\Question::class,
],

3. Related content is automatically synced on save

$post = BlogPost::create([
    'title' => 'Electric Vehicle Charging Guide',
    'content' => '...',
]);

// Embedding is generated and related content is found automatically

4. Retrieve related content

// Get all related content
$related = $post->getRelatedModels();

// Get related content of a specific type
$relatedEvents = $post->getRelatedOfType(Event::class);

// Get the raw relationship with similarity scores (this model as source only)
$post->relatedContent()->with('related')->get();

getRelatedModels() and getRelatedOfType() are the complete views — they merge both directions (where this model is the source or the related target). The raw relatedContent() relation returns only the rows where this model is the source; because each pair is stored once (and refreshed on re-sync), prefer the helper methods when you want the full set.

5. Use in Blade templates

@if($post->relatedContent->isNotEmpty())
    <div class="related-content">
        <h3>Related Content</h3>
        @foreach($post->getRelatedModels(5) as $item)
            <a href="{{ $item->url }}">{{ $item->title }}</a>
        @endforeach
    </div>
@endif

Artisan Commands

Rebuild embeddings and related content

# Process models missing embeddings (default behavior)
php artisan related-content:rebuild

# Process a specific model (missing only)
php artisan related-content:rebuild "App\Models\BlogPost"

# Force regenerate all embeddings
php artisan related-content:rebuild --force

# Process synchronously (instead of queuing)
php artisan related-content:rebuild --sync

# With custom chunk size
php artisan related-content:rebuild --chunk=50

Semantic Search

You can also use the package for semantic search:

use Vlados\LaravelRelatedContent\Services\RelatedContentService;

$service = app(RelatedContentService::class);

// Search across all embeddable models
$results = $service->search('electric vehicle charging');

// Search specific model types
$results = $service->search('charging stations', [
    \App\Models\Event::class,
    \App\Models\BlogPost::class,
]);

// By default search returns the closest N matches regardless of distance.
// Pass a minimum similarity (0-1) to filter out weak matches:
$results = $service->search('charging stations', [], limit: 10, threshold: 0.5);

Configuration

return [
    // Embedding provider: 'openai' or 'ollama'
    'provider' => env('RELATED_CONTENT_PROVIDER', 'openai'),

    // Provider-specific settings
    'providers' => [
        'openai' => [
            'api_key' => env('OPENAI_API_KEY'),
            'base_url' => env('OPENAI_BASE_URL', 'https://api.openai.com/v1'),
            'model' => env('OPENAI_EMBEDDING_MODEL', 'text-embedding-3-small'),
            'dimensions' => env('OPENAI_EMBEDDING_DIMENSIONS', 1536),
        ],
        'ollama' => [
            'base_url' => env('OLLAMA_BASE_URL', 'http://localhost:11434'),
            'model' => env('OLLAMA_EMBEDDING_MODEL', 'nomic-embed-text'),
            'dimensions' => env('OLLAMA_EMBEDDING_DIMENSIONS', 768),
        ],
    ],

    // Maximum related items per model
    'max_related_items' => 10,

    // Minimum similarity threshold (0-1)
    'similarity_threshold' => 0.5,

    // Queue settings
    'queue' => [
        'connection' => 'default',
        'name' => 'default',
    ],

    // Models to include in cross-model relationships
    'models' => [],

    // Database table names
    'tables' => [
        'embeddings' => 'embeddings',
        'related_content' => 'related_content',
    ],
];

Embedding dimensions

The active provider's dimensions value is the single source of truth. It sizes the vector column when the migration runs and determines the length of every stored vector, so the two can never drift. The top-level dimensions key is only a fallback used when the active provider does not define its own.

Because the column width is fixed at migration time, changing the effective dimension count (or switching to a provider with a different one) requires a fresh migration of the embeddings table — re-run related-content:rebuild afterwards to regenerate the vectors.

Disabling

Set RELATED_CONTENT_ENABLED=false (or leave the provider's credentials empty) and the package degrades gracefully: no jobs are dispatched and no embeddings are written, so existing rows are left untouched.

Events

The package dispatches events you can listen to:

use Vlados\LaravelRelatedContent\Events\RelatedContentSynced;

class HandleRelatedContentSynced
{
    public function handle(RelatedContentSynced $event): void
    {
        // $event->model - The model that was synced
    }
}

How It Works

  1. On Model Save: When a model with HasRelatedContent is saved, a job is dispatched
  2. Generate Embedding: The job generates a vector embedding from the model's embeddable fields
  3. Find Similar: Uses pgvector to find similar content across all configured models
  4. Store Links: Stores the related content relationships in the related_content table
  5. Fast Retrieval: When displaying related content, it's a simple database lookup (no API calls)

Bidirectional Relationships

Related content works in both directions automatically. When a new BlogPost is saved and finds an Event as related, the Event will also show the BlogPost in its related content - without needing to re-sync the Event.

This is achieved by querying both directions:

  • Forward: where this model is the source
  • Reverse: where this model is the related target

Results are deduplicated and sorted by similarity score.

When a model is re-synced (its embeddable content changed), every link incident to it is rebuilt in both directions, so similarity scores never go stale. Links to models that are no longer mutually similar are rebuilt on their own next sync, or run related-content:rebuild --force to refresh the whole graph at once.

Search accuracy at scale

The embeddings table uses an HNSW index, which performs approximate nearest -neighbour search. When you mix several model types and filter by type (or by the similarity threshold), pgvector may occasionally return fewer than max_related_items candidates because the type filter is applied after the index narrows the search. If you rely on cross-model results over a large dataset, raise hnsw.ef_search for the session or consider pgvector 0.8+ iterative index scans.

Performance

  • Embedding Generation: ~200-500ms per model (depends on text length and provider)
  • Related Content Lookup: ~5ms (simple database query)
  • Storage: ~6KB per embedding (1536 dimensions x 4 bytes)

License

MIT License. See LICENSE for more information.

Credits

vlados/laravel-related-content 适用场景与选型建议

vlados/laravel-related-content 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 628 次下载、GitHub Stars 达 13, 最近一次更新时间为 2025 年 12 月 06 日, 在 PHP 生态内属于活跃度较高的组件。

它主要适用于以下技术方向: 「laravel」 「vectors」 「similarity」 「recommendations」 「vlados」 「embeddings」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。

我们在过去多个企业项目中使用过 vlados/laravel-related-content 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。

围绕 vlados/laravel-related-content 我们能提供哪些服务?
定制开发 / 二次开发

基于 vlados/laravel-related-content 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。

BUG 修复 & 性能优化

线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。

项目外包 & 长期维护

承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。

yvsm@zunyunkeji.com QQ:316430983 微信:yvsm316 西安尊云信息科技 · 专注 PHP / Go / 分布式系统研发

统计信息

  • 总下载量: 628
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 13
  • 点击次数: 35
  • 依赖项目数: 0
  • 推荐数: 0

GitHub 信息

  • Stars: 13
  • Watchers: 0
  • Forks: 2
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2025-12-06