技能 编程开发 Groq数据安全与合规处理

Groq数据安全与合规处理

v20260423
groq-data-handling
该工具提供了一个高安全性的封装层,用于管理所有流经Groq API的数据。它能自动扫描并脱敏输入提示和模型输出中的个人身份信息(如邮箱、电话、卡号、IP地址)。同时,它还会记录详细的调用审计日志和Token使用量,确保数据处理流程符合隐私和合规要求。
获取技能
228 次下载
概览

Groq Data Handling

Overview

Manage data flowing through Groq's inference API. Covers prompt sanitization before sending to Groq, response filtering after receiving, PII redaction, conversation audit logging, and token usage tracking. Key fact: Groq does not use API data for model training (Groq Privacy Policy).

Groq Data Policy

  • Groq does not train on API request/response data
  • Prompts and completions are processed and discarded
  • Groq may temporarily log requests for abuse prevention
  • For enterprise: contact Groq for DPA and SOC 2 compliance details

Instructions

Step 1: Prompt Sanitization Layer

import Groq from "groq-sdk";

const groq = new Groq();

interface RedactionRule {
  name: string;
  pattern: RegExp;
  replacement: string;
}

const PII_RULES: RedactionRule[] = [
  { name: "email", pattern: /\b[\w.+-]+@[\w-]+\.[\w.]+\b/g, replacement: "[EMAIL]" },
  { name: "phone", pattern: /\b\d{3}[-.]?\d{3}[-.]?\d{4}\b/g, replacement: "[PHONE]" },
  { name: "ssn", pattern: /\b\d{3}-\d{2}-\d{4}\b/g, replacement: "[SSN]" },
  { name: "credit_card", pattern: /\b\d{4}[- ]?\d{4}[- ]?\d{4}[- ]?\d{4}\b/g, replacement: "[CARD]" },
  { name: "ip_address", pattern: /\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b/g, replacement: "[IP]" },
];

function sanitizeText(text: string): { sanitized: string; redactedTypes: string[] } {
  let sanitized = text;
  const redactedTypes: string[] = [];

  for (const rule of PII_RULES) {
    if (rule.pattern.test(sanitized)) {
      redactedTypes.push(rule.name);
      sanitized = sanitized.replace(rule.pattern, rule.replacement);
    }
  }

  return { sanitized, redactedTypes };
}

function sanitizeMessages(messages: any[]): { messages: any[]; hadPII: boolean } {
  let hadPII = false;
  const sanitized = messages.map((m) => {
    if (typeof m.content !== "string") return m;
    const { sanitized: text, redactedTypes } = sanitizeText(m.content);
    if (redactedTypes.length > 0) hadPII = true;
    return { ...m, content: text };
  });

  return { messages: sanitized, hadPII };
}

Step 2: Safe Completion Wrapper

async function safeCompletion(
  messages: any[],
  model = "llama-3.3-70b-versatile",
  options?: { maxTokens?: number }
) {
  // Sanitize input
  const { messages: sanitized, hadPII } = sanitizeMessages(messages);
  if (hadPII) {
    console.warn("[groq-data] PII detected and redacted before sending to Groq API");
  }

  // Call Groq
  const completion = await groq.chat.completions.create({
    model,
    messages: sanitized,
    max_tokens: options?.maxTokens ?? 1024,
  });

  // Filter response
  const responseContent = completion.choices[0].message.content || "";
  const { sanitized: filteredContent, redactedTypes } = sanitizeText(responseContent);

  if (redactedTypes.length > 0) {
    console.warn(`[groq-data] Response contained PII: ${redactedTypes.join(", ")}`);
  }

  return {
    ...completion,
    choices: [{
      ...completion.choices[0],
      message: {
        ...completion.choices[0].message,
        content: filteredContent,
      },
    }],
  };
}

Step 3: Token Usage Tracking

interface UsageRecord {
  timestamp: string;
  model: string;
  promptTokens: number;
  completionTokens: number;
  totalTokens: number;
  estimatedCostUsd: number;
  sessionId?: string;
}

const COST_PER_1M: Record<string, { input: number; output: number }> = {
  "llama-3.1-8b-instant": { input: 0.05, output: 0.08 },
  "llama-3.3-70b-versatile": { input: 0.59, output: 0.79 },
  "llama-3.3-70b-specdec": { input: 0.59, output: 0.99 },
  "meta-llama/llama-4-scout-17b-16e-instruct": { input: 0.11, output: 0.34 },
};

