-
Notifications
You must be signed in to change notification settings - Fork 11
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[QUESTION] Why classes use the final modifier #211
Comments
Hey @tryvin, thanks for your feedback and your kind words – we really appreciate it! The reason why we consistently use final is to ensure API stability and to uphold our BC promise. If we make everything extendable, we lose control over how the library is used, and it becomes much harder to guarantee backward compatibility. Moreover, keeping classes final encourages users to share their use cases with us. This way, we can evaluate whether it makes sense to remove the final modifier in specific cases or if the library should be extended with a new feature to accommodate these needs. If you have a concrete proposal for a change that would help your use case, feel free to open an issue or start a discussion – we’re always open to improving the library in a way that benefits the community. |
Hi @tryvin, Thanks for reaching out and bringing your use case! Oskar already summarized it quite well and I just want to add that we want to be quite explicit about extension points - and I know that this is quite defensive. But on the other hand this is exactly the kind of feedback loop and ideas that are coming from that and the library itself can become better through your input. In your example case I would argue that it is totally valid and we should extend the base implementation itself. Maybe all response classes just should have a metadata bag and/or the raw response - so not everything is abstracted away. I think that is basically the same solution that would help with #207. Do you think the idea of PR #175 would help your issue? |
Hey @chr-hertel and @OskarStark thanks for all the responses, maybe we can discuss how to improve things from an external developer perspective? So, lemme explain my use case, which I would say it's pretty "standard" from a "business" perspective. We are building a pretty usual chatbot, the typical you set the personality, you can add XYZ tools to it, and a user can chat with it while we store the conversation so we can rehydrate the But as with every business, you do need to have some things in place
Now, on the
|
Even if i don't really agree on your generalized takes on how a library should be, i still value your input - and like i wrote before - i think you have valid points here when it comes to the data classes in and, about the nature of this project, it's basically a few guys sharing some code with MIT license that we need in our projects - also meaning, you are very much welcome not only to add requirements but also contribute solutions :) and please don't get me wrong, this is an honest invitation since we're def open for your thoughts, use-cases and contributions so let's break it down into action items and potential PRs:
WDYT? |
Sure, that totally works for me, I was about to do a pull request, but I was in a tight time-line and couldn't do the proper thing to this code to only then import it to my project. If I have the time over the weekend I think I can come up with a PR with what you wrapped up in your comment :) Also, I think that specially data classes (things under /Models), and some other across the source code are the most likely to be open and available for inheritance |
Please keep in mind to structure the PRs as reviewable / small as possible 🙋♂️ |
Hey Guys,
I'm trying to use llm-chain in a project here, and one thing I keep hitting is the
final
modifier in classes. Every class here has thefinal
modifier, which makes some things difficult.For example, right now I'm trying to implement provider usage metadata in the
TextResponse
class, so I can store how much this request was charged for, and the same applies to basically all*Response
classes.Usually, I would just make my class return an extended version of the base class, for example, I have a Bedrock ResponseConverter class, so, in my
convert
method, I could just return something likenew TextResponseWithUsageMetadata($choices[0]->getContent(), $usageInfo)
, but unfortunately I can't, as thePhpLlm\LlmChain\Model\Response\TextResponse
is marked withfinal
, so I would need to copy thePhpLlm\LlmChain\Model\Response\TextResponse
code to my ownTextResponseWithUsageMetadata
just to add a single property.The same thing applies to the
ChainProcessor
in theToolBox
, I needed to change just theprocessOutput
method and had to copy the whole class code to add two lines of code to theprocessOutput
method.So, my main question is, do we have a strong reason to keep the
final
modifier in every class? IMHO I seefinal
useful for the "final" user of the code, where you are in total control of your code and you can decide if an XYZ class will remain final or not as the project evolves, but usingfinal
in a library which will be used embedded into other projects make the final user life kinda "difficult", as we have to workaround just to add some small features that our projects might need.Don't get me wrong, I love what you guys are doing here.
The text was updated successfully, but these errors were encountered: