coffreobsidian/webdev/ROBO_MAT_Code_WLangage_Organise.md
2025-03-24 17:36:01 +01:00

48 KiB
Raw Permalink Blame History

📘 Analyse complète du projet WebDev : ROBO_MAT

Objectif : Regrouper tout le code WLangage du projet dans un seul fichier .md, organisé selon les conventions et les sections de WebDev, afin de faciliter la compréhension, lanalyse et la réécriture en Python.


🧭 Table des matières

  1. Code du projet (initialisation/fermeture)
  2. Pages
  3. Classes
  4. Procédures globales

🔧 Code du projet

▶️ Initialisation du projet


⏹️ Fermeture du projet



📄 Pages

🧩 PAGE_TEST

🏗️ Déclaration


▶️ Événements


🔧 Terminaison


📍 Autres onglets (si présents)



🧱 Classes

💡 Pour chaque classe, on respecte les sections affichées dans WebDev : Déclaration, Constructeur, Destructeur, Méthodes, etc.

🧠 clsMistral

🔹 Déclaration de clsMistral

clsMistral est une Classe
	hérite de clsLLM
		maxToken est un entier
		seed est un entier
		presence_penalty est un réel
		frequency_penalty est un réel
		n est un entier
		prediction est un JSON
		safe_prompt est un booléen
		o_stop est une chaîne
	PRIVÉ
		m_tabModels est un tableau de chaînes
FIN

Terminaison de clsMistral


🛠️ Constructeur

PROCÉDURE Constructeur()

//:Modele = "open-mixtral-8x22b-2404"
:Modele = "mistral-large-latest"
:o_temperature = 0.2
:o_top_p = 1
:maxToken = 1000
:presence_penalty =	0
:frequency_penalty = 0
:n=1
prediction.type = "content"
prediction.content = ""
safe_prompt = Faux
o_stop = "string"

Récupération de la propriété model_list

PROCÉDURE PUBLIQUE model_list()
hReponse	est une httpRéponse
reqLLM		est une restRequête
vReponse est un Variant

SI TableauOccurrence(m_tabModels) > 1 ALORS
	RENVOYER (m_tabModels)
FIN

reqLLM.URL				= :urlBase+"models"
reqLLM.Méthode			= httpGet
SI :cleAPI <> "" ALORS
	reqLLM.Entête["Authorization"]	= "Bearer " + cleAPI
FIN
reqLLM.Entête["Content-Type"]	= "application/json"	
hReponse				= RESTEnvoie(reqLLM)
SI hReponse.CodeEtat = 200 ALORS
	vReponse = JSONVersVariant(hReponse.Contenu)
	POUR i = 1 _À_ TableauOccurrence(vReponse.data)
		TableauAjoute(m_tabModels,vReponse.data[i].id)
	FIN
SINON
	TableauAjoute(m_tabModels,hReponse.Contenu)
FIN
RENVOYER(m_tabModels)

Affectation de la propriété model_list


Récupération de la propriété urlBase

PROCÉDURE PUBLIQUE urlBase()
RENVOYER("https://api.mistral.ai/v1/")

Affectation de la propriété urlBase


Récupération de la propriété cleAPI

PROCÉDURE PUBLIQUE cleAPI()

RENVOYER("2iGzTzE9csRQ9IoASoUjplHwEjA200Vh")

Affectation de la propriété cleAPI


Récupération de la propriété urlFonction

PROCÉDURE PUBLIQUE urlFonction()

RENVOYER("chat/completions")

Affectation de la propriété urlFonction


Destructeur

PROCÉDURE Destructeur()

📦 Méthode interrogerRetourneReponse

PROCÉDURE PROTÉGÉE interrogerRetourneReponse(LOCAL sReponse est une chaîne)
sRetour est une chaîne
vReponse est un Variant
vReponse = JSONVersVariant(sReponse)
sRetour = vReponse.choices[1].message.content
RENVOYER(sRetour)

Méthode even_LLM_POST

/*
Model (string) or Model (null) (Model)

ID of the model to use. You can use the List Available Models API to see all of your available models, or see our Model overview for model descriptions.
Temperature (number) or Temperature (null) (Temperature)

What sampling temperature to use, we recommend between 0.0 and 0.7. Higher values like 0.7 will make the output more random, while lower values like 0.2 will make it more focused and deterministic. We generally recommend altering this or top_p but not both. The default value varies depending on the model you are targeting. Call the /models endpoint to retrieve the appropriate value.
top_p	
number (Top P) [ 0 .. 1 ]
Default: 1

Nucleus sampling, where the model considers the results of the tokens with top_p probability mass. So 0.1 means only the tokens comprising the top 10% probability mass are considered. We generally recommend altering this or temperature but not both.
Max Tokens (integer) or Max Tokens (null) (Max Tokens)

The maximum number of tokens to generate in the completion. The token count of your prompt plus max_tokens cannot exceed the model's context length.
stream	
boolean (Stream)
Default: false

Whether to stream back partial progress. If set, tokens will be sent as data-only server-side events as they become available, with the stream terminated by a data: [DONE] message. Otherwise, the server will hold the request open until the timeout or until completion, with the response containing the full result as JSON.
Stop (string) or Array of Stop (strings) (Stop)

Stop generation if this token is detected. Or if one of these tokens is detected when providing an array
Random Seed (integer) or Random Seed (null) (Random Seed)

The seed to use for random sampling. If set, different calls will generate deterministic results.
required

Array of any (Messages)

The prompt(s) to generate completions for, encoded as a list of dict with role and content.
object (ResponseFormat)
Array of Tools (objects) or Tools (null) (Tools)
ToolChoice (object) or ToolChoiceEnum (string) (Tool Choice)
Default: "auto"
presence_penalty	
number (Presence Penalty) [ -2 .. 2 ]
Default: 0

presence_penalty determines how much the model penalizes the repetition of words or phrases. A higher presence penalty encourages the model to use a wider variety of words and phrases, making the output more diverse and creative.
frequency_penalty	
number (Frequency Penalty) [ -2 .. 2 ]
Default: 0

frequency_penalty penalizes the repetition of words based on their frequency in the generated text. A higher frequency penalty discourages the model from repeating words that have already appeared frequently in the output, promoting diversity and reducing repetition.
N (integer) or N (null) (N)

Number of completions to return for each request, input tokens are only billed once.
object (Prediction)
Default: {"type":"content","content":""}

Enable users to specify expected results, optimizing response times by leveraging known or predictable content. This approach is especially effective for updating text documents or code files with minimal changes, reducing latency while maintaining high-quality results.
safe_prompt	
boolean
Default: false

Whether to inject a safety prompt before all conversations.



*/
PROCÉDURE PROTÉGÉE even_LLM_POST(LOCAL sQuestion est une chaîne <utile>)

