Recently, by directly using functional programming through decorators and OOP in the RAGchain project, I was able to add logic to the countless repetitive code I had written and create more organized code.

However, while excessively believing in OOP and using excessive abstraction, I got a harsh lesson during review for abstracting things that did not really need to be abstracted. So, to what extent can the concept of abstraction be used? The link below explains it veeeery well.
When an exception case is added to abstracted code later, or when additional functionality needs to be implemented and someone else continues writing the code I created, there will be pressure to prevent the original code from being damaged as much as possible. Because of this, it becomes impossible to remove incorrect abstractions, and ultimately, unsatisfactory code is produced. If there is an incorrect abstraction, removing it and returning the code to its original place can make adding new functionality faster and easier.

Abstraction means creating new abstract concepts to reduce duplication in repeatedly used code, condensing repetitive code into modules for reuse.
Nice sites and references to check out