Joey

Comment j'ai créé TMDX

Cet article expliquera comment j'ai eu l'idée de créer TMDX et comment j'ai réalisé cette idée.

Comment j'ai créé TMDX

Origine

J'écrivais des blogs il y a longtemps, en commençant par Jekyll, puis en utilisant Gatsby, mais ces générateurs de sites statiques étaient tous très compliqués à utiliser, nécessitant la configuration de Git, l'apprentissage de la construction, et l'envoi d'images était difficile, nécessitant de copier manuellement les images dans le dossier des images. J'ai donc passé à Medium, mais l'expérience d'écriture sur Medium n'était pas bonne, ne supportant pas Markdown, ne supportant pas la coloration syntaxique du code, et l'interface n'était pas assez simple. J'ai toujours cherché une meilleure plateforme d'écriture.

En juillet, j'ai créé un plugin de dons pour blogs appelé TonTip qui aide les webmasters à recevoir des revenus de dons via la blockchain, mais après avoir fait le tour, je n'ai pas eu beaucoup de réactions, alors j'ai décidé de créer moi-même une plateforme de blog qui répondrait mieux à mes besoins, capable d'intégrer n'importe quel plugin que je souhaiterais.

Début

Il existe de nombreux tutoriels en ligne pour créer des blogs personnels, j'en ai lu quelques-uns, puis j'ai eu une idée technique de base, j'ai décidé d'utiliser :

  1. svelte + sveltekit
  2. bun + typescript
  3. cloudflare
  4. tailwindcss
  5. daisyui
  6. shiki
  7. markdown-it
  8. monaco editor
  9. mathjax

J'ai choisi Svelte car ce framework compile le code de modèle en HTML et JS, et élimine les dépendances inutiles au moment de l'exécution, j'ai choisi Bun car c'est un runtime JS récent très populaire, TailwindCSS est un framework atomique très simple, en utilisant celui-ci, les débutants peuvent rapidement construire des interfaces jolies. DaisyUI est une bibliothèque de composants UI pour TailwindCSS, en l'utilisant, de nombreux composants de base n'ont pas besoin d'être écrits par soi-même. Markdown-it est utilisé pour compiler Markdown, on pourrait également choisir RemarkJS, mais j'ai décidé d'utiliser Markdown-it car il est plus simple. Shiki est une bibliothèque de coloration syntaxique de code, en l'utilisant, on peut insérer du code joli dans Markdown. Mathjax est une bibliothèque mathématique, si on a besoin de modifier des formules LaTeX, on a besoin de dépendre de cette bibliothèque. Enfin, et surtout, la partie de l'éditeur est basée sur Monaco, c'est un éditeur open source de l'équipe de Microsoft qui peut être intégré dans le navigateur, et il est également très extensible.

Conception du produit

La conception du produit était assez simple, j'ai regardé de nombreux blogs d'autres personnes pour concevoir l'interface de mon blog. Quant à la partie de l'éditeur, j'ai entièrement copié GitHub Copilot, je suis un abonné de GitHub Copilot, ce plugin aide à compléter du code de haute qualité, c'est un outil de productivité très utile pour les programmeurs. J'espérais que mon éditeur puisse également être comme GitHub Copilot, fournissant des complétions et des suggestions intelligentes de code, ce qui non seulement augmenterait l'efficacité de l'écriture, mais rendrait également le contenu plus professionnel et précis.

Voici l'interface d'édition de VSCode + GitHub Copilot

image.png

Voici l'interface d'édition de TMDX

image.png

Les fonctionnalités globales et la conception de l'interface sont proches

Implémentation de la bibliothèque d'images

La bibliothèque d'images est importante pour l'expérience d'édition, nous ne voulons pas ouvrir un dossier local pour trouver des images pendant l'édition, puis les télécharger. J'ai donc intégré une fonctionnalité de téléchargement et de gestion d'images. Les utilisateurs peuvent directement télécharger des images dans la bibliothèque d'images, les images seront automatiquement stockées dans le cloud et un lien d'image sera inséré dans l'article. Cela simplifie non seulement le processus d'opération, mais garantit également une gestion unifiée et un accès rapide aux images.

Voici l'interface de la bibliothèque d'images

image.png

Supporte le choix de fichiers par clic de souris, supporte Ctrl + V pour coller et télécharger, et le glisser-déposer de fichiers dans la bibliothèque d'images pour déclencher le téléchargement

Parfois, on ne souhaite pas télécharger des images via la bibliothèque d'images, j'ai également écouté les événements de l'éditeur, implémenté le collage et le téléchargement par glisser-déposer dans l'éditeur

editor.getDomNode()?.addEventListener("paste", handlePaste);
editor.getDomNode()?.addEventListener("dragover", handleDragOver);
editor.getDomNode()?.addEventListener("drop", handleDrop);

Implémentation de la conversation AI

