I've had decent results using a doc2query style approach:
1. Ask an LLM to return a list of questions answered by the document
2. Store the embeddings of the questions along with a document ID
3. On user query, get the embedding of the user query
4. KNN cosine similarity search the user embedding vs. the corpus of question embeddings
5. Return the highest ranked documents
You can tweak this approach depending on your use case, so that in step 1 you generate embeddings that are more similar to the types of things you want returned in step 5. If you want the answer to "What is a cat" to be similar to "What is a dog," you'd prompt/finetune the LLM in step 1 to generate broad questions that would encompass both; if you want them to be very different, you'd do the opposite and avoid generalities.