Skip to content
This repository was archived by the owner on Jul 16, 2025. It is now read-only.

Commit 916bd2d

Browse files
committed
Fix after review
1 parent 6659849 commit 916bd2d

File tree

5 files changed

+142
-11
lines changed

5 files changed

+142
-11
lines changed

README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -350,23 +350,23 @@ $eventDispatcher->addListener(ToolCallsExecuted::class, function (ToolCallsExecu
350350
LLM Chain supports document embedding and similarity search using vector stores like ChromaDB, Azure AI Search, MongoDB
351351
Atlas Search, or Pinecone.
352352

353-
For populating a vector store, LLM Chain provides the service `EmbeddingProvider`, which requires an instance of an
353+
For populating a vector store, LLM Chain provides the service `Embedder`, which requires an instance of an
354354
`EmbeddingsModel` and one of `StoreInterface`, and works with a collection of `Document` objects as input:
355355

356356
```php
357-
use PhpLlm\LlmChain\EmbeddingProvider;
357+
use PhpLlm\LlmChain\Embedder;
358358
use PhpLlm\LlmChain\Bridge\OpenAI\Embeddings;
359359
use PhpLlm\LlmChain\Bridge\OpenAI\PlatformFactory;
360360
use PhpLlm\LlmChain\Bridge\Pinecone\Store;
361361
use Probots\Pinecone\Pinecone;
362362
use Symfony\Component\HttpClient\HttpClient;
363363

364-
$embeddingProvider = new EmbeddingProvider(
364+
$embedder = new Embedder(
365365
PlatformFactory::create($_ENV['OPENAI_API_KEY']),
366366
new Embeddings(),
367367
new Store(Pinecone::client($_ENV['PINECONE_API_KEY'], $_ENV['PINECONE_HOST']),
368368
);
369-
$embeddingProvider->embed($documents);
369+
$embedder->embed($documents);
370370
```
371371

372372
The collection of `Document` instances is usually created by text input of your domain entities:

examples/store-mongodb-similarity-search.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
use PhpLlm\LlmChain\Chain\Toolbox\Toolbox;
1212
use PhpLlm\LlmChain\Document\Metadata;
1313
use PhpLlm\LlmChain\Document\TextDocument;
14-
use PhpLlm\LlmChain\EmbeddingProvider;
14+
use PhpLlm\LlmChain\Embedder;
1515
use PhpLlm\LlmChain\Model\Message\Message;
1616
use PhpLlm\LlmChain\Model\Message\MessageBag;
1717
use Symfony\Component\Dotenv\Dotenv;
@@ -52,8 +52,8 @@
5252

5353
// create embeddings for documents
5454
$platform = PlatformFactory::create($_ENV['OPENAI_API_KEY']);
55-
$embeddingProvider = new EmbeddingProvider($platform, $embeddings = new Embeddings(), $store);
56-
$embeddingProvider->embed($documents);
55+
$embedder = new Embedder($platform, $embeddings = new Embeddings(), $store);
56+
$embedder->embed($documents);
5757

5858
// initialize the index
5959
$store->initialize();

examples/store-pinecone-similarity-search.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
use PhpLlm\LlmChain\Chain\Toolbox\Toolbox;
1111
use PhpLlm\LlmChain\Document\Metadata;
1212
use PhpLlm\LlmChain\Document\TextDocument;
13-
use PhpLlm\LlmChain\EmbeddingProvider;
13+
use PhpLlm\LlmChain\Embedder;
1414
use PhpLlm\LlmChain\Model\Message\Message;
1515
use PhpLlm\LlmChain\Model\Message\MessageBag;
1616
use Probots\Pinecone\Pinecone;
@@ -46,8 +46,8 @@
4646

4747
// create embeddings for documents
4848
$platform = PlatformFactory::create($_ENV['OPENAI_API_KEY']);
49-
$embeddingProvider = new EmbeddingProvider($platform, $embeddings = new Embeddings(), $store);
50-
$embeddingProvider->embed($documents);
49+
$embedder = new Embedder($platform, $embeddings = new Embeddings(), $store);
50+
$embedder->embed($documents);
5151

5252
$llm = new GPT(GPT::GPT_4O_MINI);
5353

src/EmbeddingProvider.php renamed to src/Embedder.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
use Symfony\Component\Clock\Clock;
1414
use Symfony\Component\Clock\ClockInterface;
1515

16-
final readonly class EmbeddingProvider
16+
final readonly class Embedder
1717
{
1818
private ClockInterface $clock;
1919

tests/EmbedderTest.php

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace PhpLlm\LlmChain\Tests;
6+
7+
use PhpLlm\LlmChain\Bridge\OpenAI\Embeddings;
8+
use PhpLlm\LlmChain\Document\Metadata;
9+
use PhpLlm\LlmChain\Document\TextDocument;
10+
use PhpLlm\LlmChain\Document\Vector;
11+
use PhpLlm\LlmChain\Document\VectorDocument;
12+
use PhpLlm\LlmChain\Embedder;
13+
use PhpLlm\LlmChain\Model\Message\ToolCallMessage;
14+
use PhpLlm\LlmChain\Model\Response\AsyncResponse;
15+
use PhpLlm\LlmChain\Model\Response\ToolCall;
16+
use PhpLlm\LlmChain\Model\Response\VectorResponse;
17+
use PhpLlm\LlmChain\Platform;
18+
use PhpLlm\LlmChain\Tests\Double\PlatformTestHandler;
19+
use PhpLlm\LlmChain\Tests\Double\TestStore;
20+
use PHPUnit\Framework\Attributes\CoversClass;
21+
use PHPUnit\Framework\Attributes\Medium;
22+
use PHPUnit\Framework\Attributes\Test;
23+
use PHPUnit\Framework\Attributes\UsesClass;
24+
use PHPUnit\Framework\TestCase;
25+
use Psr\Log\LoggerInterface;
26+
use Symfony\Component\Clock\MockClock;
27+
use Symfony\Component\Uid\Uuid;
28+
29+
#[CoversClass(Embedder::class)]
30+
#[Medium]
31+
#[UsesClass(TextDocument::class)]
32+
#[UsesClass(Vector::class)]
33+
#[UsesClass(VectorDocument::class)]
34+
#[UsesClass(ToolCallMessage::class)]
35+
#[UsesClass(ToolCall::class)]
36+
#[UsesClass(Embeddings::class)]
37+
#[UsesClass(Platform::class)]
38+
#[UsesClass(AsyncResponse::class)]
39+
#[UsesClass(VectorResponse::class)]
40+
final class EmbedderTest extends TestCase
41+
{
42+
#[Test]
43+
public function embedSingleDocument(): void
44+
{
45+
$document = new TextDocument($id = Uuid::v4(), 'Test content');
46+
$vector = new Vector([0.1, 0.2, 0.3]);
47+
48+
$embedder = new Embedder(
49+
PlatformTestHandler::createPlatform(new VectorResponse($vector)),
50+
new Embeddings(),
51+
$store = new TestStore(),
52+
new MockClock(),
53+
);
54+
55+
$embedder->embed($document);
56+
57+
self::assertCount(1, $store->documents);
58+
self::assertInstanceOf(VectorDocument::class, $store->documents[0]);
59+
self::assertSame($id, $store->documents[0]->id);
60+
self::assertSame($vector, $store->documents[0]->vector);
61+
}
62+
63+
#[Test]
64+
public function embedEmptyDocumentList(): void
65+
{
66+
$logger = $this->createMock(LoggerInterface::class);
67+
$logger->expects($this->once())->method('debug')->with('No documents to embed');
68+
69+
$embedder = new Embedder(
70+
PlatformTestHandler::createPlatform(),
71+
new Embeddings(),
72+
$store = new TestStore(),
73+
new MockClock(),
74+
$logger,
75+
);
76+
77+
$embedder->embed([]);
78+
79+
self::assertSame([], $store->documents);
80+
}
81+
82+
#[Test]
83+
public function embedDocumentWithMetadata(): void
84+
{
85+
$metadata = new Metadata(['key' => 'value']);
86+
$document = new TextDocument($id = Uuid::v4(), 'Test content', $metadata);
87+
$vector = new Vector([0.1, 0.2, 0.3]);
88+
89+
$embedder = new Embedder(
90+
PlatformTestHandler::createPlatform(new VectorResponse($vector)),
91+
new Embeddings(),
92+
$store = new TestStore(),
93+
new MockClock(),
94+
);
95+
96+
$embedder->embed($document);
97+
98+
self::assertSame(1, $store->addCalls);
99+
self::assertCount(1, $store->documents);
100+
self::assertInstanceOf(VectorDocument::class, $store->documents[0]);
101+
self::assertSame($id, $store->documents[0]->id);
102+
self::assertSame($vector, $store->documents[0]->vector);
103+
self::assertSame(['key' => 'value'], $store->documents[0]->metadata->getArrayCopy());
104+
}
105+
106+
#[Test]
107+
public function embedWithSleep(): void
108+
{
109+
$vector1 = new Vector([0.1, 0.2, 0.3]);
110+
$vector2 = new Vector([0.4, 0.5, 0.6]);
111+
112+
$document1 = new TextDocument(Uuid::v4(), 'Test content 1');
113+
$document2 = new TextDocument(Uuid::v4(), 'Test content 2');
114+
115+
$embedder = new Embedder(
116+
PlatformTestHandler::createPlatform(new VectorResponse($vector1, $vector2)),
117+
new Embeddings(),
118+
$store = new TestStore(),
119+
$clock = new MockClock('2024-01-01 00:00:00'),
120+
);
121+
122+
$embedder->embed(
123+
documents: [$document1, $document2],
124+
sleep: 3
125+
);
126+
127+
self::assertSame(1, $store->addCalls);
128+
self::assertCount(2, $store->documents);
129+
self::assertSame('2024-01-01 00:00:03', $clock->now()->format('Y-m-d H:i:s'));
130+
}
131+
}

0 commit comments

Comments
 (0)