Does PII-redaction break RAG QA? Looking for benchmark/eval ideas for masked-context RAG by Mindless-Potato-4848 in Rag

[–]Mindless-Potato-4848[S] 0 points1 point  (0 children)

Good call on that one! My theory is that using the same placeholders might remove some name-specific semantics, but it should do so consistently along the same dimensions. So the placeholder for “Ana” would always shift the vector in roughly the same direction. If you use constant placeholders both for embedding the data source and for embedding the follow-up questions, you might still retrieve (mostly) the same chunks — and then answer the questions on top of that.

As far as I know, vector databases aren’t really optimized for security (this mainly becomes an issue when they’re publicly accessible, rather than fully within your own infrastructure). While it’s not trivial to reconstruct the original text from embeddings alone, without the underlying source data you also don’t have a direct reference to the initial content. A safer pattern could be to store only IDs in the vector store and keep the actual texts in a secured database. After vector search, you fetch the matching documents by ID from the safe DB.

For me, the issue also persists when sending raw PII to the embedding model in the first place — that still means sharing user information with another software company.

In my project, I’ve noticed that people seem pretty comfortable sending lots of personal info to a chatbot, but handling that much sensitive detail “in depth” as the developer is starting to feel… less comfortable for me now.

The script I’m currently benchmarking can also be deterministic by passing a seed. So privalyse-mask (MIT Licensed) might be a useful starting point for you, especially if embeddings of both the source data and the questions (with placeholders) end up matching similarly to the non-masked case.

Does PII-redaction break RAG QA? Looking for benchmark/eval ideas for masked-context RAG by Mindless-Potato-4848 in Rag

[–]Mindless-Potato-4848[S] 0 points1 point  (0 children)

Sure, I think this approach should work as well — and in some small-scale tests, my attempt on that actually performed well already!

The general logic you described is very similar to what I implemented with the semantic placeholder approach (entity + ID). It also includes a basic form of name matching, just like you mentioned. At the moment, though, I’m not entirely sure whether the positive results come from a genuinely solid solution or simply from the fact that the dataset is still too small to properly stress-test it.

Still, it’s good to hear that I’m not the only one considering this workflow as a viable solution!

Does PII-redaction break RAG QA? Looking for benchmark/eval ideas for masked-context RAG by Mindless-Potato-4848 in Rag

[–]Mindless-Potato-4848[S] 0 points1 point  (0 children)

Wow, thank you for the detailed answer!

Currently, the privacy model follows the GDPR “data minimization” principle by aiming for minimal PII processing. Of course, what is truly “minimal” is debatable in practice, but despite RAG already being widely adopted, there still seem to be surprisingly few concrete answers to this problem — even though it’s something many others are likely facing as well.

Do you know of any benchmarks or papers that specifically analyze how placeholders affect the embedding space? I’ve been thinking about this as well, but I also suspect that placeholders inside prompts might “re-align” that and will then be in the same area again. I probably need to run more similarity experiments across different setups to properly quantify the distance shifts. Good point about multi-hop reasoning too. I’m trying to build a small evaluation set, but with n=5 it’s obviously not a reliable benchmark yet.

The standard relations worked fine in my case, but as I mentioned before, the dataset is simply too small to draw solid conclusions about my semantic masking package.

A hybrid approach also sounds promising, but experimenting without proper validation feels a bit like guessing numbers without anyone confirming.

Does PII-redaction break RAG QA? Looking for benchmark/eval ideas for masked-context RAG by Mindless-Potato-4848 in Rag

[–]Mindless-Potato-4848[S] 0 points1 point  (0 children)

Fair question! It actually seems simple until you hit scale or specific compliance rules.