Contenu.messages[1].role	= "system"
Contenu.messages[1].content	= :prompt_system
Contenu.messages[2].role	= "user"
Contenu.messages[2].content	= sQuestion
Contenu.temperature = o_temperature
Contenu.top_p		=  o_top_p
SI :maxToken <> 0 ALORS
	Contenu.max_tokens = maxToken
FIN
SI :seed <> 0 ALORS
	Contenu.random_seed = :seed
FIN
SI :format <> "" ALORS
	Contenu.response_format = :format
FIN
// Contenu.tools A déterminer
// Contenu.tool_choice A déterminer
Contenu.presence_penalty	= presence_penalty
Contenu.frequency_penalty	= frequency_penalty
Contenu.n = 1
Contenu.prediction = :prediction
Contenu.stop = o_stop

🧠 clsOllama

🔹 Déclaration

clsOllama est une Classe
	hérite de clsLLM
	
	suffix				est une chaîne		
	images				est un Buffer		
	
	// Options	: Définie ci-dessous		
	template			est une chaîne			// le modèle d'invite à utiliser (remplace ce qui est défini dans le Modelfile)
	// stream est un booléen	Définie en protégé car webdev ne fonctionne pas avec le stream activé
	raw					est un booléen			// si true, aucun formatage ne sera appliqué à l'invite. Vous pouvez choisir d'utiliser le paramètre raw si vous spécifiez une invite entièrement formatée dans votre demande à l'API.
	keep_alive			est une Durée			// contrôle la durée pendant laquelle le modèle restera chargé en mémoire à la suite de la demande (par défaut : 5m)
	
	o_mirostat			est un entier			// Active l'échantillonnage Mirostat pour contrôler la perplexité. (par défaut : 0, 0 = désactivé, 1 = Mirostat, 2 = Mirostat 2.0)
	o_mirostat_eta		est un réel					// Influe sur la vitesse à laquelle l'algorithme réagit au retour d'information du texte généré. Un taux d'apprentissage plus faible entraînera des ajustements plus lents, tandis qu'un taux d'apprentissage plus élevé rendra l'algorithme plus réactif. (Valeur par défaut : 0,1)
	o_mirostat_tau		est un réel					// Contrôle l'équilibre entre la cohérence et la diversité du résultat. Une valeur plus faible permet d'obtenir un texte plus ciblé et plus cohérent. (Valeur par défaut : 5.0)
	o_num_ctx			est un entier				// Définit la taille de la fenêtre contextuelle utilisée pour générer le prochain jeton. (Valeur par défaut : 2048)
	o_repeat_last_n		est un entier				// Définit la distance à laquelle le modèle doit regarder en arrière pour éviter les répétitions. (Par défaut : 64, 0 = désactivé, -1 = num_ctx)
	o_repeat_penalty	est un réel					// Définit le degré de pénalisation des répétitions. Une valeur plus élevée (par exemple, 1,5) pénalisera plus fortement les répétitions, tandis qu'une valeur plus faible (par exemple, 0,9) sera plus indulgente. (Valeur par défaut : 1,1)
	
	o_seed				est un entier				// Définit la graine de nombres aléatoires à utiliser pour la génération. En définissant un nombre spécifique, le modèle générera le même texte pour la même invite (valeur par défaut : 0).
	o_stop				est un JSON					// Définit les séquences d'arrêt à utiliser. Lorsque ce modèle est rencontré, le LLM arrête de générer du texte et revient. Plusieurs motifs d'arrêt peuvent être définis en spécifiant plusieurs paramètres d'arrêt distincts dans un fichier modèle.
	o_num_predict		est un entier				// Nombre maximum de tokens à prédire lors de la génération de texte. (Valeur par défaut : -1, génération infinie)
	o_min_p				est un réel					// Alternative au top_p, elle vise à assurer un équilibre entre la qualité et la variété. Le paramètre p représente la probabilité minimale pour qu'un jeton soit pris en considération, par rapport à la probabilité du jeton le plus probable. Par exemple, avec p=0,05 et le jeton le plus probable ayant une probabilité de 0,9, les logits ayant une valeur inférieure à 0,045 sont filtrés. (Valeur par défaut : 0,0)
	
	// Regarder la rubrique "TEMPLATE"		
	
	/*
	Dans l'API d'Ollama, le paramètre template dans la fonction POST /api/generate permet de spécifier un modèle de prompt personnalisé qui remplace celui défini dans le fichier de modèle (Modelfile). Le modèle de prompt est utilisé pour structurer la manière dont le modèle générera sa réponse en fonction du prompt fourni.
	
	Par défaut, chaque modèle Ollama est associé à un modèle de prompt prédéfini, tel que :
	
	Copier
	{{ .System }}
	{{ .Prompt }}
	En utilisant le paramètre template, vous pouvez fournir un modèle de prompt spécifique pour une requête donnée, ce qui permet de personnaliser la structure de la réponse du modèle pour cette interaction particulière.
	
	Par exemple, si vous souhaitez que le modèle réponde sous forme de liste numérotée, vous pouvez inclure le paramètre template dans votre requête comme suit 
	{
		"model": "votre_modele",
		"prompt": "Énumérez les étapes pour préparer une tasse de thé.",
		"template": "{{ .System }}\n1. {{ .Prompt }}\n2. Faites chauffer de l'eau.\n3. Infusez le thé.\n4. Servez et dégustez."
	}
	*/	
	
FIN

Terminaison de clsOllama


🛠️ Constructeur

PROCÉDURE Constructeur()
o_mirostat			= 0
o_mirostat_eta		= 0.1
o_mirostat_tau		= 5
o_num_ctx			= 2048
o_repeat_last_n		= 64
o_repeat_penalty	= 1.1
o_temperature		= 0.8
o_seed				= 0
o_stop				= []
o_num_predict		= -1
o_top_k				= 40
o_top_p				= 0.9
o_min_p				= 0


raw					= False
keep_alive			= 5min

Récupération de la propriété urlBase

