From ef8dd98b7bbf62a1c9409d04a3785b319d55c5d4 Mon Sep 17 00:00:00 2001 From: Anthony LC Date: Thu, 12 Sep 2024 17:11:38 +0200 Subject: [PATCH] fixup! :sparkles: Add ai correction api endpoint --- src/backend/core/api/viewsets.py | 67 ++++++++++++++++++- .../docs/doc-editor/api/useAIRewrite.tsx | 9 ++- .../docs/doc-editor/components/AIButton.tsx | 45 ++++++++----- 3 files changed, 104 insertions(+), 17 deletions(-) diff --git a/src/backend/core/api/viewsets.py b/src/backend/core/api/viewsets.py index a66eb5c1..6d57635d 100644 --- a/src/backend/core/api/viewsets.py +++ b/src/backend/core/api/viewsets.py @@ -388,7 +388,7 @@ class DocumentViewSet( api_key= settings.AI_API_KEY ) - if action == "rephrase": + if action == "correct": try: response = client.chat.completions.create( model="meta-llama/Meta-Llama-3.1-70B-Instruct", @@ -401,6 +401,71 @@ class DocumentViewSet( return drf_response.Response(corrected_response['phrase_corrigee']) except (json.JSONDecodeError, KeyError) as e: return drf_response.Response({"error": f"Error processing AI response: {str(e)}"}, status=500) + elif action == "rephrase": + try: + response = client.chat.completions.create( + model="meta-llama/Meta-Llama-3.1-70B-Instruct", + messages=[ + {"role": "system", "content": 'Tu es un ecrivain. Rephrase la phrase donnée. Renvoie uniquement un JSON au format suivant: {"phrase_rephrase": "ta phrase rephrasé"}. Ne donne aucune autre information.'}, + {"role": "user", "content": f'{{"phrase": "{text}"}}'}, + ] + ) + corrected_response = json.loads(response.choices[0].message.content) + return drf_response.Response(corrected_response['phrase_rephrase']) + except (json.JSONDecodeError, KeyError) as e: + return drf_response.Response({"error": f"Error processing AI response: {str(e)}"}, status=500) + elif action == "summarize": + try: + response = client.chat.completions.create( + model="meta-llama/Meta-Llama-3.1-70B-Instruct", + messages=[ + {"role": "system", "content": 'Tu es un ecrivain. Fait un sommaire de la phrase donnée. Renvoie uniquement un JSON au format suivant: {"phrase_summary": "ton sommaire"}. Ne donne aucune autre information.'}, + {"role": "user", "content": f'{{"phrase": "{text}"}}'}, + ] + ) + corrected_response = json.loads(response.choices[0].message.content) + return drf_response.Response(corrected_response['phrase_summary']) + except (json.JSONDecodeError, KeyError) as e: + return drf_response.Response({"error": f"Error processing AI response: {str(e)}"}, status=500) + elif action == "translate_en": + try: + response = client.chat.completions.create( + model="meta-llama/Meta-Llama-3.1-70B-Instruct", + messages=[ + {"role": "system", "content": 'Tu es un traducteur anglais. Traduit en anglais la phrase donnée. Renvoie uniquement un JSON au format suivant: {"sentence": "Your sentence"}. Ne donne aucune autre information.'}, + {"role": "user", "content": f'{{"phrase": "{text}"}}'}, + ] + ) + corrected_response = json.loads(response.choices[0].message.content) + return drf_response.Response(corrected_response['phrase_summary']) + except (json.JSONDecodeError, KeyError) as e: + return drf_response.Response({"error": f"Error processing AI response: {str(e)}"}, status=500) + elif action == "translate_de": + try: + response = client.chat.completions.create( + model="meta-llama/Meta-Llama-3.1-70B-Instruct", + messages=[ + {"role": "system", "content": 'Tu es un traducteur allemand. Traduit en allemand la phrase donnée. Renvoie uniquement un JSON au format suivant: {"sentence": "Your sentence"}. Ne donne aucune autre information.'}, + {"role": "user", "content": f'{{"phrase": "{text}"}}'}, + ] + ) + corrected_response = json.loads(response.choices[0].message.content) + return drf_response.Response(corrected_response['sentence']) + except (json.JSONDecodeError, KeyError) as e: + return drf_response.Response({"error": f"Error processing AI response: {str(e)}"}, status=500) + elif action == "translate_fr": + try: + response = client.chat.completions.create( + model="meta-llama/Meta-Llama-3.1-70B-Instruct", + messages=[ + {"role": "system", "content": 'Tu es un traducteur francais. Traduit en francais la phrase donnée. Renvoie uniquement un JSON au format suivant: {"phrase": "Your sentence"}. Ne donne aucune autre information.'}, + {"role": "user", "content": f'{{"sentence": "{text}"}}'}, + ] + ) + corrected_response = json.loads(response.choices[0].message.content) + return drf_response.Response(corrected_response['phrase']) + except (json.JSONDecodeError, KeyError) as e: + return drf_response.Response({"error": f"Error processing AI response: {str(e)}"}, status=500) else: return drf_response.Response({"error": "Invalid action"}, status=400) diff --git a/src/frontend/apps/impress/src/features/docs/doc-editor/api/useAIRewrite.tsx b/src/frontend/apps/impress/src/features/docs/doc-editor/api/useAIRewrite.tsx index 7506d033..de78bc70 100644 --- a/src/frontend/apps/impress/src/features/docs/doc-editor/api/useAIRewrite.tsx +++ b/src/frontend/apps/impress/src/features/docs/doc-editor/api/useAIRewrite.tsx @@ -2,7 +2,14 @@ import { useMutation } from '@tanstack/react-query'; import { APIError, errorCauses, fetchAPI } from '@/api'; -export type AIActions = 'rephrase' | 'summarize' | 'translate' | 'correct'; +export type AIActions = + | 'rephrase' + | 'summarize' + | 'translate' + | 'correct' + | 'translate_fr' + | 'translate_en' + | 'translate_de'; export type DocAIParams = { docId: string; diff --git a/src/frontend/apps/impress/src/features/docs/doc-editor/components/AIButton.tsx b/src/frontend/apps/impress/src/features/docs/doc-editor/components/AIButton.tsx index dce43276..96d49f0a 100644 --- a/src/frontend/apps/impress/src/features/docs/doc-editor/components/AIButton.tsx +++ b/src/frontend/apps/impress/src/features/docs/doc-editor/components/AIButton.tsx @@ -1,8 +1,6 @@ import { useBlockNoteEditor, useComponentsContext, - useEditorContentOrSelectionChange, - useEditorSelectionChange, useSelectedBlocks, } from '@blocknote/react'; import { useMemo } from 'react'; @@ -20,12 +18,6 @@ export function AIButton({ doc }: AIButtonProps) { const editor = useBlockNoteEditor(); const Components = useComponentsContext(); const selectedBlocks = useSelectedBlocks(editor); - useEditorSelectionChange(() => { - console.log('Selection changed'); - }, editor); - useEditorContentOrSelectionChange(() => { - console.log('Content or selection changed'); - }, editor); const { mutateAsync: requestAI } = useAIRewrite(); const handleRephraseAI = async (action: AIActions) => { @@ -36,8 +28,6 @@ export function AIButton({ doc }: AIButtonProps) { action, }); - console.log('AI response:', newText); - editor.insertInlineContent([ newText, //{ type: 'text', text: 'World', styles: { bold: true } }, @@ -65,19 +55,44 @@ export function AIButton({ doc }: AIButtonProps) { - {['rephrase', 'summarize', 'correct'].map((action) => ( + {[ + { + label: 'Rephrase', + action: 'rephrase', + }, + { + label: 'Summarize', + action: 'summarize', + }, + { + label: 'Correct', + action: 'correct', + }, + { + label: 'Translate to French', + action: 'translate_fr', + }, + { + label: 'Translate to English', + action: 'translate_en', + }, + { + label: 'Translate to German', + action: 'translate_de', + }, + ].map(({ label, action }) => ( void handleRephraseAI('rephrase')} + onClick={() => void handleRephraseAI(action as AIActions)} $hasTransition $radius="6px" - $width="98%" + $width="100%" $align="center" $css="&:hover{background-color: #f2f8ff;}text-transform: capitalize!important;" > - {action} + {label} ))}