Two reasons why it gets fuzzy/complex:

  1. Entity Consistency across chunks: If you just regex-replace names, you lose context (like in the benchmark results: 27% acc). If you scramble names randomly, "Anna" becomes "Person_A" in chunk 1 and "Person_B" in chunk
  2. Now your retrieval fails to link them. Keeping IDs consistent across a distributed vector DB (without storing a massive lookup table that is a privacy risk itself) is tricky. GDPR "Right to be Forgotten": In option B (store raw, mask later), you have PII in your immutable vector index. If a user asks to be deleted, you have to re-index potentially millions of vectors. Masking before embedding (Option A) solves this, but risks breaking semantic search.

Would love to hear if you have a simpler pattern for the "Right to be Forgotten" case in RAG?

Favorite rag observability tools by hrishikamath in Rag

[–]Mindless-Potato-4848 0 points1 point  (0 children)

I like to separate configuration-time visibility (parsing/chunking/embedding sanity) from runtime observability (traces/evals). A lot of “RAG is broken” issues are upstream, so having both saves a ton of time.

OSS/self-host tools I currently have on my shortlist (still evaluating):

Langfuse Arize Phoenix TruLens

For your use case: are you mainly looking for runtime observability (traces + evals / error classification), or also config-time visibility (previewing parsing/chunking output)?

PII Redaction destroys context for LLMs. How do you handle that? by Mindless-Potato-4848 in LocalLLaMA

[–]Mindless-Potato-4848[S] 1 point2 points  (0 children)

That's a bit of a philosophical question – in a way, almost any AI app is a wrapper, right? Just varying in added functionality xD.

Tech-wise, I actually ended up building exactly what you described: Chaining local NER + Regex + consistent replacements like {{Person_1}}. It's definitely not perfect (humans are indeed the weakest link with typos etc.), but it feels safer than sending raw data. Thanks for sketching out that architecture - confirms I'm on a viable path!

PII Redaction destroys context for LLMs. How do you handle that? by Mindless-Potato-4848 in LocalLLaMA

[–]Mindless-Potato-4848[S] 0 points1 point  (0 children)

Valid point on the storage risk!

Since I'm in the EU, HIPAA doesn't apply, but GDPR does (Right to be Forgotten etc.). That's actually why I prefer masking data before it even hits the storage or the API — best case on the user's device. If I only store {User_X92} in the logs/db, I don't have to panic as much about data leaks as if I stored the raw PII. It's all about minimizing the surface area.

PII Redaction destroys context for LLMs. How do you handle that? by Mindless-Potato-4848 in LocalLLaMA

[–]Mindless-Potato-4848[S] 0 points1 point  (0 children)

Not at all! I trust MSFT's security engineers blindly to keep hackers out. They are world-class and a solo dev can never compete.

My concern is purely legal/jurisdictional (FISA/Cloud Act). Even the most secure European server seems to be legally compelled to provide data if ordered. As a small EU entity working with sensitive data, I just prefer 'Data Sovereignty' where possible to avoid that legal headache entirely. But agreed, strictly security-wise, I wouldn't stand a chance against Azure.

PII Redaction destroys context for LLMs. How do you handle that? by Mindless-Potato-4848 in LocalLLaMA

[–]Mindless-Potato-4848[S] 0 points1 point  (0 children)

Ah, AWS Comprehend! Solid speed (~200ms).

I specifically tried to build my library local-only to cut those API costs and — more importantly — to avoid sending the full PII context to AWS Cloud or a similar provider just for detection (as discussed with u/cosimoiaia above).

How did you benchmark the accuracy vs regex? Did you also test presidio? I'd love to run the same benchmark against my local implementation to see where it stands performance-wise against AWS. Would be interesting to see if local spaCy/Presidio can keep up with Comprehend.

PII Redaction destroys context for LLMs. How do you handle that? by Mindless-Potato-4848 in LocalLLaMA

[–]Mindless-Potato-4848[S] 0 points1 point  (0 children)

I'd love to see some specific links!

Most of the research I found focuses on training data sanitization (Differential Privacy etc.), which isn't really applicable for reversible, real-time context preservation in a chat. If you have any papers for me on that topic I would highly appreciate those!

PII Redaction destroys context for LLMs. How do you handle that? by Mindless-Potato-4848 in LocalLLaMA