PROCÉDURE PROTÉGÉE urlBase() : chaîne
RENVOYER("http://217.182.105.173:11434/")

Affectation de la propriété urlBase


Récupération de la propriété cleAPI

PROCÉDURE PROTÉGÉE cleAPI() : chaîne
RENVOYER("")

Affectation de la propriété cleAPI


Destructeur

PROCÉDURE Destructeur()

Méthode Interroger

PROCÉDURE Interroger(LOCAL sQuestion est une chaîne <utile>)
m_sUrlFonction = "api/generate"
RENVOYER(LLM_POST(sQuestion))

Méthode even_LLM_POST

PROCÉDURE PROTÉGÉ VIRTUELLE even_LLM_POST(LOCAL sQuestion est une chaîne)
Contenu.system		= :prompt_system
Contenu.prompt		= sQuestion
Contenu.stream		= :stream
Contenu.suffix		= :suffix
Contenu.format		= :format
Contenu.raw			= :raw
Contenu.keep_alive	= :keep_alive
SI :images <> "" ALORS
	// A traiter
FIN

Contenu.options.mirostat			= o_mirostat
Contenu.options.mirostat_eta		= o_mirostat_eta
Contenu.options.mirostat_tau		= o_mirostat_tau
Contenu.options.num_ctx				= o_num_ctx
Contenu.options.repeat_last_n		= o_repeat_last_n
Contenu.options.repeat_penalty		= o_repeat_penalty
Contenu.options.temperature			= o_temperature
Contenu.options.seed				= o_seed
Contenu.options.stop				= o_stop
Contenu.options.num_predict			= o_num_predict
Contenu.options.top_k				= o_top_k
Contenu.options.top_p				= o_top_p
Contenu.options.min_p				= o_min_p


📦 Méthode interrogerRetourneReponse

PROCÉDURE PROTÉGÉ VIRTUELLE interrogerRetourneReponse(LOCAL sReponse est une chaîne <utile>)
vMaReponse	est un Variant
vMaReponse				= JSONVersVariant(sReponse)
RENVOYER(vMaReponse.response)

🧠 clsDeepSeek

🔹 Déclaration de clsDeepSeek

clsDeepSeek est une Classe
	hérite de clsLLM
	frequency_penalty est un entier	// Number between -2.0 and 2.0. Positive values penalize new tokens based on their existing frequency in the text so far, decreasing the model's likelihood to repeat the same line verbatim.
	max_tokens est un entier		/* integer between 1 and 8192. The maximum number of tokens that can be generated in the chat completion.
										The total length of input tokens and generated tokens	is limited by the model's context length.
										IF max_tokens is NOT specified, the Default value 4096 is used.
									*/
	presence_penalty est un entier	//Number between -2.0 and 2.0. Positive values penalize new tokens based on whether they appear in the text so far, increasing the model's likelihood to talk about new topics.
	logprobs est un booléen 		// Whether to return log probabilities of the output tokens or not. If true, returns the log probabilities of each output token returned in the content of message.
	top_logprobs est un entier 		// An integer between 0 and 20 specifying the number of most likely tokens to return at each token position, each with an associated log probability. logprobs must be set to true if this parameter is used.
	tool_choice est une chaîne 	/*	Controls which (if any) tool is called by the model.
									none means the model will not call any tool and instead generates a message.
									auto means the model can pick between generating a message or calling one or more tools.
									required means the model must call one or more tools.
									Specifying a particular tool via {"type": "function", "function": {"name": "my_function"}} forces the model to call that tool.
									none is the default when no tools are present. auto is the default if tools are present.
								*/
FIN

Terminaison de clsDeepSeek


🛠️ Constructeur

PROCÉDURE Constructeur()

:Modele = "deepseek-chat"
frequency_penalty = 0
max_tokens = 4096
presence_penalty = 0
o_top_p	= 1
logprobs = Faux
top_logprobs = 0
tool_choice = ""

Récupération de la propriété cleAPI

PROCÉDURE PROTÉGÉE cleAPI() : chaîne

RENVOYER("sk-d359d9236ca84a5986f889631832d1e6")

Affectation de la propriété cleAPI


Récupération de la propriété urlBase

PROCÉDURE PROTÉGÉE urlBase() : chaîne

RENVOYER("https://api.deepseek.com/")

Affectation de la propriété urlBase


Récupération de la propriété urlFonction

PROCÉDURE urlFonction() : chaîne

RENVOYER("chat/completions")

Affectation de la propiété urlFonction

PROCÉDURE urlFonction(Valeur est une chaîne)

Récupération de la propriété model_list

PROCÉDURE model_list() : tableau de chaînes

tabRetour est un tableau de chaînes = ["deepseek-chat","deepseek-reasoner"]
RENVOYER(tabRetour)

Affectation de la propriété model_list


destructeur

PROCÉDURE Destructeur()

📦 Méthode even_LLM_POST

PROCÉDURE PROTÉGÉ VIRTUELLE even_LLM_POST(LOCAL sQuestion est une chaîne <utile>)

Contenu.messages[1].role	= "system"
Contenu.messages[1].content	= :prompt_system
Contenu.messages[2].role	= "user"
Contenu.messages[2].content	= sQuestion
Contenu.stream		= :stream
Contenu.frequency_penalty	= :frequency_penalty
Contenu.max_tokens			= :max_tokens
Contenu.presence_penalty	= :presence_penalty
SI :logprobs = Vrai ALORS
	Contenu.logprobs			= :logprobs
	Contenu.top_logprobs		= :top_logprobs
FIN
SI :tool_choice <> "" ALORS
	Contenu.tool_choice			= :tool_choice
FIN

Méthode interrogerRetourReponse

PROCÉDURE PROTÉGÉ VIRTUELLE interrogerRetourneReponse(LOCAL sReponse est une chaîne)
sRetour		est une chaîne
vReponse	est un Variant
vReponse	= JSONVersVariant(sReponse)
sRetour		= vReponse.choices[1].message.content
RENVOYER(sRetour)

🧠 clsPerplexity

🔹 Déclaration de clsPerplexity

clsPerplexity est une Classe
	hérite de clsLLM
	maxToken est un entier
	presence_penalty est un entier
	frequency_penaly est un entier
	search_recency_filter est une chaîne
	search_domain_filter est un tableau de chaîne
FIN

Terminaison de clsPerplexity


🛠️ Constructeur

