Aktiv læring til dataannotation: Gemini + Adala-vejledning

Adala Framework - Aktiv læring til dataannotation

Aktiv læring forandrer måden, vi træner på AI modeller ved intelligent at udvælge de mest værdifulde data til annotering. Når det parres med stærke LLM'er som Google Gemini, skaber det effektive annotationspipelines, der reducerer den manuelle indsats, samtidig med at høj datakvalitet opretholdes.

Denne guide undersøger, hvordan man bygger sådanne rørledninger ved hjælp af Adala-rammeværk – et kraftfuldt, men underudnyttet værktøj til autonom datamærkning.

Vi implementerer en medicinsk symptomklassifikator, der udnytter Gemini's færdigheder gennem en struktureret aktiv læringsarbejdsgang.

Forståelse af aktiv læring til dataannotation

Forståelse af aktiv læring til dataannotation

Aktiv læring tackler den største udfordring i overvåget læring: indhentning af store mængder mærkede data. I stedet for tilfældigt at udvælge datapunkter til annotering, aktive læringsalgoritmer Identificér de mest informative prøver, der vil bidrage mest til modelforbedring.

Hvorfor aktiv læring er vigtig:

Reducerer annoteringsomkostninger ved at fokusere den menneskelige indsats der, hvor det betyder mest.
Forbedrer model nøjagtighed med færre mærkede eksempler.
Adresserer klasseubalance ved at prioritere underrepræsenterede kategorier.
Skaber en kontinuerlig læringsløkke mellem model og annotator.

Adala-rammeværket bringer disse fordele ind i produktions arbejdsgange ved at levere modulære komponenter, der strømliner aktiv læringsproces. Før vi dykker ned i implementeringen, lad os's undersøge, hvad der gør Adala særligt velegnet til integration med moderne LLM'er som Google Gemini.

Hvad er Adala? En introduktion til rammeværket

Adala (Autonom datamærkningsagent) er en open source-ramme designet specifikt til implementering af specialiserede agenter til databehandlingI modsætning til traditionelle annotationsværktøjer anvender Adala en agentbaseret tilgang, der kombinerer:

Færdighedsbaseret arkitekturDefiner specifikke funktioner, som din annotationsagent har brug for.
Fleksibilitet i løbetidSkift mellem forskellige LLM'er eller brugerdefinerede runtime-indstillinger.
MiljøforbindelserInteragere med forskellige datakilder.
Indbyggede læringsløkkerTræn agenter til at forbedre sig over tid.

Kigger på Adala's quickstart-eksempel, vi kan se, hvordan det er struktureret følelsesklassificering:

python

import pandas as pd
from adala.agents import Agent
from adala.environments import StaticEnvironment
from adala.skills import ClassificationSkill
from adala.runtimes import OpenAIChatRuntime
from rich import print

# Train dataset
train_df = pd.DataFrame([
    ["It was the negative first impressions, and then it started working.", "Positive"],
    ["Not loud enough and doesn't turn on like it should.", "Negative"],
    ["I don't know what to say.", "Neutral"],
    ["Manager was rude, but the most important that mic shows very flat frequency response.", "Positive"],
    ["The phone doesn't seem to accept anything except CBR mp3s.", "Negative"],
    ["I tried it before, I bought this device for my son.", "Neutral"],
], columns=["text", "sentiment"])

# Test dataset
test_df = pd.DataFrame([
    "All three broke within two months of use.",
    "The device worked for a long time, can't say anything bad.",
    "Just a random line of text."
], columns=["text"])

agent = Agent(
    # connect to a dataset
    environment=StaticEnvironment(df=train_df),
    # define a skill
    skills=ClassificationSkill(
        name='sentiment',
        instructions="Label text as positive, negative or neutral.",
        labels=["Positive", "Negative", "Neutral"],
        input_template="Text: {text}",
        output_template="Sentiment: {sentiment}"
    ),
    # define runtimes
    runtimes = {
        'openai': OpenAIChatRuntime(model='gpt-4o'),
    },
    teacher_runtimes = {
        'default': OpenAIChatRuntime(model='gpt-4o'),
    },
    default_runtime='openai',
)

agent.learn(learning_iterations=3, accuracy_threshold=0.95)
predictions = agent.run(test_df)

