Aktiv inlärning för dataannotering: Gemini + Adala-guide

Adala-ramverket – Aktivt lärande för dataannotering

Aktivt lärande förändrar hur vi tränar AI modeller genom att intelligent välja de mest värdefulla uppgifterna för annotering. När de paras ihop med kraftfulla juridikexamina tycka om Google Tvillingarna, skapar det effektiva annoteringspipelines som minskar manuell ansträngning samtidigt som hög datakvalitet bibehålls.

Den här guiden utforskar hur man bygger sådana pipelines med hjälp av Adala-ramverket – ett kraftfullt men underutnyttjat verktyg för autonom datamärkning.

Vi kommer att implementera en medicinsk symptomklassificerare som utnyttjar Gemini's förmågor genom ett strukturerat aktivt lärandearbetsflöde.

Förstå aktiv inlärning för dataannotering

Förstå aktiv inlärning för dataannotering

Aktivt lärande tar itu med den största utmaningen inom övervakat lärande : att erhålla stora mängder märkt data. Istället för att slumpmässigt välja datapunkter för annotering identifierar aktiva inlärningsalgoritmer de mest informativa exemplen som kommer att bidra mest till modellförbättring.

Varför aktivt lärande är viktigt:

Minskar annoteringskostnaderna genom att fokusera mänskliga ansträngningar där det är som viktigast.
Förbättrar modellnoggrannhet med färre märkta exempel.
Åtgärdar klasskillnader genom att prioritera underrepresenterade kategorier.
Skapar en kontinuerlig inlärningsslinga mellan modell och annotator.

Adala-ramverket för in dessa fördelar i produktionsarbetsflöden genom att tillhandahålla modulära komponenter som effektiviserar den aktiva inlärningsprocessen . Innan vi går in på implementeringen, låt oss undersöka vad som gör Adala särskilt lämpat för integration med moderna LLM:er som Google Gemini.

Vad är Adala? En introduktion till ramverket

Adala (Autonomous Data Labeling Agent) är ett ramverk med öppen källkod som är specifikt utformat för att implementera specialiserade agenter för databehandling . Till skillnad från traditionella annoteringsverktyg använder Adala en agentbaserad metod som kombinerar:

Kompetensbaserad arkitekturDefiniera specifika funktioner som din annoteringsagent behöver.
Flexibilitet vid körningVäxla mellan olika LLM:er eller anpassade körtider.
MiljökopplingarInteragera med olika datakällor.
Inbyggda inlärningsslingorUtbilda agenter för att förbättra sig över tid.

Om vi ​​tittar på Adalas snabbstartsexempel kan vi se hur det strukturerar sentimentklassificering :

pytonorm

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)

För vår uppgift att klassificera medicinska symptom kommer vi att anpassa denna arkitektur för att integrera Google Gemini samtidigt som vi implementerar en anpassad aktiv inlärningsstrategi.

Ställa in din miljö

Låt's Börja med att installera Adala och nödvändiga beroenden:

pytonorm

# 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 måste också klona förrådet för direkt åtkomst till dess komponenter:

pytonorm

# 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

Integrera Google Gemini som en anpassad annotator

Till skillnad från den ursprungliga implementeringen som använde en grundläggande omslutning kring Google Gemini, kommer vi att bygga en mer robust annotator som följer Adalas designmönster. Detta gör vår lösning mer lättskött och utökningsbar.

Först måste vi konfigurera Google Generative AI klient:

pytonorm

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 ska vi skapa en anpassad annotator genom att utöka Adala.'s BaseAnnotator-klass:

pytonorm

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

Denna implementering ger betydande förbättringar jämfört med originalet:

  1. Det följer korrekt klassarv från Adala's BaseAnnotator
  2. Implementerar privata hjälpmetoder för snabb byggnation och svarsparsning
  3. Använder strukturerad felhantering och skriv tips
  4. Tillhandahåller fullständig dokumentation

Bygga en pipeline för symptomklassificering

Låt oss skapa en datamängd med medicinska symtom för vår klassificeringsuppgift. Till skillnad från den ursprungliga implementeringen kommer vi att använda en mer diversifierad datamängd med balanserad representation över olika kategorier:

pytonorm

# 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]

Implementera avancerade aktiva inlärningsstrategier

Den ursprungliga implementeringen använde en enkel prioriteringspoängmekanism. Vi kommer att förbättra detta med flera strategier för att demonstrera Adala.'s flexibilitet:

pytonorm

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)

Nu, låt's implementera vår förbättrade aktiva inlärningsslinga:

pytonorm

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öra hela pipelinen

Nu kan vi köra hela vår aktiva inlärningspipeline:

pytonorm

# 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}")

Praktiska tillämpningar och utökningar

Denna pipeline har många praktiska tillämpningar utöver medicinsk symptomklassificering:

1. Moderering av innehåll

Prioritera användarrapporterat innehåll
Fokusera på högriskkategorier
Anpassa konfidensgränser baserat på innehållstyp

2. Analys av kundfeedback

Identifiera brådskande kundfrågor
Registrera nya produktproblem
Skicka feedback till lämpliga team

3. Bearbetning av kliniska prövningsdokument

Utdrag av biverkningsrapporter
klassificera patientrapporterade resultat
Prioritera säkerhetssignaler

Du kan utöka den här implementeringen genom att:

Lägger till en feedback-slinga för förbättring av annotatorer
Implementera olika urvalsstrategier (mångfald, klustring)
Skapa ett webbgränssnitt för validering med mänskliga funktioner
Möjliggör multi-label klassificering för komplexa symtom

Slutsats

Integrationen av Adala och Google Gemini ger ett kraftfullt ramverk för att bygga intelligenta annoteringsrör. Genom att utnyttja aktiva inlärningsstrategier kan vi dramatiskt minska den manuella arbetsinsats som krävs samtidigt som vi bibehåller högkvalitativa annoteringar.

De modulära designmönstren som demonstreras i den här handledningen möjliggör enkel anpassning till olika domäner och annoteringsuppgifter.

För de som är intresserade av att utforska vidare erbjuder Adala GitHub-arkivet ytterligare exempel och dokumentation för att utöka dessa koncept till mer komplexa annoteringsscenarier.

Lämna en kommentar

Din e-postadress kommer inte att publiceras. Obligatoriska fält är markerade med *

Den här webbplatsen använder Akismet för att minska skräppost. Läs mer om hur dina kommentarsdata behandlas.

Gå med i Aimojo Stam!

Gå med i 76,000 XNUMX+ medlemmar för insidertips varje vecka! 
🎁 BONUS: Få våra 200 dollarAI ”Mastery Toolkit” GRATIS när du registrerar dig!

Trend AI Verktyg
Dreamz.ai

Bygg, chatta med och se dina privata AI flickvän, med videomeddelanden inkluderade i varje premiumplan. Ocensurerad 18+ AI sällskapschatt för vuxna som vill ha full kontroll.

Fantasybox

AI Generering av vuxenbilder och videor utan automatiska förnyelser Betala per kredit NSFW-innehåll skapande från textmeddelanden

Humata

Förvandla vilket dokument som helst till omedelbar, handlingsbar information Ocuco-landskapet AI Drivs av PDF- och dokumentanalysassistenten

Iris.ai

AI Kunskapsstiftelse som omvandlar företagsdata till pålitlig, granskbar intelligens Precision AI för reglerad forskning och utveckling samt företagskunskapshantering

Undermind

AI Drivs av litteratursökning som hittar de artiklar som andra missar Forskningsassistenten byggd för forskare, av forskare.

© Upphovsrätt 2023 - 2026 | Bli en AI Proffs | Tillverkad med ♥