PROCÉDURE Constructeur()
maxToken = 1000
o_temperature = 0.5
o_top_p = 0.8
o_top_k = 0
presence_penalty = 0
frequency_penaly = 1
search_recency_filter = "all" // year
prompt_system = "Soyez précis et concis. Répondez uniquement en français. Effectuez une recherche approfondie et fournissez des informations détaillées et à jour."

Récupération de la propriété cleAPI

PROCÉDURE PROTÉGÉE cleAPI() : chaîne
RENVOYER("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")

Affectation de la propriété cleAPI


Récupération de la propriété urlBase

PROCÉDURE PROTÉGÉE urlBase() : chaîne
RENVOYER("https://api.perplexity.ai/chat/completions")

Affectation de la propriété urlBase


Destructeur

PROCÉDURE Destructeur()

Méthode Interroger

PROCÉDURE Interroger(LOCAL sQuestion est une chaîne)
:Modele = "sonar"
RENVOYER(LLM_POST(sQuestion))

Méthode even_LLM_POST

PROCÉDURE PROTÉGÉE even_LLM_POST(LOCAL sQuestion est une chaîne)

Contenu.messages[1].role = "system"
Contenu.messages[1].content = :prompt_system
Contenu.messages[2].role = "user"
Contenu.messages[2].content = sQuestion
SI :maxToken <> 0 ALORS
	Contenu.max_tokens = maxToken
FIN
Contenu.temperature = o_temperature
SI :format <> "" ALORS
	Contenu.response_format = :format
FIN
Contenu.top_p =o_top_p
SI TableauOccurrence(search_domain_filter) <> 0 ALORS
	// ["perplexity.ai"]
	Contenu.search_domain_filter = search_domain_filter
FIN
Contenu.return_images = Faux
Contenu.return_related_questions = Faux
SI search_recency_filter <> "all" ALORS
	Contenu.search_recency_filter = search_recency_filter
FIN
Contenu.top_k =  o_top_k
Contenu.presence_penalty = presence_penalty
Contenu.frequency_penalty = frequency_penaly
Contenu.response_format = Null

Méthode interrogerRetourneReponse

/*
Format de sortie
{
	"id":"f5fd096e-b694-4135-8fd2-ab241e3c15bf",
	"model":"sonar",
	"created":1738769945,
	"usage":
	{
		"prompt_tokens":13,
		"completion_tokens":72,
		"total_tokens":85
	},
	"citations":
	[
		"https://www.youtube.com/watch?v=TOrph-vS_a8",
		"https://www.teidebynight.com/how-many-stars-are-in-the-milky-way/"
	],
	"object":"chat.completion",
	"choices":
	[
		{
		"index":0,
		"finish_reason":"stop",
		"message":
		{
		"role":"assistant",
		"content":"The Milky Way galaxy is estimated to contain between **100 billion and 400 billion stars**. A more precise estimate suggests that there are approximately **100 billion stars** in our galaxy. These estimates vary due to the challenges of counting stars, such as the presence of gas, dust, and black holes that obscure many stars from view[1][2]."
		},
		"delta":
		{
		"role":"assistant",
		"content":""
		}
		}
	]
}
*/
PROCÉDURE PROTÉGÉ VIRTUELLE interrogerRetourneReponse(LOCAL sReponse est une chaîne <utile>)
vRepoonse est un Variant = JSONVersVariant(sReponse)
sRetour est une chaîne
sRetour = vRepoonse.choices[1].message.content

RENVOYER(sRetour)

🧠 clsRAG

🔹 Déclaration de clsRAG

clsRAG est une Classe
PUBLIQUE CONSTANT	
	sessionID est une chaîne
PRIVÉ
	reqRAG est une restRequête
	taContenu est un tableau associatif de Variant	
	m_sChatID est une chaîne
	mn_Question est un entier
FIN

Terminaison de clsRAG


🛠️ Constructeur

PROCÉDURE Constructeur()
reqRAG.Entête["Authorization"]	= "Bearer " + "ragflow-c4YTNkMzcwZDM1ODExZWZiODA2MDI0Mm"
reqRAG.Entête["Content-Type"]	= "application/json"	

Récupération de la propriété urlBase

PROCÉDURE PRIVÉE  urlBase()

RENVOYER("http://10.103.0.100/api/v1/chats/")

Affectation de la propriété urlBase


Récupération de la propriété chatID

PROCÉDURE PRIVÉE  chatID()
SI m_sChatID <> "" ALORS 
	RENVOYER(m_sChatID)
SINON
	RENVOYER("ffb1058ed4b811ef8a900242ac120003")
FIN

Affectation de la propriété chatID

PROCÉDURE PRIVÉ chatID(Valeur)

m_sChatID = Valeur

Récupération de la propriété Contenu

PROCÉDURE PRIVÉE  Contenu()
bufContenu est un Buffer
Sérialise(taContenu,bufContenu,psdJSON)
RENVOYER(bufContenu)

Affectation de la propriété Contenu


Récupération de la propriété urlChat

PROCÉDURE PRIVÉE  urlChat()

RENVOYER(:urlBase+chatID+"/")

Affectation de la propriété urlChat


Destructeur

PROCÉDURE Destructeur()

SI mn_Question = 0 OU EnModeTest() ALORS
	supprimeSessionChat()	
FIN

📦 Méthode creeSessionChat

PROCÉDURE PRIVÉ creeSessionChat()
vMaReponse est un Variant
hReponse est une httpRéponse
TableauSupprimeTout(taContenu)
reqRAG.URL = :urlChat+"sessions"
reqRAG.Méthode = httpPost
taContenu["name"] = DateHeureVersChaîne(DateHeureSys,"AAAAMMJJ_HHmmSS")
reqRAG.Contenu = :Contenu

hReponse = RESTEnvoie(reqRAG)
SI ErreurDétectée ALORS
	RENVOYER(Faux,TexteVersHTML(ErreurInfo()))
SINON
	vMaReponse = JSONVersVariant(hReponse.Contenu)
	SI vMaReponse.code = 0
		:sessionID = vMaReponse.data.id
		RENVOYER(Vrai,:formateReponse(vMaReponse.data.messages[1].content))
	SINON
		RENVOYER(Faux,:formateReponse(vMaReponse.message))
	FIN
FIN

Méthode Chat

