Una guía de codificación para construir sistemas de control de calidad modulares y autocorrectados con DSPY

En este tutorial, exploramos cómo construir un sistema inteligente y autocorrectivo de preguntas sobre la respuesta utilizando el Dspy Marco, integrado con el modelo Gemini 1.5 Flash de Google. Comenzamos definiendo firmas estructuradas que claramente describan el comportamiento de entrada-salida, que DSPY utiliza como base para construir tuberías confiables. Con el enfoque de programación declarativa de DSPY, construimos módulos compuestos, como AdvancedQA y SimpleRag, para responder preguntas utilizando la generación de contexto y recuperación de la recuperación. Al combinar la modularidad de DSPY con el poderoso razonamiento de Gemini, elaboramos un sistema de IA capaz de ofrecer respuestas precisas y paso a paso. A medida que avanzamos, también aprovechamos las herramientas de optimización de DSPY, como BootstraPfewshot, para mejorar automáticamente el rendimiento en función de los ejemplos de capacitación.

!pip install dspy-ai google-generativeai


import dspy
import google.generativeai as genai
import random
from typing import List, Optional


GOOGLE_API_KEY = "Use Your Own API Key"  
genai.configure(api_key=GOOGLE_API_KEY)


dspy.configure(lm=dspy.LM(model="gemini/gemini-1.5-flash", api_key=GOOGLE_API_KEY))

Comenzamos instalando las bibliotecas requeridas, DSPY para tuberías de IA declarativas y Google-Generativeai para acceder a los modelos Gemini de Google. Después de importar los módulos necesarios, configuramos Gemini usando nuestra tecla API. Finalmente, configuramos DSPY para usar el modelo Gemini 1.5 Flash como el backend de nuestro modelo de idioma.

class QuestionAnswering(dspy.Signature):
    """Answer questions based on given context with reasoning."""
    context: str = dspy.InputField(desc="Relevant context information")
    question: str = dspy.InputField(desc="Question to answer")
    reasoning: str = dspy.OutputField(desc="Step-by-step reasoning")
    answer: str = dspy.OutputField(desc="Final answer")


class FactualityCheck(dspy.Signature):
    """Verify if an answer is factually correct given context."""
    context: str = dspy.InputField()
    question: str = dspy.InputField()
    answer: str = dspy.InputField()
    is_correct: bool = dspy.OutputField(desc="True if answer is factually correct")

Definimos dos firmas DSPY para estructurar las entradas y salidas de nuestro sistema. Primero, QuestsAnwering espera un contexto y una pregunta, y devuelve tanto el razonamiento como una respuesta final, lo que permite que el modelo explique su proceso de pensamiento. A continuación, FactualityCheck está diseñado para verificar la veracidad de una respuesta devolviendo un simple booleano, ayudándonos a construir un sistema de control de control de autocorrección.

class AdvancedQA(dspy.Module):
    def __init__(self, max_retries: int = 2):
        super().__init__()
        self.max_retries = max_retries
        self.qa_predictor = dspy.ChainOfThought(QuestionAnswering)
        self.fact_checker = dspy.Predict(FactualityCheck)
       
    def forward(self, context: str, question: str) -> dspy.Prediction:
        prediction = self.qa_predictor(context=context, question=question)
       
        for attempt in range(self.max_retries):
            fact_check = self.fact_checker(
                context=context,
                question=question,
                answer=prediction.answer
            )
           
            if fact_check.is_correct:
                break
               
            refined_context = f"{context}nnPrevious incorrect answer: {prediction.answer}nPlease provide a more accurate answer."
            prediction = self.qa_predictor(context=refined_context, question=question)
       
        return prediction

Creamos un módulo avanzado para agregar capacidad de autocorrección a nuestro sistema de control de calidad. Primero utiliza un predictor de cadena de pensamiento para generar una respuesta con razonamiento. Luego, verifica la precisión objetiva utilizando un predictor de verificación de hechos. Si la respuesta es incorrecta, refinamos el contexto y vuelvamos a intentar, hasta un número especificado de veces, para garantizar resultados más confiables.

class SimpleRAG(dspy.Module):
    def __init__(self, knowledge_base: List[str]):
        super().__init__()
        self.knowledge_base = knowledge_base
        self.qa_system = AdvancedQA()
       
    def retrieve(self, question: str, top_k: int = 2) -> str:
        # Simple keyword-based retrieval (in practice, use vector embeddings)
        scored_docs = []
        question_words = set(question.lower().split())
       
        for doc in self.knowledge_base:
            doc_words = set(doc.lower().split())
            score = len(question_words.intersection(doc_words))
            scored_docs.append((score, doc))
       
        # Return top-k most relevant documents
        scored_docs.sort(reverse=True)
        return "nn".join([doc for _, doc in scored_docs[:top_k]])
   
    def forward(self, question: str) -> dspy.Prediction:
        context = self.retrieve(question)
        return self.qa_system(context=context, question=question)

Construimos un módulo SimpleRag para simular la generación de recuperación con una generación con DSPY. Proporcionamos una base de conocimiento e implementamos un Retriever básico basado en palabras clave para obtener los documentos más relevantes para una pregunta determinada. Estos documentos sirven como contexto para el módulo AdvancedQA, que luego realiza razonamiento y autocorrección para producir una respuesta precisa.

knowledge_base = [
    “Use Your Context and Knowledge Base Here”
]