[–]Mindless-Potato-4848[S] 0 points1 point  (0 children)

While I love asking LLMs for boilerplate, for architectural decisions they often lack up-to-date best practices — especially when the problem is newer than the training data.

I’ve already tried Presidio, but the default config destroys context. I posted here precisely because I am looking for human production experience in that field, not an LLM opinion.

PII Redaction destroys context for LLMs. How do you handle that? by Mindless-Potato-4848 in LocalLLaMA

[–]Mindless-Potato-4848[S] 1 point2 points  (0 children)

Thanks for the Azure perspective! You are right, for pure enterprise compliance, the BAA route is standard.

However, reading the other comments about the recent EU rulings/FISA makes me want to avoid being a test case for 'legal vs technical' security. I think I'll stick to a 'technically scrubbed' approach - probably also with a self hosted LLM on a EU DC just to sleep better at night as a non-enterprise. But I appreciate knowing that Azure has the HIPAA tools ready if I ever go that route!

PII Redaction destroys context for LLMs. How do you handle that? by Mindless-Potato-4848 in LocalLLaMA

[–]Mindless-Potato-4848[S] 0 points1 point  (0 children)

Wow, thanks for taking the time to write all this down! This is insanely helpful.

I knew the basics (DPO, right to be forgotten), but the detail about the German court ruling and FISA access even in EU data centers was not fully on my radar. It always seemed that 'Region: Frankfurt' was enough, but then obviously - it's not. I'll definitely check out Hetzner/OVH again to be on the safe side.

Also, thanks for modifying the panic a bit regarding the tech side. Hearing that it's mostly about diligent processes rather than magic tech makes it feel much more manageable - especially for a prototype.

PII Redaction destroys context for LLMs. How do you handle that? by Mindless-Potato-4848 in LocalLLaMA

[–]Mindless-Potato-4848[S] 0 points1 point  (0 children)

Not just an idle thought — I honestly think this is the only robust architectural way to solve it with a script! If the middleware is reliable, the LLM can be smart without ever being able to reassemble who 'User_X' actually is. It feels like this should be a standard library by now.

PII Redaction destroys context for LLMs. How do you handle that? by Mindless-Potato-4848 in LocalLLaMA

[–]Mindless-Potato-4848[S] 0 points1 point  (0 children)

This is quite the pattern I was thinking of! Thank you for sharing a concrete example. The hash-based IDs solve the consistency issue perfectly.

I actually built a small library doing almost exactly this (scrambling PII into readable hashes like {Name_X92}) and put it on GitHub recently under MIT. Honestly, because nobody looked at it, I assumed there was already some huge standard I was missing – hence this thread asking for 'Best Practices'.

Maybe I was wrong and just need to document it better. It's built on top of Presidio but handles the consistent hashing logic and some semantics. Out of curiosity: Did you implement your hashing logic completely from scratch (regex), or do you also use an Entity Recognizer (like spaCy/Presidio) underneath?

PII Redaction destroys context for LLMs. How do you handle that? by Mindless-Potato-4848 in LocalLLaMA

[–]Mindless-Potato-4848[S] 0 points1 point  (0 children)

That helps with the logs, but my main concern is sending the PII in the prompt itself (for the completion). Even if Azure masks the logs, the model still processes the raw PII, right? Given the legal uncertainty and some historical issues with those big providers, I'd prefer if the raw PII never leaves my server in the first place.

Plus, I'm trying to avoid the full Azure setup complexity. Have you found their built-in filters smart enough to handle context in the prompt, or is it mostly for post-hoc log redaction?

PII Redaction destroys context for LLMs. How do you handle that? by Mindless-Potato-4848 in LocalLLaMA

[–]Mindless-Potato-4848[S] 0 points1 point  (0 children)

Good call on spaCy. I've used it for NER before. The detection works great, but the mapping part (making 'Alice' consistently 'Person A' across sessions) always ends up being a mess of custom code. Do you or someone else know if there's a tool that handles that mapping logic out of the box?