PROCÉDURE Chat(LOCAL sQuestion est une chaîne)
bSessionCree est un booléen
sReponse est une chaîne
vMaReponse	est un Variant
SI :sessionID = "" ALORS
	(bSessionCree,sReponse) = creeSessionChat()
	SI PAS bSessionCree ALORS
		RENVOYER(:formateReponse(sReponse))
	FIN	
FIN

mn_Question++
hReponse	est une httpRéponse
TableauSupprimeTout(taContenu)
reqRAG.URL			= :urlChat+"completions"
reqRAG.Méthode		= httpPost
taContenu["question"]		= sQuestion
taContenu["stream"]			= False
taContenu["session_id"]		= :sessionID
reqRAG.Contenu		= :Contenu

hReponse			= RESTEnvoie(reqRAG)
SI ErreurDétectée ALORS
	RENVOYER(TexteVersHTML(ErreurInfo()))
SINON
	vMaReponse = JSONVersVariant(hReponse.Contenu)
	SI vMaReponse.code = 0 ALORS
		sReponse = vMaReponse.data.answer
		RENVOYER(:formateReponse(sReponse))
	SINON
		sReponse = vMaReponse.message
		RENVOYER(:formateReponse(sReponse))
	FIN
FIN

Méthode formateReponse

PROCÉDURE PUBLIQUE formateReponse(LOCAL sReponse est une chaîne)
sRetour est une chaîne ANSI
sRetour+="<div style=""background-color: #e8f4ff; border: 1px solid #c2e0ff; border-radius: 10px; padding: 10px 15px; font-family: Arial, sans-serif; font-size: 14px; color: #000; display: inline-block;"">"
sRetour+=UnicodeVersAnsi(UTF8VersUnicode(MarkdownVersHTML(sReponse)))
sRetour+="</div>"
//sRetourANSI = UnicodeVersAnsi(sRetourUnicode)
RENVOYER(sRetour)

Méthode formateQuestion

PROCÉDURE GLOBALE formateQuestion(LOCAL sQuestion est une chaîne)
sRetour est une chaîne
sRetour = "<div style=""text-align: right; font-family: Arial, sans-serif; font-size: 14px; color: #000; padding: 10px 15px;"">"
sRetour+= sQuestion
sRetour+= "</div>"
RENVOYER(sRetour)

Méthode supprimeSessionChat

PROCÉDURE PRIVÉ supprimeSessionChat()
vMaReponse	est un Variant
sReponse	est une chaîne
hReponse	est une httpRéponse
TableauSupprimeTout(taContenu)
reqRAG.URL					= :urlChat+"/sessions"
reqRAG.Méthode				= httpDelete
taContenu["ids"]			= [sessionID]
reqRAG.Contenu				= :Contenu

hReponse					= RESTEnvoie(reqRAG)
SI ErreurDétectée ALORS
	RENVOYER(TexteVersHTML(ErreurInfo()))
SINON
	vMaReponse = JSONVersVariant(hReponse.Contenu)
	SI vMaReponse.code = 0 ALORS
		RENVOYER("OK")
	SINON
		sReponse = vMaReponse.message
		RENVOYER(sReponse)
	FIN
FIN


🧠 clsLLM

🔹 Déclaration de clsLLM

clsLLM est une Classe <abstraite>
	PUBLIQUE
		// Paramètres 
		Modele est une chaîne
		prompt_system est une chaîne // message système à (remplace ce qui est défini dans le fichier modèle)		

		o_temperature est un réel		// La température du modèle. En augmentant la température, le modèle répondra de manière plus créative. (Valeur par défaut : 0,8)
						
		// Options
		// https://github.com/ollama/ollama/blob/main/docs/modelfile.md#format
		o_top_k	est un entier			// Réduit la probabilité de générer des non-sens. Une valeur plus élevée (par exemple 100) donnera des réponses plus diversifiées, tandis qu'une valeur plus faible (par exemple 10) sera plus conservatrice. (Valeur par défaut : 40)
		o_top_p	est un réel				// Fonctionne avec top-k. Une valeur élevée (par exemple, 0,95) conduira à un texte plus diversifié, tandis qu'une valeur plus faible (par exemple, 0,5) générera un texte plus ciblé et conservateur. (Valeur par défaut : 0,9)
	PUBLIQUE CONSTANTE
		dureeTraitement est une Durée
		reponseErreur est un booléen
	PROTÉGÉ
		Contenu est un JSON
		m_sUrlFonction est une chaîne
		stream est un booléen
		m_sFormat est une chaîne
		heureDepart est une Heure
		heureFin est une Heure
FIN

Terminaison de clsLLM


🛠️ Constructeur

PROCÉDURE Constructeur()
stream = Faux

Récupération de la propriété urlBase

PROCÉDURE PROTÉGÉ ABSTRAITE urlBase() : chaîne

Affectation de la propriété urlBase


Récupération de la propriété cleAPI

PROCÉDURE PROTÉGÉ ABSTRAITE cleAPI() :chaîne

Affectation de la propriété cleAPI


Récupération de la propriété urlFonction

PROCÉDURE PUBLIQUE urlFonction()
RENVOYER(m_sUrlFonction)

Affectation de la propriété urlFonction

PROCÉDURE PUBLIQUE urlFonction(Valeur)
m_sUrlFonction = Valeur

Récupération de la propriété format

PROCÉDURE PUBLIQUE format()

RENVOYER(m_sFormat)

Affectation de la propriété format

PROCÉDURE PUBLIQUE format(Valeur)
m_sFormat = Valeur

Récupération de la propriété model_list

PROCÉDURE PUBLIQUE model_list():tableau de chaînes
tabModels est un tableau de chaînes
RENVOYER(tabModels)

Affectation de la propriété model_list


Récupération de la propriété commandeAutorisation

PROCÉDURE PUBLIQUE commandeAutorisation()

RENVOYER("Bearer")

Affectation de la propriété commandeAutorisation


Destructeur

PROCÉDURE Destructeur()

📦 Méthode Interroger

PROCÉDURE Interroger(LOCAL sQuestion est une chaîne):chaîne
sReponse est une chaîne
sReponse	= LLM_POST(sQuestion)
RENVOYER(sReponse)

Méthode LLM_POST

PROCÉDURE PROTÉGÉE LLM_POST(LOCAL sQuestion est une chaîne):chaîne
sErreur est une chaîne
sReponse est une chaîne
hReponse	est une httpRéponse
reqLLM		est une restRequête


