We want to get your feedback on this proposal early,
so that we can directly include it :)
In our releases over the last few months, we solved specific use cases by integrating a chat-based AI into Neos CMS. We optimized prompts and integrated external services.
But the great strength of the Neos Community lies creative and smart developers. We aim to empower you to implement your use cases.
The following proposal outlines extension points for developers:
Is the naming consistent and clear? Are the options suitable for the use cases you can think of? How could this be even better?
Or on Slack #neos-general and mention @rolandschuetz
Writing effective briefings drastically improves the quality of the generated text. You might want your editors to follow specific templates, and use page-specific briefings and target audiences.
We propose two new options:
Both options support ClientEval and we use JavaScript String literals to generate the text in this example:
'Vendor.Site:Document.LangingPage':
...
ui:
inspector:
groups:
briefing:
label: Page Briefing
icon: route
position: 10
tab: seo
options:
sidekick:
focusKeyword: 'ClientEval: node.properties.focusKeyword'
targetAudience: 'ClientEval: node.properties.targetAudience'
pageBriefing: 'ClientEval: node.properties.problemDescription && `The page should first describe the following problem: ${node.properties.problemDescription}. Then it should describe how we solve it: ${node.properties.problemSolutionDescription || ''}. Our goal is to optimize conversions.`'
properties:
focusKeyword:
type: string
ui:
label: SEO Focus Keyword
inspector:
group: 'briefing'
position: 10
editor: 'Neos.Neos/Inspector/Editors/TextFieldEditor'
targetAudience:
type: string
ui:
label: Target Audience
inspector:
group: 'briefing'
position: 20
editor: 'Neos.Neos/Inspector/Editors/TextAreaEditor'
validation:
'Neos.Neos/Validation/StringLengthValidator':
maximum: 450
problemDescription:
type: string
ui:
label: Customers Problem
inspector:
group: 'briefing'
position: 30
editor: 'Neos.Neos/Inspector/Editors/TextAreaEditor'
validation:
'Neos.Neos/Validation/StringLengthValidator':
maximum: 450
problemSolutionDescription:
type: string
ui:
label: How we solve it
inspector:
group: 'briefing'
position: 40
editor: 'Neos.Neos/Inspector/Editors/TextAreaEditor'
validation:
'Neos.Neos/Validation/StringLengthValidator':
maximum: 450
This would create the following inspector group for the editor.
On every change of these properties, NEOSidekick gets an updated briefing.
As an editor, many times you just want to have a decent text description without spending too much time on it.
A typical example is the meta description. Editors can just create a description based on the content of the current page with one button click.
We want to enable you to fill properties with generated text based on your own logic. This is achieved with:
'Neos.Seo:SeoMetaTagsMixin':
properties:
metaDescription:
ui:
inspector:
editor: 'NEOSidekick.AiAssistant/Inspector/Editors/MagicTextAreaEditor'
editorOptions:
placeholder: 'Neos.Seo:NodeTypes.SeoMetaTagsMixin:properties.metaDescription.textAreaEditor.placeholder'
module: 'meta_description'
Another common case is the generation of alternative text for an image. We aim to define a general API for many modules to come.
Our proposed API:
'Vendor.Site:Content.Image':
superTypes:
'Neos.Neos:Content': true
ui:
label: Image
properties:
image:
type: Neos\Media\Domain\Model\ImageInterface
ui:
label: 'Image'
reloadIfChanged: true
showInCreationDialog: true
inspector:
group: general
position: 50
alternativeText:
type: string
ui:
label: 'Alternative Text'
reloadIfChanged: false
inspector:
group: general
position: 100
editor: 'NEOSidekick.AiAssistant/Inspector/Editors/MagicTextAreaEditor'
editorOptions:
module: 'alt_tag_generator'
arguments:
url: 'ClientEval: AssetUri(node.properties.image)'
Now this is where it really get's interesting. We want to enable you as integrators to create your own text generation logic. Since text generation takes time, we aim to stream the text directly into the node property.
Let's say you intend to create a content NodeType "Magic Text", which generates a full paragraph based on the current page content and the title. You can do this with YAML:
'Vendor.Site:Content.Text':
superTypes:
'Neos.Neos:Content': true
ui:
label: Magic Text
...
properties:
title:
type: string
ui:
label: Title
showInCreationDialog: true
inlineEditable: true
text:
type: string
ui:
inlineEditable: true
options:
sidekick:
onCreate:
module: paragraph_generation
arguments:
topic: 'ClientEval: node.properties.title'
Each text generation module can have multiple arguments, based on the module. All values are evaluated on the client when you use ClientEval.
You are not dependent on our premade modules. Let's say you want to create a TLDR, then your NodeType could look as follows:
'NEOSidekick.Site:Content.TLDR':
superTypes:
'Neos.Neos:Content': true
ui:
label: TLDR
...
properties:
text:
type: string
ui:
inlineEditable: true
options:
sidekick:
onCreate:
module: free_conversation
arguments:
content: 'Generate a TLDR for this page, as a bullet point list. Make it engaging, so that visitors want to read the whole page.'
writingStyle: 'marketing_genius'
As an integrator, we want to enable you to create auto-generating nodes and fill them with text. Since text generation takes time, we want to stream the text directly into the nodes.
Let's say you are creating a blog post and want to add a FAQ section. A typical FAQ has multiple child nodes.
Notice that this example is complex on purpose. We can't generate independent answers, since they should form a consistent FAQ.
We use NodeTemplates to create an FAQ section with items. Now each item can have nodes inside the answer, with one text node as default. Then we use an AI skill to fill them.
ATTENTION: This is not the final API, we are currently exploring how this can be done intuitively.
'Vendor.Site:Content.FAQ':
superTypes:
'Neos.Neos:Content': true
'Neos.Neos:ContentCollection': true
ui:
label: FAQ Section
creationDialog:
elements:
numberOfItems:
type: integer
defaultValue: 3
ui:
label: 'Questions to create:'
validation:
'Neos.Neos/Validation/NotEmptyValidator': [ ]
constraints:
nodeTypes:
'*': false
'Vendor.Site:Content.FAQ.Item': true
options:
template:
childNodes:
item:
name: '${"item" + item}'
type: 'NEOSidekick.Site:Content.FAQ.Item'
withItems: '${Array.range(1, data.numberOfItems)}'
aiProperties:
title: '${"faq_generator." + data.numberOfItems + ".question"}'
childNodes:
text:
type: 'Vendor.Site:Content.Text.Block'
properties:
text: '${"result." + data.numberOfItems + ".answer"}'
sidekick:
onCreated:
faq:
module: faq_generator
'Vendor.Site:Content.FAQ.Item':
superTypes:
'Neos.Neos:Content': true
'Neos.Neos:ContentCollection': true
ui:
label: FAQ Item
...
constraints:
nodeTypes:
'*': false
'Vendor.Site:Constraint.Content.Block': true
Is the naming consistent and clear? Are the options suitable for the use cases you can think of? How could this be even better?
Or on Slack #neos-general and mention @rolandschuetz