atoolo / genai-bundle
Indexing resources into a GenAI application and asking it questions
Package info
github.com/sitepark/atoolo-genai-bundle
Type:symfony-bundle
pkg:composer/atoolo/genai-bundle
Requires
- php: >=8.1 <8.6.0
- atoolo/index-bundle: dev-main
- atoolo/resource-bundle: ^1
- overblog/graphql-bundle: ^1.9
- psr/log: ^3
- symfony/config: ^6.3 || ^7.4.7
- symfony/console: ^6.3 || ^7.4.7
- symfony/dependency-injection: ^6.3 || ^7.4.7
- symfony/http-client: ^6.3 || ^7.4.7
- symfony/http-client-contracts: ^2.5 || ^3
- symfony/http-foundation: ^6.3 || ^7.4.7
- symfony/http-kernel: ^6.3 || ^7.4.7
- symfony/yaml: ^6.3 || ^7.4.6
Requires (Dev)
- dealerdirect/phpcodesniffer-composer-installer: ^1.2
- infection/infection: ^0.27.11
- overtrue/phplint: ^9.7.1
- phpcompatibility/php-compatibility: ^9.3.5
- phpunit/phpunit: ^10.5.64
- roave/security-advisories: dev-latest
- squizlabs/php_codesniffer: ^3.13.5
- symfony/filesystem: ^6.3 || ^7.4.6
Suggests
None
Provides
None
Conflicts
None
Replaces
None
This package is auto-updated.
Last update: 2026-10-09 14:04:04 UTC
README
Atoolo GenAI bundle
Indexes resources into an external GenAI application - embedding and vector database - and asks that application questions. The GenAI technology itself is not part of this bundle, just as the Solr server is not part of the search-bundle.
The indexer core comes from atoolo/index-bundle; this bundle only provides the target implementation, the document, its enricher and the assistant.
Asking through GraphQL
The bundle adds a question and the feedback on its answer to the atoolo GraphQL schema:
query { genAiQuestion(query: "Wann hat das Bürgerbüro geöffnet?") { __typename ... on GenAiAnsweredQuestion { id feedbackToken } ... on GenAiAnswer { sections { __typename headline sources { url title } ... on GenAiTextSection { html } ... on GenAiLinksSection { links { url label } } } } ... on GenAiNoMatchingDocumentsError { hints { headline html sources { url title } } suggestedQuestions } } }
The result is a GenAiAnswer or an error that says why the question was not
answered: GenAiNoDocumentsError (no resource was similar enough),
GenAiNoMatchingDocumentsError (none of the resources found answers the
question; with hints how to ask more precisely and suggested questions),
GenAiAnswerCutOffError (the answer became too long and was discarded) or
GenAiUnansweredError (an error of the GenAI application this version of the
bundle does not know yet). Every result can be rated with its
feedbackToken. A question that cannot be asked at all - too long, too many
requests, the application not available - is a GraphQL error in errors
with extensions.classification BAD_REQUEST, TOO_MANY_REQUESTS or
INTERNAL_ERROR.
mutation { genAiAnswerFeedback(feedbackToken: "t-1", feedback: GOOD) }
The feedback takes the feedbackToken the answer came with, no answer id; the
GenAI application finds the answer from the token. It is valid for 15 minutes
by default; within that time the feedback can be set, changed or withdrawn
(feedback: null) as often as wanted, afterwards the mutation returns
false. An answer without a token cannot be rated. Keep the token in
the memory of the page only, never in localStorage or the URL.
Busy index
The GenAI application lets one request at a time write a source. A request
that waits longer than the application's GENAI_INDEX_LOCK_TIMEOUT - for
instance an incremental update after a publish while a bulk of a full run is
embedding - is refused with 409. The bundle then sends the index request
again after a pause, by default after 15, 30 and 60 seconds, and only fails
once every attempt was refused. Other requests and other statuses are never
repeated.
GENAI_BUSY_RETRIES sets the pauses in seconds, comma separated
(15,30,60); the number of pauses is the number of retries, an empty value
disables the retry. The lock timeout of the application must stay below
GENAI_IDLE_TIMEOUT (300 seconds by default), so that the application
answers with 409 before the bundle gives up the connection.