reqLLM.URL				= :urlBase+urlFonction
reqLLM.Méthode			= httpPost
SI :cleAPI <> "" ALORS
	reqLLM.Entête["Authorization"]	= :commandeAutorisation+ " " + :cleAPI
FIN
reqLLM.Entête["Content-Type"]	= "application/json"	

Contenu=""
SI :Modele <> "" ALORS
	Contenu.model 		= :Modele
FIN

even_LLM_POST(sQuestion)

reqLLM.Contenu			= Contenu
reqLLM..DuréeNonRéponse = 2min
dureeTraitement = 0
heureDepart	= HeureSys()
hReponse				= RESTEnvoie(reqLLM)
SI ErreurDétectée ALORS
	reponseErreur = Vrai
	RENVOYER(ErreurInfo(errComplet))
FIN
SI hReponse.CodeEtat = 200 OU hReponse.CodeEtat = 201 ALORS
	sReponse = interrogerRetourneReponse(hReponse.Contenu)
	heureFin	= HeureSys()
	dureeTraitement = heureFin - heureDepart
	reponseErreur = Faux
	RENVOYER(sReponse)
SINON
	sErreur = hReponse.Contenu
	heureFin	= HeureSys()
	dureeTraitement = heureFin - heureDepart
	reponseErreur = Vrai
	RENVOYER(sErreur)
FIN

Méthode even_LLM_POST

PROCÉDURE PROTÉGÉE ABSTRAITE VIRTUELLE even_LLM_POST(LOCAL sQuestion est une chaîne <utile>)

Méthode interrogerRetourneReponse

PROCÉDURE PROTÉGÉ ABSTRAITE VIRTUELLE interrogerRetourneReponse(LOCAL sReponse est une chaîne <utile>):chaîne

🧠 clsDeepl

🔹 Déclaration de clsDeepl

clsDeepl est une Classe
	hérite de clsLLM
	langueSource			est une chaîne
	langueDesti				est une chaîne
	context					est une chaîne
	split_sentences			est une chaîne
	preserve_formatting		est un booléen
	formality				est une chaîne
	show_billed_characters	est un booléen
	tag_handling			est une chaîne
	outline_detection		est un booléen
	non_splitting_tags		est un tableau de chaînes
	splitting_tags			est un tableau de chaînes
	ignore_tags				est un tableau de chaînes
PUBLIC CONSTANTE
	glossaire_id				est un tableau associatif (ccSansCasse) de chaînes
	m_tabGlossaireListePaire	est un tableau de 0 par 2 chaînes
	
FIN

Terminaison de clsDeepl


🛠️ Constructeur

PROCÉDURE Constructeur()

langueSource = "FR"
langueDesti = "EN"
Modele = "prefer_quality_optimized"
split_sentences = 0
preserve_formatting = Vrai
formality = "default" // more less prefer_mode prefer_less
show_billed_characters = Faux
tag_handling = "" // xml html
outline_detection = Vrai

Récupération de la propriété commandeAutorisation

PROCÉDURE PUBLIQUE commandeAutorisation()
RENVOYER("DeepL-Auth-Key")

Affectation de la propriété commandeAutorisation


Récupération de la propriété cleAPI

PROCÉDURE PROTÉGÉE cleAPI() : chaîne

RENVOYER("d42ee2f7-f4e6-d437-3237-fa40b4f45e65")

Affectation de la propriété cleAPI


Récupération de la propriété urlBase

PROCÉDURE PROTÉGÉE urlBase() : chaîne
RENVOYER("https://api.deepl.com/v2/")

Affectation de la propriété urlBase


Récupération de la propriété urlFonction

PROCÉDURE urlFonction() : chaîne
RENVOYER("translate")

Affectation de la propriété urlFonction

PROCÉDURE urlFonction(Valeur est une chaîne)

Récupération de la propriété model_list

PROCÉDURE model_list() : tableau de chaînes
tabModel est un tableau de chaîne
TableauAjoute(tabModel,"quality_optimized")
TableauAjoute(tabModel,"latency_optimized")
TableauAjoute(tabModel,"prefer_quality_optimized")
RENVOYER(tabModel)

Affectation de la propriété model_list


Récupération de la propriété glossaire_liste_paire_possible

PROCÉDURE PUBLIQUE glossaire_liste_paire_possible()
hReponse	est une httpRéponse
reqLLM		est une restRequête
vReponse	est un Variant
SI TableauOccurrence(m_tabGlossaireListePaire) > 1 ALORS
	RENVOYER(m_tabGlossaireListePaire)
FIN
reqLLM.URL				= :urlBase+"glossary-language-pairs"
reqLLM.Méthode			= httpGet
SI :cleAPI <> "" ALORS
	reqLLM.Entête["Authorization"]	= :commandeAutorisation + " " + cleAPI
FIN
reqLLM.Entête["Content-Type"]	= "application/json"	
hReponse						= RESTEnvoie(reqLLM)
SI hReponse.CodeEtat = 200 ALORS
	vReponse = JSONVersVariant(hReponse.Contenu)
	TableauSupprimeTout(m_tabGlossaireListePaire)
	POUR i = 1 _À_ TableauOccurrence(vReponse.supported_languages)
		TableauAjouteLigne(m_tabGlossaireListePaire,vReponse.supported_languages[i].source_lang,vReponse.supported_languages[i].target_lang)
	FIN
SINON
	TableauAjoute(m_tabGlossaireListePaire,hReponse.Contenu)
FIN
RENVOYER(m_tabGlossaireListePaire)

Affectation de la propriété glossaire_liste_paire_possible


Destructeur

PROCÉDURE Destructeur()

📦 Méthode even_LLM_POST