Til vores opgave med klassificering af medicinske symptomer vil vi tilpasse denne arkitektur for at integrere Google Gemini mens man implementerer en brugerdefineret aktiv læringsstrategi.

Opsætning af dit miljø

Lade's Start med at installere Adala og nødvendige afhængigheder:

python

# Install Adala directly from GitHub
!pip install -q git+https://github.com/HumanSignal/Adala.git

# Verify installation
!pip list | grep adala

# Install additional dependencies
!pip install -q google-generativeai pandas matplotlib numpy

Vi skal også klone arkivet for at få direkte adgang til dets komponenter:

python

# Clone the repository for access to source files
!git clone https://github.com/HumanSignal/Adala.git

# Ensure the package is in our Python path
import sys
sys.path.append('./Adala')

# Import key components
from Adala.adala.annotators.base import BaseAnnotator
from Adala.adala.strategies.random_strategy import RandomStrategy
from Adala.adala.utils.custom_types import TextSample, LabeledSample

Integrering af Google Gemini som en brugerdefineret annotator

I modsætning til den oprindelige implementering, der brugte en grundlæggende wrapper omkring Google Gemini, vil vi bygge en mere robust annotator der følger Adala's designmønstre. Dette gør vores løsning mere vedligeholdelig og udvidelig.

Først skal vi konfigurere Google Generative AI klient:

python

import google.generativeai as genai
import os

# Set API key from environment or enter manually
GEMINI_API_KEY = os.getenv("GEMINI_API_KEY") or getpass("Enter your Gemini API Key: ")
genai.configure(api_key=GEMINI_API_KEY)

Nu opretter vi en brugerdefineret annotator ved at udvide Adala.'s BaseAnnotator-klasse:

python

import json
import re
from typing import List, Dict, Any, Optional

class GeminiAnnotator(BaseAnnotator):
    """Custom annotator using Google Gemini for medical symptom classification."""
    
    def __init__(self, 
                 model_name: str = "models/gemini-2.0-flash-lite", 
                 categories: List[str] = None,
                 temperature: float = 0.1):
        """Initialize the Gemini annotator.
        
        Args:
            model_name: The Gemini model to use
            categories: List of valid classification categories
            temperature: Controls randomness in generation (lower = more deterministic)
        """
        self.model = genai.GenerativeModel(
            model_name=model_name,
            generation_config={"temperature": temperature}
        )
        self.categories = categories or ["Cardiovascular", "Respiratory", 
                                         "Gastrointestinal", "Neurological"]
    
    def _build_prompt(self, text: str) -> str:
        """Create a structured prompt for the model.
        
        Args:
            text: The symptom text to classify
            
        Returns:
            A formatted prompt string
        """
        return f"""Classify this medical symptom into one of these categories:
        {', '.join(self.categories)}.
        
        Return JSON format: {{"category": "selected_category", 
        "confidence": 0.XX, "explanation": "brief_reason"}}
        
        SYMPTOM: {text}"""
    
    def _parse_response(self, response: str) -> Dict[str, Any]:
        """Extract structured data from model response.
        
        Args:
            response: Raw text response from Gemini
            
        Returns:
            Dictionary containing parsed fields
        """
        try:
            # Extract JSON from response even if surrounded by text
            json_match = re.search(r'(\{.*\})', response, re.DOTALL)
            result = json.loads(json_match.group(1) if json_match else response)
            return {
                "category": result.get("category", "Unknown"),
                "confidence": result.get("confidence", 0.0),
                "explanation": result.get("explanation", "")
            }
        except Exception as e:
            return {
                "category": "Unknown",
                "confidence": 0.0,
                "explanation": f"Error parsing response: {str(e)}"
            }
    
    def annotate(self, samples: List[TextSample]) -> List[LabeledSample]:
        """Annotate a batch of text samples.
        
        Args:
            samples: List of TextSample objects
            
        Returns:
            List of LabeledSample objects with annotations
        """
        results = []
        for sample in samples:
            prompt = self._build_prompt(sample.text)
            try:
                response = self.model.generate_content(prompt).text
                parsed = self._parse_response(response)
                
                # Create labeled sample with metadata
                labeled_sample = LabeledSample(
                    text=sample.text,
                    labels=parsed["category"],
                    metadata={
                        "confidence": parsed["confidence"],
                        "explanation": parsed["explanation"]
                    }
                )
            except Exception as e:
                # Graceful error handling
                labeled_sample = LabeledSample(
                    text=sample.text,
                    labels="Unknown",
                    metadata={"error": str(e)}
                )
            
            # Store reference to original sample
            labeled_sample._sample = sample
            results.append(labeled_sample)
            
        return results