training_examples = [
    dspy.Example(
        question="What is the height of the Eiffel Tower?",
        context="The Eiffel Tower is located in Paris, France. It was constructed from 1887 to 1889 and stands 330 meters tall including antennas.",
        answer="330 meters"
    ).with_inputs("question", "context"),
   
    dspy.Example(
        question="Who created Python programming language?",
        context="Python is a high-level programming language created by Guido van Rossum. It was first released in 1991 and emphasizes code readability.",
        answer="Guido van Rossum"
    ).with_inputs("question", "context"),
   
    dspy.Example(
        question="What is machine learning?",
        context="ML focuses on algorithms that can learn from data without being explicitly programmed.",
        answer="Machine learning focuses on algorithms that learn from data without explicit programming."
    ).with_inputs("question", "context")
]

Definimos una pequeña base de conocimiento que contiene hechos diversos en varios temas, incluida la historia, la programación y la ciencia. Esto sirve como nuestra fuente de contexto para la recuperación. Junto, preparamos un conjunto de ejemplos de capacitación para guiar el proceso de optimización de DSPY. Cada ejemplo incluye una pregunta, su contexto relevante y la respuesta correcta, ayudando a nuestro sistema a aprender a responder con mayor precisión.

def accuracy_metric(example, prediction, trace=None):
    """Simple accuracy metric for evaluation"""
    return example.answer.lower() in prediction.answer.lower()


print("🚀 Initializing DSPy QA System with Gemini...")
print("📝 Note: Using Google's Gemini 1.5 Flash (free tier)")
rag_system = SimpleRAG(knowledge_base)


basic_qa = dspy.ChainOfThought(QuestionAnswering)


print("n📊 Before Optimization:")
test_question = "What is the height of the Eiffel Tower?"
test_context = knowledge_base[0]
initial_prediction = basic_qa(context=test_context, question=test_question)
print(f"Q: {test_question}")
print(f"A: {initial_prediction.answer}")
print(f"Reasoning: {initial_prediction.reasoning}")


print("n🔧 Optimizing with BootstrapFewShot...")
optimizer = dspy.BootstrapFewShot(metric=accuracy_metric, max_bootstrapped_demos=2)
optimized_qa = optimizer.compile(basic_qa, trainset=training_examples)


print("n📈 After Optimization:")
optimized_prediction = optimized_qa(context=test_context, question=test_question)
print(f"Q: {test_question}")
print(f"A: {optimized_prediction.answer}")
print(f"Reasoning: {optimized_prediction.reasoning}")

Comenzamos definiendo una métrica de precisión simple para verificar si la respuesta predicha contiene la respuesta correcta. Después de inicializar nuestro sistema SimpleRag y una cadena de referencia de módulo de control de calidad, lo probamos en una pregunta de muestra antes de cualquier optimización. Luego, utilizando el optimizador BootstraPfewshot de DSPY, ajustamos el sistema de control de calidad con nuestros ejemplos de entrenamiento. Esto permite que el modelo genere automáticamente indicaciones más efectivas, lo que lleva a una precisión mejorada, lo que verificamos al comparar las respuestas antes y después de la optimización.

def evaluate_system(qa_module, test_cases):
    """Evaluate QA system performance"""
    correct = 0
    total = len(test_cases)
   
    for example in test_cases:
        prediction = qa_module(context=example.context, question=example.question)
        if accuracy_metric(example, prediction):
            correct += 1
   
    return correct / total


print(f"n📊 Evaluation Results:")
print(f"Basic QA Accuracy: {evaluate_system(basic_qa, training_examples):.2%}")
print(f"Optimized QA Accuracy: {evaluate_system(optimized_qa, training_examples):.2%}")


print("n✅ Tutorial Complete! Key DSPy Concepts Demonstrated:")
print("1. 🔤 Signatures - Defined input/output schemas")
print("2. 🏗️  Modules - Built composable QA systems")
print("3. 🔄 Self-correction - Implemented iterative improvement")
print("4. 🔍 RAG - Created retrieval-augmented generation")
print("5. ⚡ Optimization - Used BootstrapFewShot to improve prompts")
print("6. 📊 Evaluation - Measured system performance")
print("7. 🆓 Free API - Powered by Google Gemini 1.5 Flash")

Ejecutamos un avanzado TRAPO demostración haciendo múltiples preguntas en diferentes dominios. Para cada pregunta, el sistema SimpleRag recupera el contexto más relevante y luego utiliza el módulo AdvancedQA de autocorrección para generar una respuesta bien razonada. Imprimimos las respuestas junto con una vista previa del razonamiento, mostrando cómo DSPY combina la recuperación y la generación reflexiva para ofrecer respuestas confiables.

En conclusión, hemos demostrado con éxito todo el potencial de DSPY para construir tuberías de control de calidad avanzadas. Vemos cómo DSPY simplifica el diseño de módulos inteligentes con interfaces claras, admite bucles de autocorrección, integra la recuperación básica y permite una optimización de inmediato de pocas disparos con un código mínimo. Con solo unas pocas líneas, configuramos y evaluamos nuestros modelos utilizando ejemplos del mundo real, midiendo las ganancias de rendimiento. Esta experiencia práctica muestra cómo DSPY, cuando se combina con la API de Géminis de Google, nos permite prototipos, probar y escalar aplicaciones lingüísticas sofisticadas sin lógica calderosa o compleja.


Mira el Codos. Todo el crédito por esta investigación va a los investigadores de este proyecto. Además, siéntete libre de seguirnos Gorjeo, YouTube y Spotify Y no olvides unirte a nuestro Subreddit de 100k+ ml y suscribirse a Nuestro boletín.


Sana Hassan, una pasante de consultoría en MarktechPost y estudiante de doble grado en IIT Madras, le apasiona aplicar tecnología e IA para abordar los desafíos del mundo real. Con un gran interés en resolver problemas prácticos, aporta una nueva perspectiva a la intersección de la IA y las soluciones de la vida real.