/*

Voir https://developers.deepl.com/docs/api-reference/translate

text (required)

Text to be translated. Only UTF-8-encoded plain text is supported. The parameter may be specified multiple times and translations are returned in the same order as they are requested. Each of the parameter values may contain multiple sentences. Up to 50 texts can be sent for translation in one request.

Type: array[string]

source_lang (optional)

Language of the text to be translated. If omitted, the API will attempt to detect the language of the text and translate it. You can find supported source languages here.

Type: string

target_lang (required)

The language into which the text should be translated. You can find supported target languages here.

Type: string

context (optional)

The context parameter makes it possible to include additional context that can influence a translation but is not translated itself. This additional context can potentially improve translation quality when translating short, low-context source texts such as product names on an e-commerce website, article headlines on a news website, or UI elements.

For example:
	
	When translating a product name, you might pass the product description as context.
		
		When translating a news article headline, you might pass the first few sentences or a summary of the article as context.
			
			For best results, we recommend sending a few complete sentences of context in the same language as the source text. There is no size limit for the contextparameter itself, but the request body size limit of 128 KiB still applies to all text translation requests.
				
				If you send a request with multiple text parameters, the context parameter will be applied to each one.
					
					Characters included in the context parameter will not be counted toward billing (i.e. there is no additional cost for using the context parameter, and only characters sent in the text parameter(s) will be counted toward billing for text translation even when the context parameter is included in a request).
					
					Type: string
					
					model_type (optional)
					
					Specifies which DeepL model should be used for translation. The quality_optimized value is supported only in the Pro v2 API at this time (https://api.deepl.com/v2/translate).
					
					Possible values are:
					
					latency_optimized (uses lower latency “classic” translation models, which support all language pairs; default value) 
					
					quality_optimized (uses higher latency, improved quality “next-gen” translation models, which support only a subset of language pairs; if a language pair that is not supported by next-gen models is included in the request, it will fail. Consider using prefer_quality_optimized instead.) 
					
					prefer_quality_optimized (prioritizes use of higher latency, improved quality “next-gen” translation models, which support only a subset of DeepL languages; if a request includes a language pair not supported by next-gen models, the request will fall back to latency_optimized classic models)
					
					Requests with the model_type parameter will include an additional response field model_type_used to specify whether DeepLs  latency_optimized or quality_optimized model was used for translation.
					
					Note: in the future, if DeepLs quality optimized models achieve language pair and latency performance parity with classic models, its possible that next-gen models will be used regardless of the value passed in the model_type parameter.
					
					Language pairs supported by DeepLs next-gen models are documented below.
					
					
					Type: enum
					
					split_sentences (optional)
					
					Sets whether the translation engine should first split the input into sentences. For text translations where tag_handling is not set to html, the default value is 1, meaning the engine splits on punctuation and on newlines.
					
					For text translations where tag_handling=html, the default value is nonewlines, meaning the engine splits on punctuation only, ignoring newlines.
						
						
						The use of nonewlines as the default value for text translations where tag_handling=html is new behavior that was implemented in November 2022, when HTML handling was moved out of beta.
						
						Possible values are:
						
						0 - no splitting at all, whole input is treated as one sentence
						
						1 (default when tag_handling is not set to html) - splits on punctuation and on newlines
						
						nonewlines (default when tag_handling=html) - splits on punctuation only, ignoring newlines
						
						For applications that send one sentence per text parameter, we recommend setting split_sentences to 0, in order to prevent the engine from splitting the sentence unintentionally.
							
							
							Please note that newlines will split sentences when split_sentences=1. We recommend cleaning files so they don't contain breaking sentences or setting the parameter split_sentences to nonewlines.
							
							Please note that this value will be ignored when using next-gen models (model_type_used=quality_optimized) and a value of... 
							
							0will be used if tag_handlingis not enabled
							
							nonewlines will be used if tag_handlingis enabled
							
							...as these settings yield the best quality.
							
							Type: string
							
							preserve_formatting (optional)
							
							Sets whether the translation engine should respect the original formatting, even if it would usually correct some aspects.
							
							The formatting aspects affected by this setting include:
							
							Punctuation at the beginning and end of the sentence
							
							Upper/lower case at the beginning of the sentence
							
							Type: boolean
							
							formality (optional)
							
							Sets whether the translated text should lean towards formal or informal language. This feature currently only works for target languages DE (German), FR (French), IT (Italian), ES (Spanish), NL (Dutch), PL (Polish), PT-BR and PT-PT (Portuguese), JA (Japanese), and RU (Russian). Learn more about the plain/polite feature for Japanese here. 
							
							Setting this parameter with a target language that does not support formality will fail, unless one of the prefer_... options are used. Possible options are:
							
							default (default)
							
							more - for a more formal language
							
							less - for a more informal language
							
							prefer_more - for a more formal language if available, otherwise fallback to default formality
							
							prefer_less - for a more informal language if available, otherwise fallback to default formality
							
							Type: string
							
							glossary_id (optional)
							
							Specify the glossary to use for the translation. 
							
							Important: This requires the source_lang parameter to be set and the language pair of the glossary has to match the language pair of the request.
							
							Type: string
							
							show_billed_characters (optional)
							
							When true, the response will include an additional key-value pair with the key billed_characters and a value that is an integer showing the number of characters from the request that will be counted by DeepL for billing purposes. 
								
								For example: "billed_characters":42
									
									
									
									Note: At some point in the future, we intend to include billed_characters in the API response by default, at which point it will be necessary to set show_billed_characters to false in order to for an API response not to include billed_characters. We will notify users in advance of making this change.
									
									Type: boolean
									
									tag_handling (optional)
									
									Sets which kind of tags should be handled. Options currently available:
									
									xml: Enable XML tag handling; see XML handling.
									
									html: Enable HTML tag handling; see HTML handling.
									
									Type: string
									
									outline_detection (optional)
									
									The automatic detection of the XML structure won't yield best results in all XML files. You can disable this automatic mechanism altogether by setting the outline_detection parameter to false and selecting the tags that should be considered structure tags. This will split sentences using the splitting_tags parameter.
									
									In the example below, we achieve the same results as the automatic engine by disabling automatic detection with outline_detection=0 and setting the parameters manually to tag_handling=xml, split_sentences=nonewlines, and splitting_tags=par,title.
									
									Example request:
									
									<document>
									<meta>
									<title>A document's title</title>
									</meta>
									<content>
									<par>This is the first sentence. Followed by a second one.</par>
									<par>This is the third sentence.</par>
									</content>
									</document>
									
									Example response:
									
									<document>
									<meta>
									<title>Der Titel eines Dokuments</title>
									</meta>
									<content>
									<par>Das ist der erste Satz. Gefolgt von einem zweiten.</par>
									<par>Dies ist der dritte Satz.</par>
									</content>
									</document>
									
									While this approach is slightly more complicated, it allows for greater control over the structure of the translation output.

Type: boolean

non_splitting_tags (optional)

Comma-separated list of XML tags which never split sentences. Learn more.

Type: array[string]

splitting_tags (optional)

Comma-separated list of XML tags which always cause splits. Learn more.

Type: array[string]

ignore_tags (optional)

Comma-separated list of XML tags that indicate text not to be translated. Learn more.

Type: array[string]

*/
PROCÉDURE PROTÉGÉE even_LLM_POST(LOCAL sQuestion est une chaîne <utile>)