Depuis l'apparition de ChatGPT en 23, il y a maintenant de nombreux robots de conversation, les frais d'interface sont également tombés à un niveau très bas. Pour implémenter une interface de conversation, il est assez simple de montrer alternativement les questions et les réponses dans un conteneur, et d'envoyer une question en modifiant un textarea en bas. Parce que la réponse de l'interface de chat est assez lente, et elle est renvoyée token par token, j'ai donc utilisé une caractéristique assez pratique de Svelte rune pendant le processus de création de l'interface, en utilisant rune pour la programmation réactive, de sorte que chaque fois qu'une interface renvoie un token supplémentaire, il peut immédiatement apparaître sur l'interface.

La capture d'écran suivante montre comment j'ai utilisé la programmation réactive, ainsi que la caractéristique SSE de l'interface HTTP, pour mettre à jour messages puis mettre à jour l'interface

image.png

J'ai d'abord intégré un seul modèle de Deepseek, puis j'ai testé quelques autres modèles d'autres fournisseurs, comme ChatGLM, et j'ai trouvé qu'ils étaient également bons, donc je les ai également ajoutés, maintenant les modèles supportés sont :

  1. Deepseek : supporte uniquement la conversation textuelle
  2. GLM : supporte uniquement la conversation textuelle
  3. Flux : supporte uniquement la génération d'images à partir de texte
  4. Cogview : génération d'images à partir de texte
  5. Cogvideox : génération de vidéos à partir de texte

Pour la génération d'images à partir de texte, je l'aime personnellement pour générer des images de couverture de blog, ainsi je peux facilement générer des images de couverture de haute qualité sans avoir besoin de les concevoir ou de les trouver manuellement.

Par exemple, j'ai demandé à Flux de générer une image avec les mots-clés suivants :

"blue sky, white cloud"

Il a renvoyé l'image suivante,

blue sky, white cloud

Je n'ai qu'à copier le lien et le définir comme champ de couverture dans le frontmatter

Implémentation de la complétion AI

La complétion AI est une chose assez technique, je me souviens encore de 2019, quand Tabnine est apparu pour la première fois, tout le monde l'a félicité et était étonné. Puis il y a eu GitHub Copilot, mais à l'époque, la technologie LLM n'était pas très développée, la complétion de Copilot n'était pas très précise, jusqu'en 2023, quand ChatGPT est apparu, les gens ont découvert qu'on pouvait utiliser des grands modèles pour réaliser la complétion de code, alors Microsoft a rapidement mis à jour GitHub Copilot, et a continué à itérer jusqu'à ce que l'effet de complétion soit maintenant très bon. J'ai décidé d'intégrer également la fonction de complétion AI dans mon éditeur, ainsi les utilisateurs pourraient bénéficier d'une expérience de complétion intelligente similaire à GitHub Copilot lors de l'écriture. Pour réaliser cette fonction, j'ai choisi le modèle Deepseek comme support backend, car il se comporte bien dans le traitement du langage naturel et la complétion de code. Grâce à l'appel API, l'éditeur peut obtenir en temps réel des suggestions de complétion et les afficher dans l'éditeur, les utilisateurs n'ont qu'à appuyer sur la touche Tab pour accepter la suggestion.

Monaco Editor fournit une interface de complétion, nous n'avons qu'à implémenter cette interface pour obtenir le contenu de complétion souhaité

monaco.languages.registerInlineCompletionsProvider(
    "markdown",
    {
        provideInlineCompletions: async (
            model,
            position,
            context,
            token,
        ) => {
            // générer des complétions...
        }
    }
);

Comment générer rapidement, efficacement et avec précision le contenu de complétion est le point clé, pour cela j'ai consulté de nombreuses implémentations d'autres personnes, y compris

  1. https://spencerporter2.medium.com/building-copilot-on-the-web-f090ceb9b20b
  2. https://github.com/arshad-yaseen/monacopilot
  3. https://sourcegraph.com/blog/the-lifecycle-of-a-code-ai-completion

Actuellement, j'utilise la manière la plus simple, envoyer périodiquement des demandes de complétion à l'AI, puis mettre en cache le contenu, l'afficher à l'utilisateur lorsque c'est nécessaire.

J'ai une table enregistrant le temps de complétion, voici une capture d'écran de certains enregistrements

image.png

La troisième colonne est la longueur du contenu généré, la quatrième colonne est le temps d'interface, il peut généralement revenir en moins de 5 secondes, ce qui est acceptable pour les créateurs de contenu, il y a encore de la marge d'optimisation à l'avenir.

Je n'ai pas particulièrement compté la qualité du contenu de complétion, la situation d'acceptation des utilisateurs, j'ai pris des captures d'écran de certains résultats de complétion pendant que j'éditais cet article, je pense personnellement que c'est bien

image.png

image.png

image.png

image.png

Implémentation de la recherche AI

J'ai placé une boîte de recherche dans la barre de navigation

image.png

Contrairement à la recherche traditionnelle utilisant Elasticsearch ou Algolia, j'ai basé une fonction de recherche AI sur la base de données vectorielles Vectorize fournie par Cloud Flare AI, chaque fois qu'un utilisateur publie un article, cela déclenche l'AI pour analyser l'article, générer des embeddings, pu

Discussion (0)