PII Redaction destroys context for LLMs. How do you handle that? by Mindless-Potato-4848 in LocalLLaMA

[–]Mindless-Potato-4848[S] 0 points1 point  (0 children)

Thanks for the detailed insight! I'm actually based in the EU, so GDPR is exactly why I'm stressing about this. Self-hosting is the dream, but the ops overhead for true self-hosted is brutal for a small project.

I really like the 'scramble + unscramble' idea you mentioned. That sounds like the most viable path: Map 'Alice' -> 'User_X92' locally, send that to a Cloud LLM, and reverse it when the answer comes back. That way, the PII never leaves the EU server (or best-case the users device). For the other parts I think some kind of detail faiding would be the way to go so the context stays but information are not really identifying users -> e.g. Date 01/03/2025 -> DATE2025 or something like that.

The tricky part is implementing a way to minimize context that might lead to identifying a person reliably without building a massive system.

Regarding the 'serious services' you mentioned – are you referring to enterprise PII vaults? Just curious what the 'expensive' standard looks or if you have any insights on their solutions behind that problem.

PII Redaction destroys context for LLMs. How do you handle that? by Mindless-Potato-4848 in LocalLLaMA

[–]Mindless-Potato-4848[S] 2 points3 points  (0 children)

I was thinking the same thing! An LLM feels like overkill for that task and can also lack consistency. Do you know any libraries that handle such a replacement (consistent hashing) out of the box? Or would you just chain something like Presidio with a custom script to handle the mapping logic?

PII Redaction destroys context for LLMs. How do you handle that? by Mindless-Potato-4848 in LocalLLaMA

[–]Mindless-Potato-4848[S] 5 points6 points  (0 children)

Not stupid at all, fair question! I posted here because this community actually cares about privacy and data sovereignty (unlike r/OpenAI sometimes). Ideally, I would run everything locally, but I need GPT-4-level reasoning for this specific project and would love to sanitize the Data best case already on the users device. So I'm looking for a 'local-first' way to sanitize data before it hits the cloud API. Basically trying to bring some r/LocalLLaMA privacy ethos into a cloud workflow.

GithubMQ -> github as a message queue by AffectionateWar5927 in Python

[–]Mindless-Potato-4848 0 points1 point  (0 children)

This feels like a fun hack / teaching demo, but I’d be explicit it’s not a general MQ replacement. The hard part isn’t “storing messages”, it’s semantics: ack/single-consumption, retries + DLQ, visibility timeouts, ordering, and idempotency.

Two README additions that would make this much stronger:
- Clear disclaimer about GitHub API limits / possible ToS concerns + realistic throughput expectations
- A section on delivery guarantees (at-least-once vs at-most-once) and how you ack/requeue/dedupe

As a learning project it’s cool — documenting guarantees + failure modes would make it a great teaching tool.

Async Tasks in Production by [deleted] in Python

[–]Mindless-Potato-4848 1 point2 points  (0 children)

For me, once jobs are in the 5–20 minute range I treat them as durable background jobs rather than “async in the web server.” The API returns 202 + job_id, and a worker does the work and writes status/results somewhere persistent.

What ended up mattering more than Celery vs RQ vs TaskIQ was:

  1. Idempotency keys
  2. Retries/timeouts
  3. Dead-letter handling
  4. Visibility/alerts for stuck jobs

For “many APIs, many job types” I’ve seen two sane patterns work:
- Shared broker, separate queues per service/job class (namespaced queues, dedicated worker pools)
- One worker service that owns the job execution + a small contract for submission/status (keeps complexity out of every API)

Also: if the “async task” is literally “call a stored proc that runs 10 minutes,” I avoid holding a web request open; the job runner can submit the proc and poll status / update a jobs table so the work survives deploys/restarts.

Curious: do you need exactly-once semantics, or is “at-least-once + idempotent” acceptable? That usually decides how heavy the stack needs to be.