function calculateCost(model: string, usage: any): number {
  const pricing = COST_PER_1M[model] || { input: 0.10, output: 0.10 };
  return (
    (usage.prompt_tokens / 1_000_000) * pricing.input +
    (usage.completion_tokens / 1_000_000) * pricing.output
  );
}

function trackUsage(model: string, usage: any, sessionId?: string): UsageRecord {
  const record: UsageRecord = {
    timestamp: new Date().toISOString(),
    model,
    promptTokens: usage.prompt_tokens,
    completionTokens: usage.completion_tokens,
    totalTokens: usage.total_tokens,
    estimatedCostUsd: calculateCost(model, usage),
    sessionId,
  };

  // Store in your preferred backend
  console.log(JSON.stringify({ type: "groq_usage", ...record }));
  return record;
}

Step 4: Audit-Logged Completion

interface AuditLog {
  timestamp: string;
  sessionId: string;
  model: string;
  promptHash: string;        // Hash of input (not the input itself)
  piiDetected: boolean;
  responseFiltered: boolean;
  usage: UsageRecord;
}

async function auditedCompletion(
  sessionId: string,
  messages: any[],
  model = "llama-3.3-70b-versatile"
): Promise<{ content: string; audit: AuditLog }> {
  const { messages: sanitized, hadPII } = sanitizeMessages(messages);

  const completion = await groq.chat.completions.create({
    model,
    messages: sanitized,
  });

  const responseContent = completion.choices[0].message.content || "";
  const { sanitized: filtered, redactedTypes } = sanitizeText(responseContent);
  const usage = trackUsage(model, completion.usage, sessionId);

  const audit: AuditLog = {
    timestamp: new Date().toISOString(),
    sessionId,
    model,
    promptHash: createHash("sha256")
      .update(sanitized.map((m: any) => m.content).join("|"))
      .digest("hex"),
    piiDetected: hadPII,
    responseFiltered: redactedTypes.length > 0,
    usage,
  };

  // Log audit entry (don't log prompt content, only hash)
  console.log(JSON.stringify({ type: "groq_audit", ...audit }));

  return { content: filtered, audit };
}

Step 5: Content Safety Check

// Use Groq's Llama Guard for content moderation
async function moderateContent(text: string): Promise<{
  safe: boolean;
  categories: string[];
}> {
  const completion = await groq.chat.completions.create({
    model: "meta-llama/llama-guard-4-12b",
    messages: [{ role: "user", content: text }],
    max_tokens: 100,
  });

  const response = completion.choices[0].message.content || "";
  const safe = response.trim().toLowerCase().startsWith("safe");

  return {
    safe,
    categories: safe ? [] : response.split("\n").slice(1).map((l) => l.trim()).filter(Boolean),
  };
}

Step 6: Daily Cost Report

function generateCostReport(records: UsageRecord[]) {
  const totalCost = records.reduce((sum, r) => sum + r.estimatedCostUsd, 0);
  const totalTokens = records.reduce((sum, r) => sum + r.totalTokens, 0);

  const byModel: Record<string, { cost: number; tokens: number; calls: number }> = {};
  for (const r of records) {
    if (!byModel[r.model]) byModel[r.model] = { cost: 0, tokens: 0, calls: 0 };
    byModel[r.model].cost += r.estimatedCostUsd;
    byModel[r.model].tokens += r.totalTokens;
    byModel[r.model].calls++;
  }

  return {
    totalCost: `$${totalCost.toFixed(4)}`,
    totalTokens,
    totalCalls: records.length,
    byModel: Object.fromEntries(
      Object.entries(byModel).map(([model, data]) => [
        model,
        { cost: `$${data.cost.toFixed(4)}`, tokens: data.tokens, calls: data.calls },
      ])
    ),
  };
}

Error Handling

Issue Cause Solution
PII leaks in response Model echoes sensitive input Apply response filtering on all completions
Cost spike 70B model for all requests Route simple tasks to 8B
Missing usage data Streaming mode Use non-streaming for tracked requests, or estimate
Audit gaps Not all code paths use wrapper Lint rule: ban direct groq.chat.completions.create

Resources

Next Steps

For enterprise access controls, see groq-enterprise-rbac.

信息
Category 编程开发
Name groq-data-handling
版本 v20260423
大小 8.32KB
更新时间 2026-04-28
语言