Denne implementering giver betydelige forbedringer i forhold til originalen:

  1. Det følger korrekt klassearv fra Adala's BaseAnnotator
  2. Implementerer private hjælpermetoder til hurtig opbygning og responsparsing
  3. Bruger struktureret fejlhåndtering og skriv hints
  4. Leverer komplet dokumentation

Opbygning af en pipeline til symptomklassificering

Lade's opret et datasæt af medicinske symptomer til vores klassificeringsopgave. I modsætning til den oprindelige implementering bruger vi et mere forskelligartet datasæt med afbalanceret repræsentation på tværs af kategorier:

python

# Create a more comprehensive dataset
symptom_data = [
    # Cardiovascular symptoms
    "Chest pain radiating to left arm during exercise",
    "Heart palpitations when lying down",
    "Swollen ankles and shortness of breath",
    "Dizziness when standing up quickly",
    
    # Respiratory symptoms
    "Persistent dry cough with occasional wheezing",
    "Shortness of breath when climbing stairs",
    "Coughing up yellow or green mucus",
    "Rapid breathing with chest tightness",
    
    # Gastrointestinal symptoms
    "Stomach cramps and nausea after eating",
    "Burning sensation in upper abdomen",
    "Frequent loose stools with abdominal pain",
    "Yellowing of skin and eyes",
    
    # Neurological symptoms
    "Severe headache with sensitivity to light",
    "Numbness in fingers of right hand",
    "Memory loss and confusion",
    "Tremors in hands when reaching for objects"
]

# Convert to TextSample objects
text_samples = [TextSample(text=text) for text in symptom_data]

Implementering af avancerede aktive læringsstrategier

Den oprindelige implementering brugte en simpel prioritetsscoringsmekanisme. Vi vil forbedre denne med flere strategier for at demonstrere Adala.'s fleksibilitet:

python

import numpy as np
from typing import List, Callable

class PrioritizationStrategy:
    """Base class for sample prioritization strategies."""
    
    def score_samples(self, samples: List[TextSample]) -> np.ndarray:
        """Assign priority scores to samples.
        
        Args:
            samples: List of samples to score
            
        Returns:
            Array of scores, higher values indicate higher priority
        """
        raise NotImplementedError("Subclasses must implement this method")
    
    def select(self, samples: List[TextSample], n: int = 1) -> List[TextSample]:
        """Select the top n highest scoring samples.
        
        Args:
            samples: List of samples to select from
            n: Number of samples to select
            
        Returns:
            List of selected samples
        """
        if not samples:
            return []
        
        scores = self.score_samples(samples)
        indices = np.argsort(-scores)[:n]  # Descending order
        return [samples[i] for i in indices]

class KeywordPriority(PrioritizationStrategy):
    """Prioritize samples based on medical urgency keywords."""
    
    def __init__(self, keyword_weights: Dict[str, float]):
        """Initialize with keyword weights.
        
        Args:
            keyword_weights: Dictionary mapping keywords to priority weights
        """
        self.keyword_weights = keyword_weights
    
    def score_samples(self, samples: List[TextSample]) -> np.ndarray:
        scores = np.zeros(len(samples))
        for i, sample in enumerate(samples):
            # Base score
            scores[i] = 0.1
            
            # Add weights for each keyword found
            text_lower = sample.text.lower()
            for keyword, weight in self.keyword_weights.items():
                if keyword in text_lower:
                    scores[i] += weight
        
        return scores

class UncertaintyPriority(PrioritizationStrategy):
    """Prioritize samples based on model uncertainty."""
    
    def __init__(self, model_fn: Callable[[List[TextSample]], List[float]]):
        """Initialize with uncertainty model function.
        
        Args:
            model_fn: Function that returns uncertainty scores for samples
        """
        self.model_fn = model_fn
    
    def score_samples(self, samples: List[TextSample]) -> np.ndarray:
        # Higher uncertainty = higher priority
        return np.array(self.model_fn(samples))