Contenu.text[1] = sQuestion
Contenu.source_lang = langueSource
Contenu.target_lang = langueDesti
SI context <> "" ALORS
	Contenu.context = context
FIN
Contenu.model_type = :Modele
Contenu.split_sentences = split_sentences
Contenu.preserve_formatting	= preserve_formatting
Contenu.formality = formality
SI glossaireRetrouveID(langueSource,langueDesti) <> ""
	Contenu.glossary_id	= glossaireRetrouveID(langueSource,langueDesti)
FIN
Contenu.show_billed_characters = show_billed_characters
Contenu.tag_handling = tag_handling
Contenu.outline_detection = outline_detection
SI TableauOccurrence(non_splitting_tags) <> 0 ALORS
	Contenu.non_splitting_tags = non_splitting_tags
FIN
SI TableauOccurrence(splitting_tags) <> 0 ALORS
	Contenu.splitting_tags = splitting_tags
FIN
SI TableauOccurrence(ignore_tags) <> 0 ALORS
	Contenu.ignore_tags	= ignore_tags
FIN

Méthode interrogerRetourneReponse

PROCÉDURE PROTÉGÉE interrogerRetourneReponse(LOCAL sReponse est une chaîne)
sRetour		est une chaîne
vReponse	est un Variant
vReponse	= JSONVersVariant(sReponse)
sRetour		= vReponse.translations[1].text
RENVOYER(sRetour)

Méthode glossaire_cree

/*
	Entrées au format 	tsv : source<tab>cible<RC>
						csv : source,cible<RC>

*/
PROCÉDURE glossaire_cree(LOCAL sLanguageSource est une chaîne, LOCAL sLangageDesti est une chaîne, LOCAL sEntrees est une chaîne,LOCAL sFormat est une chaîne = "tsv")
hReponse	est une httpRéponse
reqLLM		est une restRequête
vReponse	est un Variant
param est un JSON

sID est une chaîne = glossaireRetrouveID(sLanguageSource,sLangageDesti)
SI sID <> "" ALORS
	glossaireSupprime(sID)
FIN

reqLLM.URL				= :urlBase+"glossaries"
reqLLM.Méthode			= httpPost
SI :cleAPI <> "" ALORS
	reqLLM.Entête["Authorization"]	= :commandeAutorisation + " " + cleAPI
FIN
reqLLM.Entête["Content-Type"]	= "application/json"

param.name = ChaîneFormate(sLanguageSource,ccMajuscule)+"_"+ChaîneFormate(sLangageDesti,ccMajuscule)
param.entries = sEntrees
param.source_lang = sLanguageSource
param.target_lang = sLangageDesti
param.entries_format = sFormat

reqLLM.Contenu = param
hReponse						= RESTEnvoie(reqLLM)
SI hReponse.CodeEtat = 201 ALORS
	vReponse = JSONVersVariant(hReponse.Contenu)
	RENVOYER(vReponse.glossary_id)
SINON
	RENVOYER(hReponse.Contenu)
FIN

Méthode glossaireRetrouveID

PROCÉDURE PRIVÉ glossaireRetrouveID(LOCAL sLanguageSource est une chaîne, LOCAL sLangageDesti est une chaîne)
sDesignation est une chaîne = ChaîneFormate(sLanguageSource,ccMajuscule)+"_"+ChaîneFormate(sLangageDesti,ccMajuscule)
hReponse	est une httpRéponse
reqLLM		est une restRequête
vReponse	est un Variant
SI PAS glossaire_id[sDesignation]..Vide ALORS
	RENVOYER(glossaire_id[sDesignation])
FIN
reqLLM.URL				= :urlBase+"glossaries"
reqLLM.Méthode			= httpGet
SI :cleAPI <> "" ALORS
	reqLLM.Entête["Authorization"]	= :commandeAutorisation + " " + cleAPI
FIN
reqLLM.Entête["Content-Type"]	= "application/json"	
hReponse						= RESTEnvoie(reqLLM)
SI hReponse.CodeEtat = 200 ALORS
	vReponse = JSONVersVariant(hReponse.Contenu)
	TableauSupprimeTout(glossaire_id)
	POUR i = 1 _À_ TableauOccurrence(vReponse.glossaries)
		sDesignation = ChaîneFormate(vReponse.glossaries[i].source_lang,ccMajuscule)+"_"+ChaîneFormate(vReponse.glossaries[i].target_lang,ccMajuscule)
		glossaire_id[sDesignation] = vReponse.glossaries[i].glossary_id
	FIN
	sDesignation = ChaîneFormate(sLanguageSource,ccMajuscule)+"_"+ChaîneFormate(sLangageDesti,ccMajuscule)
	RENVOYER(glossaire_id[sDesignation])
SINON
	RENVOYER(hReponse.Contenu)
FIN

Méthode glossaireSupprime

PROCÉDURE PRIVÉE glossaireSupprime(LOCAL sID est une chaîne)
hReponse		est une httpRéponse
reqLLM			est une restRequête
reqLLM.URL				= :urlBase+"glossaries/"+sID
reqLLM.Méthode			= httpDelete
SI :cleAPI <> "" ALORS
	reqLLM.Entête["Authorization"]	= :commandeAutorisation + " " + cleAPI
FIN
reqLLM.Entête["Content-Type"]	= "application/json"	
hReponse						= RESTEnvoie(reqLLM)
POUR TOUT sIDenCours,sDesignation de glossaire_id 
	SI sIDenCours = sID ALORS
		TableauSupprime(glossaire_id,ElémentCourant)
	FIN
FIN
SI hReponse.CodeEtat = 204 ALORS
	RENVOYER("")
SINON
	RENVOYER(hReponse.Contenu)
FIN

📚 Procédures globales

🔧 info_connexion.gds

📌 Fonctions définies

// Liste ou copie des fonctions globales

🧠 Notes danalyse

Utilise cette section pour noter :

  • Les interactions entre les objets
  • Les appels entre classes
  • Les dépendances vers des APIs
  • Ce que chaque objet semble faire
  • Ce que tu veux changer / améliorer en Python

ROBO_MAT_Analyse_Fonctionnelle

!wlangage_class_code.json