diff --git a/editors/demo/src/HHMI/config/config.js b/editors/demo/src/HHMI/config/config.js
index 162052fd573df0c359984459f9aba25fbf667e51..51441eab0db7264344c129c0faeedf57b3c9c1c2 100644
--- a/editors/demo/src/HHMI/config/config.js
+++ b/editors/demo/src/HHMI/config/config.js
@@ -22,10 +22,74 @@ import {
   EssayService,
   MatchingService,
   MultipleDropDownService,
+  AnyStyleService,
 } from 'wax-prosemirror-services';
 
 import { DefaultSchema } from 'wax-prosemirror-core';
 import invisibles, { hardBreak } from '@guardian/prosemirror-invisibles';
+const API_KEY = '';
+
+async function AnyStyleTransformation(prompt) {
+  const response = await fetch('https://api.openai.com/v1/chat/completions', {
+    method: 'POST',
+    headers: {
+      'Content-Type': 'application/json',
+      Authorization: `Bearer ${API_KEY}`,
+    },
+    body: JSON.stringify({
+      model: 'gpt-3.5-turbo',
+      messages: [
+        {
+          role: 'user',
+          content: prompt,
+        },
+      ],
+      temperature: 0,
+      // max_tokens: 400,
+      // n: 1,
+      // stop: null,
+    }),
+  });
+
+  try {
+    const data = await response.json();
+    console.log(data);
+    return data.choices[0].message.content;
+  } catch (e) {
+    console.error(e);
+  } finally {
+  }
+  return prompt;
+}
+
+// async function AnyStyleTransformation(prompt) {
+//   const response = await fetch('https://api.openai.com/v1/completions', {
+//     method: 'POST',
+//     headers: {
+//       'Content-Type': 'application/json',
+//       Authorization: `Bearer ${API_KEY}`,
+//     },
+//     body: JSON.stringify({
+//       model: 'text-davinci-003',
+//       prompt: prompt,
+//       max_tokens: 400,
+//       n: 1,
+//       stop: null,
+//       temperature: 0.5,
+//     }),
+//   });
+
+//   try {
+//     const data = await response.json();
+//     console.log(data);
+//     return data.choices[0].text.trim();
+//   } catch (e) {
+//     console.error(e);
+//   } finally {
+//     console.log('We do cleanup here');
+//   }
+//   return 'Nothing found';
+// }
 
 export default {
   MenuService: [
@@ -47,6 +111,7 @@ export default {
         'Lists',
         'Images',
         'Tables',
+        'AnyStyle',
         'QuestionsDropDown',
         'FullScreen',
       ],
@@ -60,6 +125,9 @@ export default {
       toolGroups: ['MultipleDropDown'],
     },
   ],
+  AnyStyleService: {
+    AnyStyleTransformation: AnyStyleTransformation,
+  },
 
   SchemaService: DefaultSchema,
   RulesService: [emDash, ellipsis],
@@ -67,6 +135,7 @@ export default {
 
   PmPlugins: [columnResizing(), tableEditing(), invisibles([hardBreak()])],
   services: [
+    new AnyStyleService(),
     new MatchingService(),
     new FillTheGapQuestionService(),
     new MultipleChoiceQuestionService(),
diff --git a/wax-prosemirror-services/index.js b/wax-prosemirror-services/index.js
index d3da09ef62f22cf882ba6965b9bb29cbbddaf4a3..ef7a4b2f8c0b6ac21bef18e8510ed99c6169cc08 100644
--- a/wax-prosemirror-services/index.js
+++ b/wax-prosemirror-services/index.js
@@ -39,6 +39,7 @@ export { default as MultipleDropDownService } from './src/MultipleDropDownServic
 
 export { default as OENContainersService } from './src/OENContainersService/OENContainersService';
 export { default as YjsService } from './src/YjsService/YjsService';
+export { default as AnyStyleService } from './src/AnyStyleService/AnyStyleService';
 /*
 ToolGroups
 */
diff --git a/wax-prosemirror-services/src/AnyStyleService/AnyStyleService.js b/wax-prosemirror-services/src/AnyStyleService/AnyStyleService.js
new file mode 100644
index 0000000000000000000000000000000000000000..c1a1ed47e1e6df6b8c9900d82ed4ea2deff8f3cd
--- /dev/null
+++ b/wax-prosemirror-services/src/AnyStyleService/AnyStyleService.js
@@ -0,0 +1,24 @@
+import { Service } from 'wax-prosemirror-core';
+import AnyStyleTool from './AnyStyleTool';
+import AnyStyleToolGroupService from './AnyStyleToolGroupService/AnyStyleToolGroupService';
+import AnyStylePlaceHolderPlugin from './plugins/AnyStylePlaceHolderPlugin';
+import './anyStyle.css';
+
+class AnyStyleService extends Service {
+  name = 'AnyStyleService';
+
+  boot() {
+    this.app.PmPlugins.add(
+      'anyStylePlaceHolder',
+      AnyStylePlaceHolderPlugin('anyStylePlaceHolder'),
+    );
+  }
+
+  register() {
+    this.container.bind('AnyStyleTool').to(AnyStyleTool);
+  }
+
+  dependencies = [new AnyStyleToolGroupService()];
+}
+
+export default AnyStyleService;
diff --git a/wax-prosemirror-services/src/AnyStyleService/AnyStyleTool.js b/wax-prosemirror-services/src/AnyStyleService/AnyStyleTool.js
new file mode 100644
index 0000000000000000000000000000000000000000..d070dd0cf56eeaf6c1636d4184aaca26fd147f12
--- /dev/null
+++ b/wax-prosemirror-services/src/AnyStyleService/AnyStyleTool.js
@@ -0,0 +1,68 @@
+import React, { useContext } from 'react';
+import { v4 as uuidv4 } from 'uuid';
+import { isEmpty } from 'lodash';
+import { injectable } from 'inversify';
+import { WaxContext, Commands, Tools } from 'wax-prosemirror-core';
+import AnyStyleButton from './components/AnyStyleButton';
+import replaceText from './replaceText';
+
+@injectable()
+class AnyStyleTool extends Tools {
+  title = 'ChatGPT';
+  name = 'ChatGPT';
+  label = 'ChatGPT';
+
+  get run() {
+    return true;
+  }
+
+  select = activeView => {
+    return true;
+  };
+
+  get enable() {
+    return state => {
+      return true;
+    };
+  }
+
+  renderTool(view) {
+    if (isEmpty(view)) return null;
+    const context = useContext(WaxContext);
+    const anyStyle = replaceText(
+      view,
+      this.config.get('config.AnyStyleService').AnyStyleTransformation,
+      this.pmplugins.get('anyStylePlaceHolder'),
+      context,
+    );
+    return this.isDisplayed() ? (
+      <AnyStyleButton
+        anyStyle={anyStyle}
+        item={this.toJSON()}
+        key={uuidv4()}
+        view={view}
+      />
+    ) : null;
+  }
+
+  //   renderTool(view) {
+  //     if (isEmpty(view)) return null;
+  //     const context = useContext(WaxContext);
+  //     const upload = fileUpload(
+  //       view,
+  //       this.config.get('fileUpload'),
+  //       this.pmplugins.get('imagePlaceHolder'),
+  //       context,
+  //     );
+  //     return this.isDisplayed() ? (
+  //       <ImageUpload
+  //         fileUpload={upload}
+  //         item={this.toJSON()}
+  //         key={uuidv4()}
+  //         view={view}
+  //       />
+  //     ) : null;
+  //   }
+}
+
+export default AnyStyleTool;
diff --git a/wax-prosemirror-services/src/AnyStyleService/AnyStyleToolGroupService/AnyStyle.js b/wax-prosemirror-services/src/AnyStyleService/AnyStyleToolGroupService/AnyStyle.js
new file mode 100644
index 0000000000000000000000000000000000000000..57217fd6791e37ede78b30d4b9dbd810b7ac6db3
--- /dev/null
+++ b/wax-prosemirror-services/src/AnyStyleService/AnyStyleToolGroupService/AnyStyle.js
@@ -0,0 +1,13 @@
+import { injectable, inject } from 'inversify';
+import { ToolGroup } from 'wax-prosemirror-core';
+
+@injectable()
+class Anystyle extends ToolGroup {
+  tools = [];
+  constructor(@inject('AnyStyleTool') anyStyleTool) {
+    super();
+    this.tools = [anyStyleTool];
+  }
+}
+
+export default Anystyle;
diff --git a/wax-prosemirror-services/src/AnyStyleService/AnyStyleToolGroupService/AnyStyleToolGroupService.js b/wax-prosemirror-services/src/AnyStyleService/AnyStyleToolGroupService/AnyStyleToolGroupService.js
new file mode 100644
index 0000000000000000000000000000000000000000..703a4688e34d31d57045cc56121d6d0dfdec993b
--- /dev/null
+++ b/wax-prosemirror-services/src/AnyStyleService/AnyStyleToolGroupService/AnyStyleToolGroupService.js
@@ -0,0 +1,10 @@
+import { Service } from 'wax-prosemirror-core';
+import AnyStyle from './AnyStyle';
+
+class AnyStyleToolGroupService extends Service {
+  register() {
+    this.container.bind('AnyStyle').to(AnyStyle);
+  }
+}
+
+export default AnyStyleToolGroupService;
diff --git a/wax-prosemirror-services/src/AnyStyleService/anyStyle.css b/wax-prosemirror-services/src/AnyStyleService/anyStyle.css
new file mode 100644
index 0000000000000000000000000000000000000000..ef4885cbd069a2368e985ffe1f2bd90f26447d26
--- /dev/null
+++ b/wax-prosemirror-services/src/AnyStyleService/anyStyle.css
@@ -0,0 +1,5 @@
+placeholder-any-style:before {
+    position: relative;
+    top: 3px;
+    content: url("data:image/svg+xml; utf8, <svg xmlns='http://www.w3.org/2000/svg' height='24' width='24'><path d='M8 20h8v-3q0-1.65-1.175-2.825Q13.65 13 12 13q-1.65 0-2.825 1.175Q8 15.35 8 17Zm-4 2v-2h2v-3q0-1.525.713-2.863Q7.425 12.8 8.7 12q-1.275-.8-1.987-2.138Q6 8.525 6 7V4H4V2h16v2h-2v3q0 1.525-.712 2.862Q16.575 11.2 15.3 12q1.275.8 1.988 2.137Q18 15.475 18 17v3h2v2Z' /></svg>");
+}
\ No newline at end of file
diff --git a/wax-prosemirror-services/src/AnyStyleService/components/AnyStyleButton.js b/wax-prosemirror-services/src/AnyStyleService/components/AnyStyleButton.js
new file mode 100644
index 0000000000000000000000000000000000000000..eafacca2053069392faeb6c5ee9c69ba98689d20
--- /dev/null
+++ b/wax-prosemirror-services/src/AnyStyleService/components/AnyStyleButton.js
@@ -0,0 +1,58 @@
+/* eslint react/prop-types: 0 */
+import React, { useContext, useMemo, useEffect } from 'react';
+import { WaxContext, DocumentHelpers, MenuButton } from 'wax-prosemirror-core';
+import { TextSelection } from 'prosemirror-state';
+
+const AnyStyleButton = ({ view = {}, item, anyStyle }) => {
+  const { active, icon, label, run, select, title } = item;
+
+  const {
+    app,
+    pmViews: { main },
+    activeViewId,
+    activeView,
+  } = useContext(WaxContext);
+
+  const { state } = view;
+
+  const handleMouseDown = (e, editorState) => {
+    e.preventDefault();
+    const {
+      selection: { $from, $to },
+    } = editorState;
+    /* this is the content that we have to get from the selection */
+    const textSelection = new TextSelection($from, $to);
+
+    const content = textSelection.content();
+
+    anyStyle(content.content.content[0].textContent);
+  };
+
+  useEffect(() => {}, []);
+
+  const isActive = !!active(state, activeViewId);
+  let isDisabled = !select(state, activeViewId, activeView);
+
+  const isEditable = main.props.editable(editable => {
+    return editable;
+  });
+  if (!isEditable) isDisabled = true;
+
+  const AnyStyleButtonComponent = useMemo(
+    () => (
+      <MenuButton
+        active={isActive || false}
+        disabled={isDisabled}
+        iconName={icon}
+        label={label}
+        onMouseDown={e => handleMouseDown(e, view.state, view.dispatch)}
+        title={title}
+      />
+    ),
+    [isActive, isDisabled],
+  );
+
+  return AnyStyleButtonComponent;
+};
+
+export default AnyStyleButton;
diff --git a/wax-prosemirror-services/src/AnyStyleService/plugins/AnyStylePlaceHolderPlugin.js b/wax-prosemirror-services/src/AnyStyleService/plugins/AnyStylePlaceHolderPlugin.js
new file mode 100644
index 0000000000000000000000000000000000000000..990b75ee2173d6255fc6091b2210595b30a33f45
--- /dev/null
+++ b/wax-prosemirror-services/src/AnyStyleService/plugins/AnyStylePlaceHolderPlugin.js
@@ -0,0 +1,37 @@
+/* eslint-disable no-param-reassign */
+import { Plugin, PluginKey } from 'prosemirror-state';
+import { Decoration, DecorationSet } from 'prosemirror-view';
+
+export default key =>
+  new Plugin({
+    key: new PluginKey(key),
+    state: {
+      init: function init() {
+        return DecorationSet.empty;
+      },
+      apply: function apply(tr, set) {
+        // Adjust decoration positions to changes made by the transaction
+        set = set.map(tr.mapping, tr.doc);
+        // See if the transaction adds or removes any placeholders
+        const action = tr.getMeta(this);
+        if (action && action.add) {
+          const widget = document.createElement('placeholder-any-style');
+          const deco = Decoration.widget(action.add.pos, widget, {
+            id: action.add.id,
+          });
+
+          set = set.add(tr.doc, [deco]);
+        } else if (action && action.remove) {
+          set = set.remove(
+            set.find(null, null, spec => spec.id === action.remove.id),
+          );
+        }
+        return set;
+      },
+    },
+    props: {
+      decorations: function decorations(state) {
+        return this.getState(state);
+      },
+    },
+  });
diff --git a/wax-prosemirror-services/src/AnyStyleService/replaceText.js b/wax-prosemirror-services/src/AnyStyleService/replaceText.js
new file mode 100644
index 0000000000000000000000000000000000000000..20b258fdd573516b78712a53a939f0156aec3770
--- /dev/null
+++ b/wax-prosemirror-services/src/AnyStyleService/replaceText.js
@@ -0,0 +1,62 @@
+import { v4 as uuidv4 } from 'uuid';
+import { DOMParser } from 'prosemirror-model';
+
+const findPlaceholder = (state, id, placeholderPlugin) => {
+  const decos = placeholderPlugin.getState(state);
+  const found = decos.find(null, null, spec => spec.id === id);
+  return found.length ? found[0].from : null;
+};
+
+const elementFromString = string => {
+  const wrappedValue = `<body>${string}</body>`;
+
+  return new window.DOMParser().parseFromString(wrappedValue, 'text/html').body;
+};
+
+export default (
+  view,
+  AnyStyleTransformation,
+  placeholderPlugin,
+  context,
+) => data => {
+  const { state } = view;
+  // A fresh object to act as the ID for this upload
+  const id = {};
+
+  // Replace the selection with a placeholder
+  const { tr } = state;
+  if (!tr.selection.empty) tr.deleteSelection();
+
+  tr.setMeta(placeholderPlugin, {
+    add: { id, pos: tr.selection.from },
+  });
+
+  view.dispatch(tr);
+
+  AnyStyleTransformation(data).then(
+    text => {
+      const pos = findPlaceholder(view.state, id, placeholderPlugin);
+      // If the content around the placeholder has been deleted, drop
+      // the image
+      if (pos == null) {
+        return;
+      }
+      const parser = DOMParser.fromSchema(
+        context.pmViews.main.state.config.schema,
+      );
+      const parsedContent = parser.parse(elementFromString(text));
+      // Otherwise, insert it at the placeholder's position, and remove
+      // the placeholder
+      context.pmViews[context.activeViewId].dispatch(
+        context.pmViews[context.activeViewId].state.tr
+          .replaceWith(pos, pos, parsedContent)
+          .setMeta(placeholderPlugin, { remove: { id } }),
+      );
+    },
+
+    () => {
+      // On failure, just clean up the placeholder
+      view.dispatch(tr.setMeta(placeholderPlugin, { remove: { id } }));
+    },
+  );
+};