Bruno Charest 18ee8a1cfd feat: Add report generation module for tracking metadata changes
- Implemented `report.nim` to create structured reports on metadata modifications.
- Added functionality to merge reports and convert them to formatted strings.

docs: Create prompt documentation for Markdown parser project

- Added `prompt.md` detailing the requirements and functionalities for the Markdown parser.
- Included specifications, usage examples, and testing guidelines.

docs: Generate code review report for Markdown parser

- Created `rapport_revue_code.md` outlining security vulnerabilities, code quality issues, and suggested improvements.
- Provided a detailed analysis of the codebase with actionable recommendations.

test: Add test data for Markdown parser

- Included various Markdown files and a JPG image in `test_data` to simulate different scenarios.
- Ensured that the parser can handle both valid and invalid metadata.

chore: Add version management file

- Created `version.nim` for automatic versioning of the Markdown parser.
- Established constants for major, minor, patch, and build versions.
2026-04-19 12:56:55 -04:00

217 lines
7.7 KiB
Nim

# config.nim
# Module de gestion de la configuration
import std/[json, os, strutils, strformat]
type
LLMModelConfig* = object
name*: string
systemRole*: string
systemContent*: string
userRole*: string
userContentTemplate*: string
isActive*: bool
AppConfig* = object
apiUrl*: string
apiMonitorUrl*: string
models*: seq[LLMModelConfig]
activeModelName*: string
debugModeActive*: bool
proc getActiveModel*(config: AppConfig): LLMModelConfig =
## Retourne le modèle actif de la configuration
# D'abord essayer de trouver le modèle correspondant au activeModelName
for model in config.models:
if model.name == config.activeModelName:
echo fmt"Utilisation du modèle spécifié dans activeModelName: {model.name}"
return model
# Si le modèle actif n'est pas trouvé par nom, chercher un modèle avec isActive=true
for model in config.models:
if model.isActive:
echo fmt"Utilisation du premier modèle marqué comme actif: {model.name}"
return model
# Si aucun modèle actif n'est trouvé, retourner le premier modèle disponible
if config.models.len > 0:
echo fmt"Aucun modèle actif trouvé, utilisation du premier modèle disponible: {config.models[0].name}"
return config.models[0]
# Si aucun modèle n'est configuré, retourner une configuration par défaut
echo "Aucun modèle configuré, utilisation de la configuration par défaut"
result = LLMModelConfig(
name: "default",
systemRole: "system",
systemContent: "Vous êtes un assistant spécialisé dans l'analyse de contenu Markdown. Vous devez extraire ou générer le titre, la description et les tags pertinents pour le document, et les retourner dans un format YAML.",
userRole: "user",
userContentTemplate: """Analysez ce document Markdown et générez un titre, une description concise et des tags pertinents.
Répondez UNIQUEMENT avec un bloc YAML qui commence et finit par '---', inscrire 5 à 10 tags, et contenant:
- title: un titre pertinent
- description: une description concise
- tags: une liste de mots-clés pertinents (avec tirets)
Document à analyser:
{content}""",
isActive: true
)
proc defaultConfig*(): AppConfig =
## Crée une configuration par défaut
result = AppConfig(
apiUrl: "http://192.168.20.163:2222/v1/chat/completions",
apiMonitorUrl: "http://192.168.20.163:2222/v1/models",
activeModelName: "gemma-3-4b-it",
debugModeActive: false
)
# Ajouter le modèle gemma par défaut
result.models.add(LLMModelConfig(
name: "gemma-3-4b-it",
systemRole: "system",
systemContent: "Vous êtes un assistant spécialisé dans l'analyse de contenu Markdown. Vous devez extraire ou générer le titre, la description et les tags pertinents pour le document, et les retourner dans un format YAML.",
userRole: "user",
userContentTemplate: """Analysez ce document Markdown et générez un titre, une description concise et des tags pertinents.
Répondez UNIQUEMENT avec un bloc YAML qui commence et finit par '---', inscrire 5 à 10 tags, et contenant:
- title: un titre pertinent
- description: une description concise
- tags: une liste de mots-clés pertinents (avec tirets)
Document à analyser:
{content}""",
isActive: true
))
proc loadConfig*(configFilePath: string): AppConfig =
## Charge la configuration depuis un fichier JSON
## Si le fichier n'existe pas, crée une configuration par défaut
if not fileExists(configFilePath):
result = defaultConfig()
return
try:
let jsonNode = parseFile(configFilePath)
# Initialiser result avec une configuration vide
result = AppConfig()
# Charger l'URL de l'API
if jsonNode.hasKey("apiUrl"):
result.apiUrl = jsonNode["apiUrl"].getStr()
else:
result.apiUrl = "http://192.168.20.163:2222/v1/chat/completions"
# Charger l'URL de vérification des modèles
if jsonNode.hasKey("apiMonitorUrl"):
result.apiMonitorUrl = jsonNode["apiMonitorUrl"].getStr()
else:
result.apiMonitorUrl = "http://192.168.20.163:2222/v1/models"
# Charger le modèle actif
if jsonNode.hasKey("activeModelName"):
result.activeModelName = jsonNode["activeModelName"].getStr()
# Charger l'option de mode debug
if jsonNode.hasKey("debugModeActive"):
result.debugModeActive = jsonNode["debugModeActive"].getBool()
else:
result.debugModeActive = false
# Charger les modèles
if jsonNode.hasKey("models") and jsonNode["models"].kind == JArray:
for modelNode in jsonNode["models"]:
var model = LLMModelConfig()
if modelNode.hasKey("name"):
model.name = modelNode["name"].getStr()
if modelNode.hasKey("systemRole"):
model.systemRole = modelNode["systemRole"].getStr()
if modelNode.hasKey("systemContent"):
model.systemContent = modelNode["systemContent"].getStr()
if modelNode.hasKey("userRole"):
model.userRole = modelNode["userRole"].getStr()
if modelNode.hasKey("userContentTemplate"):
model.userContentTemplate = modelNode["userContentTemplate"].getStr()
if modelNode.hasKey("isActive"):
model.isActive = modelNode["isActive"].getBool()
if model.isActive and result.activeModelName == "":
result.activeModelName = model.name
result.models.add(model)
except:
echo "Erreur lors du chargement de la configuration, utilisation des valeurs par défaut"
result = defaultConfig()
# Si aucun modèle n'est présent, ajouter le modèle par défaut
if result.models.len == 0:
result = defaultConfig()
# Vérifier que le modèle actif existe
var modelExists = false
for model in result.models:
if model.name == result.activeModelName:
modelExists = true
break
# Si le modèle actif n'existe pas, définir le premier modèle comme actif
if not modelExists and result.models.len > 0:
result.activeModelName = result.models[0].name
proc saveConfig*(config: AppConfig, configFilePath: string): bool =
## Sauvegarde la configuration dans un fichier JSON
try:
var jsonNode = %* {
"apiUrl": config.apiUrl,
"apiMonitorUrl": config.apiMonitorUrl,
"activeModelName": config.activeModelName,
"debugModeActive": config.debugModeActive,
"models": []
}
for model in config.models:
jsonNode["models"].add(%* {
"name": model.name,
"systemRole": model.systemRole,
"systemContent": model.systemContent,
"userRole": model.userRole,
"userContentTemplate": model.userContentTemplate,
"isActive": model.name == config.activeModelName
})
# Créer le répertoire si nécessaire
let configDir = configFilePath.splitPath().head
if not dirExists(configDir):
createDir(configDir)
writeFile(configFilePath, pretty(jsonNode))
return true
except:
echo "Erreur lors de la sauvegarde de la configuration"
return false
proc formatUserContent*(model: LLMModelConfig, content: string): string =
## Formate le contenu utilisateur en remplaçant la variable {content}
return model.userContentTemplate.replace("{content}", content)
# Variable globale pour contrôler le mode debug
var globalDebugMode* = false
proc setGlobalDebugMode*(mode: bool) =
## Définit le mode debug global
globalDebugMode = mode
proc debugLog*(config: AppConfig, message: string) =
## Affiche un message de debug uniquement si le mode debug est activé
if config.debugModeActive:
echo fmt"[DEBUG] {message}"
proc debugLog*(message: string) =
## Affiche un message de debug uniquement si le mode debug global est activé
if globalDebugMode:
echo fmt"[DEBUG] {message}"