# Create a combined strategy
keyword_weights = {
    "chest": 0.5,
    "pain": 0.4,
    "breathing": 0.4, 
    "dizz": 0.3,
    "head": 0.2,
    "numb": 0.2
}

keyword_strategy = KeywordPriority(keyword_weights)

Lad nu's implementer vores forbedrede aktive læringsloop:

python

from matplotlib import pyplot as plt
from IPython.display import clear_output
import time

def run_active_learning_loop(
    samples: List[TextSample],
    annotator: GeminiAnnotator,
    strategy: PrioritizationStrategy,
    iterations: int = 5,
    batch_size: int = 1,
    visualization_interval: int = 1
):
    """Run an active learning loop with visualization.
    
    Args:
        samples: Pool of unlabeled samples
        annotator: Annotation system
        strategy: Sample selection strategy
        iterations: Number of learning iterations
        batch_size: Samples to annotate per iteration
        visualization_interval: How often to update visualizations
    
    Returns:
        List of labeled samples
    """
    labeled_samples = []
    remaining_samples = list(samples)
    
    print("\nStarting Active Learning Loop:")
    
    for i in range(iterations):
        print(f"\n--- Iteration {i+1}/{iterations} ---")
        
        # Filter out already labeled samples
        remaining_samples = [
            s for s in remaining_samples 
            if s not in [getattr(l, '_sample', l) for l in labeled_samples]
        ]
        
        if not remaining_samples:
            print("No more samples to label. Stopping.")
            break
        
        # Select most important samples
        selected = strategy.select(remaining_samples, n=batch_size)
        
        # Annotate selected samples
        newly_labeled = annotator.annotate(selected)
        labeled_samples.extend(newly_labeled)
        
        # Display annotation results
        for sample in newly_labeled:
            print(f"Text: {sample.text}")
            print(f"Category: {sample.labels}")
            print(f"Confidence: {sample.metadata.get('confidence', 0):.2f}")
            explanation = sample.metadata.get('explanation', '')
            print(f"Explanation: {explanation[:100]}..." if len(explanation) > 100 else explanation)
            print()
        
        # Visualize results periodically
        if (i + 1) % visualization_interval == 0:
            visualize_results(labeled_samples)
            
    return labeled_samples

def visualize_results(labeled_samples: List[LabeledSample]):
    """Create visualizations of annotation results.
    
    Args:
        labeled_samples: List of labeled samples to visualize
    """
    if not labeled_samples:
        return
        
    # Extract data
    categories = [s.labels for s in labeled_samples]
    confidence = [s.metadata.get("confidence", 0) for s in labeled_samples]
    texts = [s.text[:30] + "..." for s in labeled_samples]
    
    # Set up plots
    fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(15, 6))
    
    # Plot 1: Confidence by category
    category_counts = {}
    category_confidence = {}
    
    for cat, conf in zip(categories, confidence):
        if cat not in category_counts:
            category_counts[cat] = 0
            category_confidence[cat] = 0
        category_counts[cat] += 1
        category_confidence[cat] += conf
    
    for cat in category_confidence:
        category_confidence[cat] /= category_counts[cat]
    
    cats = list(category_counts.keys())
    counts = list(category_counts.values())
    avg_conf = list(category_confidence.values())
    
    x = np.arange(len(cats))
    width = 0.35
    
    ax1.bar(x - width/2, counts, width, label='Count')
    ax1.bar(x + width/2, avg_conf, width, label='Avg Confidence')
    ax1.set_xticks(x)
    ax1.set_xticklabels(cats, rotation=45)
    ax1.set_title('Category Distribution and Confidence')
    ax1.legend()
    
    # Plot 2: Individual sample confidence
    sorted_indices = np.argsort(confidence)
    ax2.barh(range(len(texts)), [confidence[i] for i in sorted_indices])
    ax2.set_yticks(range(len(texts)))
    ax2.set_yticklabels([texts[i] for i in sorted_indices])
    ax2.set_title('Sample Confidence')
    ax2.set_xlabel('Confidence')
    
    plt.tight_layout()
    plt.show()

