Component secret management breaks serialization
We currently have components (OpenAI generator, Gemini integration) that accept an API key as an init parameter. However, for good reason, we do not serialize this key to disk when dumping a pipeline.
This is problematic - if the user passes the key via init parameter, serializes the pipeline to disk and reloads it from disk, the component will break during runtime due to the lack of the API key. Some components attempt to read from a hardcoded environment variable if None is passed as the init param (which is also the case during deserialization). This only "works" iff:
- The env var is set.
- The key in the env var is the same as the one that was originally passed as the init parameter.
The second point, in particular, can lead to an insidious situation if the keys are different, i.e., if the env var key is different from the one that was passed to the ctor.
In summary, the current implementation explicitly invites users to use the API in a manner that is guaranteed to break during serde. It also violate the principle of least surprise and leads to hard-to-debug issues or, worse, incurs extra costs for the user.
Potential fixes:
-
Restrict the API to eliminate this class of error altogether, i.e, remove the API key parameter altogether.
This is the most straight-forward, but it makes the API much more restrictive. This would also break existing workflows that rely on different authentication tokens for different instances of the same component in a given pipeline.
-
Change the API key parameter to accept the name of the env var that's to be read.
This would allow for more flexibility that the previously mentioned fix albeit with greater verbosity. However, the currently implemented components are not consistent in how environment variables are handled - some resolve the token explicitly and pass that to the backend, where as others leave that to the backend. In some cases, it's not possible to use the component without specifying one even when the backend doesn't require it.
Preferred solution:
Implement a structured way of handling secrets that lets the framework distinguish between different methods of authentication, supporting current workflows/usecases. C.f https://github.com/deepset-ai/haystack/pull/6748 for a similar approach.
### Tasks
- [ ] https://github.com/deepset-ai/haystack/issues/6851
- [ ] https://github.com/deepset-ai/haystack/issues/6854
- [ ] https://github.com/deepset-ai/haystack/issues/6912
- [ ] https://github.com/deepset-ai/haystack/issues/6905
- [ ] https://github.com/deepset-ai/haystack/issues/6906
- [ ] https://github.com/deepset-ai/haystack/issues/6907
- [ ] https://github.com/deepset-ai/haystack/issues/6908
- [ ] https://github.com/deepset-ai/haystack/issues/6911
- [ ] https://github.com/deepset-ai/haystack/issues/6910
- [ ] https://github.com/deepset-ai/haystack/issues/6909