import { DlpServiceClient } from '@google-cloud/dlp';
import { Logging } from '@google-cloud/logging';
interface PIIDetectionResult {
private dlpClient: DlpServiceClient;
private logging: Logging;
private readonly PROJECT_ID: string;
private readonly MIN_LIKELIHOOD: number;
constructor(projectId: string, minLikelihood: number = 0.3) {
this.PROJECT_ID = projectId;
this.MIN_LIKELIHOOD = minLikelihood;
this.dlpClient = new DlpServiceClient();
this.logging = new Logging({ projectId });
* Inspects text for PII before sending to LLM
* Returns detection results and optional redacted version
async inspectPrompt(text: string): Promise<PIIDetectionResult> {
const parent = `projects/${this.PROJECT_ID}/locations/global`;
{ name: 'US_SOCIAL_SECURITY_NUMBER' },
{ name: 'EMAIL_ADDRESS' },
{ name: 'PHONE_NUMBER' },
{ name: 'CREDIT_CARD_NUMBER' },
minLikelihood: this.MIN_LIKELIHOOD,
limits: { maxFindingsPerRequest: 10 }
const item = { value: text };
const [response] = await this.dlpClient.inspectContent({
const findings = response.result?.findings || [];
const hasPII = findings.length > 0;
const piiFindings = findings.map(finding => ({
type: finding.infoType?.name || 'UNKNOWN',
value: finding.quote || '',
confidence: finding.likelihood || 0
// Log detection for audit trail
const logEntry = this.logging.log('llm-pii-detection');
text: 'PII detected in LLM prompt',
timestamp: new Date().toISOString()
console.error('PII detection failed:', error);
// Fail-safe: reject if detection fails
* Redacts PII from text using DLP
async redactText(text: string): Promise<string> {
const parent = `projects/${this.PROJECT_ID}/locations/global`;
{ name: 'US_SOCIAL_SECURITY_NUMBER' },
{ name: 'EMAIL_ADDRESS' },
{ name: 'PHONE_NUMBER' },
{ name: 'CREDIT_CARD_NUMBER' }
minLikelihood: this.MIN_LIKELIHOOD
infoTypeTransformations: {
primitiveTransformation: {
const item = { value: text };
const [response] = await this.dlpClient.redactContent({
return response.item?.value || text;
console.error('PII redaction failed:', error);
// Return original text on failure
* Process LLM prompt with PII filtering
* Returns safe prompt and audit info
async processLLMPrompt(prompt: string): Promise<{
audit: PIIDetectionResult;
const detection = await this.inspectPrompt(prompt);
const redacted = await this.redactText(prompt);
audit: { ...detection, redactedText: redacted }
const filter = new LLMPIIFilter('your-project-id');
"My SSN is 123-45-6789 and email is test@example.com",
"Can you help me with my account balance?",
"Call me at 555-0123 or reach out to john.doe@company.com"
for (const prompt of testPrompts) {
console.log(`\nOriginal: ${prompt}`);
const result = await filter.processLLMPrompt(prompt);
console.log(`Safe: ${result.safePrompt}`);
console.log(`PII Found: ${result.audit.hasPII}`);
if (result.audit.findings.length > 0) {
console.log('Findings:', result.audit.findings);
// Run if this file is executed directly
if (require.main === module) {
main().catch(console.error);
export { LLMPIIFilter, PIIDetectionResult };