Kørsel af end-to-end-pipelinen

Nu kan vi køre vores komplette aktive læringspipeline:

python

# Initialize components
categories = ["Cardiovascular", "Respiratory", "Gastrointestinal", "Neurological"]
annotator = GeminiAnnotator(categories=categories)
strategy = keyword_strategy

# Run the active learning loop
labeled_data = run_active_learning_loop(
    samples=text_samples,
    annotator=annotator,
    strategy=strategy,
    iterations=5,
    visualization_interval=2
)

# Final visualization and analysis
visualize_results(labeled_data)

# Print summary statistics
print("\nAnnotation Summary:")
print(f"Total samples annotated: {len(labeled_data)}")

categories = [s.labels for s in labeled_data]
unique_categories = set(categories)
print(f"Categories found: {len(unique_categories)}")
for category in unique_categories:
    count = categories.count(category)
    print(f"  - {category}: {count} samples ({count/len(labeled_data):.1%})")

avg_confidence = sum(s.metadata.get("confidence", 0) for s in labeled_data) / len(labeled_data)
print(f"Average confidence: {avg_confidence:.2f}")

Praktiske anvendelser og udvidelser

Denne pipeline har adskillige praktiske anvendelser ud over medicinsk symptomklassificering:

1. Moderering af indhold

Prioriter brugerrapporteret indhold
Fokus på højrisikokategorier
Tilpas konfidensgrænser baseret på indholdstype

2. Analyse af kundefeedback

Identificer hastende kundeproblemer
Registrer nye produktproblemer
Send feedback til relevante teams

3. Behandling af kliniske forsøgsdokumenter

Uddrag rapporter om bivirkninger
Klassificere patientrapporterede resultater
Prioriter sikkerhedssignaler

Du kan udvide denne implementering ved at:

Tilføjelse af en feedback-loop til forbedring af annotatorer
Implementering af forskellige udvælgelsesstrategier (diversitet, klyngedannelse)
Oprettelse af en webgrænseflade til human-in-the-loop-validering
Aktivering multi-label klassificering for komplekse symptomer

Konklusion

Integrationen af ​​Adala og Google Gemini giver en kraftfuld ramme til opbygning af intelligente annotationspipelines. Ved at udnytte aktive læringsstrategier, kan vi dramatisk reducere den nødvendige manuelle indsats, samtidig med at vi vedligeholder annoteringer af høj kvalitet.

De modulære designmønstre, der er demonstreret i denne vejledning, giver mulighed for nem tilpasning til forskellige domæner og annotationsopgaver.

For dem, der er interesserede i at udforske yderligere, Adala GitHub-arkiv tilbyder yderligere eksempler og dokumentation for at udvide disse koncepter til mere komplekse annotationsscenarier.

Giv en kommentar

Din e-mail adresse vil ikke blive offentliggjort. Krævede felter er markeret *

Dette websted bruger Akismet til at reducere spam. Lær, hvordan dine kommentardata behandles.

Deltag i Aimojo Stamme!

Slut dig til 76,200+ medlemmer for insider-tips hver uge! 
🎁 BONUS: Få vores 200 dollarsAI "Mestringsværktøjskasse" GRATIS ved tilmelding!

trending AI Værktøjer
Superskala AI

Lav enhver URL om til en lanceringsklar annoncekampagne på få minutter AI Annonceagent bygget til performance marketingfolk og vækstfokuserede brands

tl;dv

Stop med at miste det, der blev sagt. Begynd at handle på hvert møde. AI mødenotatskriver, der optager og omdanner samtaler til handlingsrettet output.

AskYura

Forvandl hver kundesamtale til en afsluttet forretningshandling Ingen kode AI Agent bygget til operationel udførelse

Kuberner

Implementer smartere. Skaler hurtigere. Skær ned på cloudomkostninger med op til 40 %. AI-Agentic Cloud PaaS bygget til nul-konfigurations full-stack implementering.

uizard

Forvandl idéer til interaktive prototyper uden en eneste designfærdighed AI UI-designværktøj til wireframes, mockups og app-prototyping

© Ophavsret 2023 - 2026 | Bliv en AI Professionel | Lavet med ♥