From 7a6b67a053a1837fff0f0f36546b1518c61454a7 Mon Sep 17 00:00:00 2001 From: ModelHub XC Date: Wed, 5 Aug 2026 22:37:23 +0800 Subject: [PATCH] =?UTF-8?q?=E5=88=9D=E5=A7=8B=E5=8C=96=E9=A1=B9=E7=9B=AE?= =?UTF-8?q?=EF=BC=8C=E7=94=B1ModelHub=20XC=E7=A4=BE=E5=8C=BA=E6=8F=90?= =?UTF-8?q?=E4=BE=9B=E6=A8=A1=E5=9E=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Model: MainStack/marvy-1-14B Source: Original Platform --- .gitattributes | 37 ++ CITATION.cff | 28 ++ LICENSE | 202 +++++++++++ LICENSE-CC-BY-4.0 | 396 +++++++++++++++++++++ LICENSING.md | 47 +++ NOTICE | 80 +++++ README.md | 350 ++++++++++++++++++ USAGE.md | 191 ++++++++++ VALIDATION.md | 138 ++++++++ chat_template.jinja | 54 +++ config.json | 30 ++ generation_config.json | 14 + marvy_improvement.png | Bin 0 -> 57570 bytes marvy_vs_base_ppl.png | 3 + model-00001-of-00006.safetensors | 3 + model-00002-of-00006.safetensors | 3 + model-00003-of-00006.safetensors | 3 + model-00004-of-00006.safetensors | 3 + model-00005-of-00006.safetensors | 3 + model-00006-of-00006.safetensors | 3 + model.safetensors.index.json | 587 +++++++++++++++++++++++++++++++ tokenizer.json | 3 + tokenizer_config.json | 31 ++ validate.sh | 61 ++++ 24 files changed, 2270 insertions(+) create mode 100644 .gitattributes create mode 100644 CITATION.cff create mode 100644 LICENSE create mode 100644 LICENSE-CC-BY-4.0 create mode 100644 LICENSING.md create mode 100644 NOTICE create mode 100644 README.md create mode 100644 USAGE.md create mode 100644 VALIDATION.md create mode 100644 chat_template.jinja create mode 100644 config.json create mode 100644 generation_config.json create mode 100644 marvy_improvement.png create mode 100644 marvy_vs_base_ppl.png create mode 100644 model-00001-of-00006.safetensors create mode 100644 model-00002-of-00006.safetensors create mode 100644 model-00003-of-00006.safetensors create mode 100644 model-00004-of-00006.safetensors create mode 100644 model-00005-of-00006.safetensors create mode 100644 model-00006-of-00006.safetensors create mode 100644 model.safetensors.index.json create mode 100644 tokenizer.json create mode 100644 tokenizer_config.json create mode 100644 validate.sh diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..9dc6a48 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,37 @@ +*.7z filter=lfs diff=lfs merge=lfs -text +*.arrow filter=lfs diff=lfs merge=lfs -text +*.bin filter=lfs diff=lfs merge=lfs -text +*.bz2 filter=lfs diff=lfs merge=lfs -text +*.ckpt filter=lfs diff=lfs merge=lfs -text +*.ftz filter=lfs diff=lfs merge=lfs -text +*.gz filter=lfs diff=lfs merge=lfs -text +*.h5 filter=lfs diff=lfs merge=lfs -text +*.joblib filter=lfs diff=lfs merge=lfs -text +*.lfs.* filter=lfs diff=lfs merge=lfs -text +*.mlmodel filter=lfs diff=lfs merge=lfs -text +*.model filter=lfs diff=lfs merge=lfs -text +*.msgpack filter=lfs diff=lfs merge=lfs -text +*.npy filter=lfs diff=lfs merge=lfs -text +*.npz filter=lfs diff=lfs merge=lfs -text +*.onnx filter=lfs diff=lfs merge=lfs -text +*.ot filter=lfs diff=lfs merge=lfs -text +*.parquet filter=lfs diff=lfs merge=lfs -text +*.pb filter=lfs diff=lfs merge=lfs -text +*.pickle filter=lfs diff=lfs merge=lfs -text +*.pkl filter=lfs diff=lfs merge=lfs -text +*.pt filter=lfs diff=lfs merge=lfs -text +*.pth filter=lfs diff=lfs merge=lfs -text +*.rar filter=lfs diff=lfs merge=lfs -text +*.safetensors filter=lfs diff=lfs merge=lfs -text +saved_model/**/* filter=lfs diff=lfs merge=lfs -text +*.tar.* filter=lfs diff=lfs merge=lfs -text +*.tar filter=lfs diff=lfs merge=lfs -text +*.tflite filter=lfs diff=lfs merge=lfs -text +*.tgz filter=lfs diff=lfs merge=lfs -text +*.wasm filter=lfs diff=lfs merge=lfs -text +*.xz filter=lfs diff=lfs merge=lfs -text +*.zip filter=lfs diff=lfs merge=lfs -text +*.zst filter=lfs diff=lfs merge=lfs -text +*tfevents* filter=lfs diff=lfs merge=lfs -text +tokenizer.json filter=lfs diff=lfs merge=lfs -text +marvy_vs_base_ppl.png filter=lfs diff=lfs merge=lfs -text diff --git a/CITATION.cff b/CITATION.cff new file mode 100644 index 0000000..facfdda --- /dev/null +++ b/CITATION.cff @@ -0,0 +1,28 @@ +cff-version: 1.2.0 +message: "If you use marvy-1-14B as a baseline, fine-tune it, distill from it, or evaluate against it, please cite this work and credit MainStack." +title: "marvy-1-14B: An open fine-tuned model for the full ServiceNow delivery lifecycle" +abstract: "marvy-1-14B is an Apache-2.0 fine-tune of Qwen2.5-14B-Instruct specialized for the full ServiceNow delivery lifecycle: business analysis, requirements, stakeholder mapping, systems inventory, solution design documents, user stories, implementation planning, test cases, and validation." +type: software +authors: + - name: "MainStack" + website: "https://www.mainstack.co.uk/" +url: "https://huggingface.co/MainStack/marvy-1-14B" +repository-artifact: "https://huggingface.co/MainStack/marvy-1-14B" +version: "1" +date-released: "2026-06-01" +license: Apache-2.0 +keywords: + - ServiceNow + - ITSM + - CSDM + - solution-design + - delivery + - qwen2.5 + - lora +references: + - type: software + title: "Qwen2.5-14B-Instruct" + authors: + - name: "Qwen Team, Alibaba Cloud" + url: "https://huggingface.co/Qwen/Qwen2.5-14B-Instruct" + license: Apache-2.0 diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..d645695 --- /dev/null +++ b/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/LICENSE-CC-BY-4.0 b/LICENSE-CC-BY-4.0 new file mode 100644 index 0000000..da6ab6c --- /dev/null +++ b/LICENSE-CC-BY-4.0 @@ -0,0 +1,396 @@ +Attribution 4.0 International + +======================================================================= + +Creative Commons Corporation ("Creative Commons") is not a law firm and +does not provide legal services or legal advice. Distribution of +Creative Commons public licenses does not create a lawyer-client or +other relationship. Creative Commons makes its licenses and related +information available on an "as-is" basis. Creative Commons gives no +warranties regarding its licenses, any material licensed under their +terms and conditions, or any related information. Creative Commons +disclaims all liability for damages resulting from their use to the +fullest extent possible. + +Using Creative Commons Public Licenses + +Creative Commons public licenses provide a standard set of terms and +conditions that creators and other rights holders may use to share +original works of authorship and other material subject to copyright +and certain other rights specified in the public license below. The +following considerations are for informational purposes only, are not +exhaustive, and do not form part of our licenses. + + Considerations for licensors: Our public licenses are + intended for use by those authorized to give the public + permission to use material in ways otherwise restricted by + copyright and certain other rights. Our licenses are + irrevocable. Licensors should read and understand the terms + and conditions of the license they choose before applying it. + Licensors should also secure all rights necessary before + applying our licenses so that the public can reuse the + material as expected. Licensors should clearly mark any + material not subject to the license. This includes other CC- + licensed material, or material used under an exception or + limitation to copyright. More considerations for licensors: + wiki.creativecommons.org/Considerations_for_licensors + + Considerations for the public: By using one of our public + licenses, a licensor grants the public permission to use the + licensed material under specified terms and conditions. If + the licensor's permission is not necessary for any reason--for + example, because of any applicable exception or limitation to + copyright--then that use is not regulated by the license. Our + licenses grant only permissions under copyright and certain + other rights that a licensor has authority to grant. Use of + the licensed material may still be restricted for other + reasons, including because others have copyright or other + rights in the material. A licensor may make special requests, + such as asking that all changes be marked or described. + Although not required by our licenses, you are encouraged to + respect those requests where reasonable. More considerations + for the public: + wiki.creativecommons.org/Considerations_for_licensees + +======================================================================= + +Creative Commons Attribution 4.0 International Public License + +By exercising the Licensed Rights (defined below), You accept and agree +to be bound by the terms and conditions of this Creative Commons +Attribution 4.0 International Public License ("Public License"). To the +extent this Public License may be interpreted as a contract, You are +granted the Licensed Rights in consideration of Your acceptance of +these terms and conditions, and the Licensor grants You such rights in +consideration of benefits the Licensor receives from making the +Licensed Material available under these terms and conditions. + + +Section 1 -- Definitions. + + a. Adapted Material means material subject to Copyright and Similar + Rights that is derived from or based upon the Licensed Material + and in which the Licensed Material is translated, altered, + arranged, transformed, or otherwise modified in a manner requiring + permission under the Copyright and Similar Rights held by the + Licensor. For purposes of this Public License, where the Licensed + Material is a musical work, performance, or sound recording, + Adapted Material is always produced where the Licensed Material is + synched in timed relation with a moving image. + + b. Adapter's License means the license You apply to Your Copyright + and Similar Rights in Your contributions to Adapted Material in + accordance with the terms and conditions of this Public License. + + c. Copyright and Similar Rights means copyright and/or similar rights + closely related to copyright including, without limitation, + performance, broadcast, sound recording, and Sui Generis Database + Rights, without regard to how the rights are labeled or + categorized. For purposes of this Public License, the rights + specified in Section 2(b)(1)-(2) are not Copyright and Similar + Rights. + + d. Effective Technological Measures means those measures that, in the + absence of proper authority, may not be circumvented under laws + fulfilling obligations under Article 11 of the WIPO Copyright + Treaty adopted on December 20, 1996, and/or similar international + agreements. + + e. Exceptions and Limitations means fair use, fair dealing, and/or + any other exception or limitation to Copyright and Similar Rights + that applies to Your use of the Licensed Material. + + f. Licensed Material means the artistic or literary work, database, + or other material to which the Licensor applied this Public + License. + + g. Licensed Rights means the rights granted to You subject to the + terms and conditions of this Public License, which are limited to + all Copyright and Similar Rights that apply to Your use of the + Licensed Material and that the Licensor has authority to license. + + h. Licensor means the individual(s) or entity(ies) granting rights + under this Public License. + + i. Share means to provide material to the public by any means or + process that requires permission under the Licensed Rights, such + as reproduction, public display, public performance, distribution, + dissemination, communication, or importation, and to make material + available to the public including in ways that members of the + public may access the material from a place and at a time + individually chosen by them. + + j. Sui Generis Database Rights means rights other than copyright + resulting from Directive 96/9/EC of the European Parliament and of + the Council of 11 March 1996 on the legal protection of databases, + as amended and/or succeeded, as well as other essentially + equivalent rights anywhere in the world. + + k. You means the individual or entity exercising the Licensed Rights + under this Public License. Your has a corresponding meaning. + + +Section 2 -- Scope. + + a. License grant. + + 1. Subject to the terms and conditions of this Public License, + the Licensor hereby grants You a worldwide, royalty-free, + non-sublicensable, non-exclusive, irrevocable license to + exercise the Licensed Rights in the Licensed Material to: + + a. reproduce and Share the Licensed Material, in whole or + in part; and + + b. produce, reproduce, and Share Adapted Material. + + 2. Exceptions and Limitations. For the avoidance of doubt, where + Exceptions and Limitations apply to Your use, this Public + License does not apply, and You do not need to comply with + its terms and conditions. + + 3. Term. The term of this Public License is specified in Section + 6(a). + + 4. Media and formats; technical modifications allowed. The + Licensor authorizes You to exercise the Licensed Rights in + all media and formats whether now known or hereafter created, + and to make technical modifications necessary to do so. The + Licensor waives and/or agrees not to assert any right or + authority to forbid You from making technical modifications + necessary to exercise the Licensed Rights, including + technical modifications necessary to circumvent Effective + Technological Measures. For purposes of this Public License, + simply making modifications authorized by this Section 2(a) + (4) never produces Adapted Material. + + 5. Downstream recipients. + + a. Offer from the Licensor -- Licensed Material. Every + recipient of the Licensed Material automatically + receives an offer from the Licensor to exercise the + Licensed Rights under the terms and conditions of this + Public License. + + b. No downstream restrictions. You may not offer or impose + any additional or different terms or conditions on, or + apply any Effective Technological Measures to, the + Licensed Material if doing so restricts exercise of the + Licensed Rights by any recipient of the Licensed + Material. + + 6. No endorsement. Nothing in this Public License constitutes or + may be construed as permission to assert or imply that You + are, or that Your use of the Licensed Material is, connected + with, or sponsored, endorsed, or granted official status by, + the Licensor or others designated to receive attribution as + provided in Section 3(a)(1)(A)(i). + + b. Other rights. + + 1. Moral rights, such as the right of integrity, are not + licensed under this Public License, nor are publicity, + privacy, and/or other similar personality rights; however, to + the extent possible, the Licensor waives and/or agrees not to + assert any such rights held by the Licensor to the limited + extent necessary to allow You to exercise the Licensed + Rights, but not otherwise. + + 2. Patent and trademark rights are not licensed under this + Public License. + + 3. To the extent possible, the Licensor waives any right to + collect royalties from You for the exercise of the Licensed + Rights, whether directly or through a collecting society + under any voluntary or waivable statutory or compulsory + licensing scheme. In all other cases the Licensor expressly + reserves any right to collect such royalties. + + +Section 3 -- License Conditions. + +Your exercise of the Licensed Rights is expressly made subject to the +following conditions. + + a. Attribution. + + 1. If You Share the Licensed Material (including in modified + form), You must: + + a. retain the following if it is supplied by the Licensor + with the Licensed Material: + + i. identification of the creator(s) of the Licensed + Material and any others designated to receive + attribution, in any reasonable manner requested by + the Licensor (including by pseudonym if + designated); + + ii. a copyright notice; + + iii. a notice that refers to this Public License; + + iv. a notice that refers to the disclaimer of + warranties; + + v. a URI or hyperlink to the Licensed Material to the + extent reasonably practicable; + + b. indicate if You modified the Licensed Material and + retain an indication of any previous modifications; and + + c. indicate the Licensed Material is licensed under this + Public License, and include the text of, or the URI or + hyperlink to, this Public License. + + 2. You may satisfy the conditions in Section 3(a)(1) in any + reasonable manner based on the medium, means, and context in + which You Share the Licensed Material. For example, it may be + reasonable to satisfy the conditions by providing a URI or + hyperlink to a resource that includes the required + information. + + 3. If requested by the Licensor, You must remove any of the + information required by Section 3(a)(1)(A) to the extent + reasonably practicable. + + 4. If You Share Adapted Material You produce, the Adapter's + License You apply must not prevent recipients of the Adapted + Material from complying with this Public License. + + +Section 4 -- Sui Generis Database Rights. + +Where the Licensed Rights include Sui Generis Database Rights that +apply to Your use of the Licensed Material: + + a. for the avoidance of doubt, Section 2(a)(1) grants You the right + to extract, reuse, reproduce, and Share all or a substantial + portion of the contents of the database; + + b. if You include all or a substantial portion of the database + contents in a database in which You have Sui Generis Database + Rights, then the database in which You have Sui Generis Database + Rights (but not its individual contents) is Adapted Material; and + + c. You must comply with the conditions in Section 3(a) if You Share + all or a substantial portion of the contents of the database. + +For the avoidance of doubt, this Section 4 supplements and does not +replace Your obligations under this Public License where the Licensed +Rights include other Copyright and Similar Rights. + + +Section 5 -- Disclaimer of Warranties and Limitation of Liability. + + a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE + EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS + AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF + ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS, + IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION, + WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR + PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS, + ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT + KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT + ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU. + + b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE + TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION, + NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT, + INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES, + COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR + USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN + ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR + DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR + IN PART, THIS LIMITATION MAY NOT APPLY TO YOU. + + c. The disclaimer of warranties and limitation of liability provided + above shall be interpreted in a manner that, to the extent + possible, most closely approximates an absolute disclaimer and + waiver of all liability. + + +Section 6 -- Term and Termination. + + a. This Public License applies for the term of the Copyright and + Similar Rights licensed here. However, if You fail to comply with + this Public License, then Your rights under this Public License + terminate automatically. + + b. Where Your right to use the Licensed Material has terminated under + Section 6(a), it reinstates: + + 1. automatically as of the date the violation is cured, provided + it is cured within 30 days of Your discovery of the + violation; or + + 2. upon express reinstatement by the Licensor. + + For the avoidance of doubt, this Section 6(b) does not affect any + right the Licensor may have to seek remedies for Your violations + of this Public License. + + c. For the avoidance of doubt, the Licensor may also offer the + Licensed Material under separate terms or conditions or stop + distributing the Licensed Material at any time; however, doing so + will not terminate this Public License. + + d. Sections 1, 5, 6, 7, and 8 survive termination of this Public + License. + + +Section 7 -- Other Terms and Conditions. + + a. The Licensor shall not be bound by any additional or different + terms or conditions communicated by You unless expressly agreed. + + b. Any arrangements, understandings, or agreements regarding the + Licensed Material not stated herein are separate from and + independent of the terms and conditions of this Public License. + + +Section 8 -- Interpretation. + + a. For the avoidance of doubt, this Public License does not, and + shall not be interpreted to, reduce, limit, restrict, or impose + conditions on any use of the Licensed Material that could lawfully + be made without permission under this Public License. + + b. To the extent possible, if any provision of this Public License is + deemed unenforceable, it shall be automatically reformed to the + minimum extent necessary to make it enforceable. If the provision + cannot be reformed, it shall be severed from this Public License + without affecting the enforceability of the remaining terms and + conditions. + + c. No term or condition of this Public License will be waived and no + failure to comply consented to unless expressly agreed to by the + Licensor. + + d. Nothing in this Public License constitutes or may be interpreted + as a limitation upon, or waiver of, any privileges and immunities + that apply to the Licensor or You, including from the legal + processes of any jurisdiction or authority. + + +======================================================================= + +Creative Commons is not a party to its public +licenses. Notwithstanding, Creative Commons may elect to apply one of +its public licenses to material it publishes and in those instances +will be considered the “Licensor.” The text of the Creative Commons +public licenses is dedicated to the public domain under the CC0 Public +Domain Dedication. Except for the limited purpose of indicating that +material is shared under a Creative Commons public license or as +otherwise permitted by the Creative Commons policies published at +creativecommons.org/policies, Creative Commons does not authorize the +use of the trademark "Creative Commons" or any other trademark or logo +of Creative Commons without its prior written consent including, +without limitation, in connection with any unauthorized modifications +to any of its public licenses or any other arrangements, +understandings, or agreements concerning use of licensed material. For +the avoidance of doubt, this paragraph does not form part of the +public licenses. + +Creative Commons may be contacted at creativecommons.org. + diff --git a/LICENSING.md b/LICENSING.md new file mode 100644 index 0000000..69fbc5a --- /dev/null +++ b/LICENSING.md @@ -0,0 +1,47 @@ +# Licensing — marvy-1-14B + +marvy-1-14B uses a **layered (dual) license** that reflects what is built on top +of an upstream open model versus what MainStack authored. + +| Component | License | What it covers | +|---|---|---| +| **Model weights** (`*.safetensors`, GGUF quants, LoRA adapter) | **Apache-2.0** | The fine-tuned weights. These are a derivative of Qwen2.5-14B-Instruct (Apache-2.0); per that license they remain Apache-2.0 and free to use, modify, and redistribute. | +| **MainStack original contributions** | **CC-BY-4.0** | The model cards, documentation (`USAGE.md`, `VALIDATION.md`, benchmark), the benchmark charts, the curated training-data methodology, and the pipeline framing authored by MainStack. | + +## What this means in practice + +### You may (under Apache-2.0, for the weights) +- Use marvy-1-14B commercially, privately, or in research. +- Fine-tune, distill, quantize, merge, or otherwise build on the weights. +- Redistribute the weights, including modified versions. + +…provided you **retain the `NOTICE` file** in derivatives and redistributions +(Apache-2.0 §4(d) — this is mandatory and carries the attribution request). + +### You must (under CC-BY-4.0, for our contributions) +If you reuse MainStack's **documentation, model cards, benchmark, or charts** — +e.g. copying our eval methodology, reproducing our charts, or lifting card text +into your own model — you must give **attribution**: credit "MainStack" and link +to https://huggingface.co/MainStack/marvy-1-14B. This is a binding condition of +CC-BY-4.0, not just a request. + +### We ask (attribution for the model) +If you use marvy-1-14B **as a baseline, a starting point for your own fine-tune, +a distillation source, or an evaluation comparison**, please credit MainStack +and cite the entry in the model card. See `NOTICE` and the card's Citation +section. + +## Why the weights can't be more restricted + +Qwen2.5-14B-Instruct is released under Apache-2.0, which grants every recipient +an irrevocable, royalty-free right to use and redistribute. A fine-tune cannot +revoke those rights on the resulting weights. MainStack's protection therefore +lives where it legally can: (1) the CC-BY-4.0 license on our **own** authored +materials, and (2) the Apache-2.0 **NOTICE** that must travel with the weights. + +## Files +- `LICENSE` — Apache-2.0 (governs the weights; inherited from the base model). +- `LICENSE-CC-BY-4.0` — CC-BY-4.0 (governs MainStack's documentation and other + original contributions). +- `NOTICE` — required attribution notices (retain in derivatives). +- `CITATION.cff` — citation metadata. diff --git a/NOTICE b/NOTICE new file mode 100644 index 0000000..a704580 --- /dev/null +++ b/NOTICE @@ -0,0 +1,80 @@ +marvy-1-14B +Copyright 2026 MainStack + +This product is licensed under the Apache License, Version 2.0 (the "License"). +You may obtain a copy of the License in the accompanying LICENSE file or at: + + http://www.apache.org/licenses/LICENSE-2.0 + +================================================================================ +Attribution request (downstream use) +================================================================================ + +marvy-1-14B was created by MainStack (https://huggingface.co/MainStack). + +If you use marvy-1-14B as a baseline, fine-tune it, distill from it, evaluate +against it, or otherwise build on it, please credit MainStack and link to: + + https://huggingface.co/MainStack/marvy-1-14B + +Under the Apache License, Version 2.0, this NOTICE file MUST be retained and +reproduced in any derivative works and redistributions (License §4(d)). + +================================================================================ +Dual licensing +================================================================================ + + * Model weights (safetensors / GGUF / LoRA adapter): Apache-2.0 (LICENSE). + * MainStack original contributions — model cards, documentation, benchmark, + charts, and curated training methodology: CC-BY-4.0 (LICENSE-CC-BY-4.0). + +Reuse of MainStack's contributions requires attribution to MainStack under the +terms of CC-BY-4.0. See LICENSING.md for the full breakdown. + +================================================================================ +Attribution +================================================================================ + +marvy-1-14B is a fine-tuned derivative of: + + Qwen2.5-14B-Instruct + Copyright Alibaba Cloud / Qwen Team + Licensed under the Apache License, Version 2.0 + https://huggingface.co/Qwen/Qwen2.5-14B-Instruct + +The base model weights are the property of their respective authors and are +used and redistributed in modified (fine-tuned) form under the terms of the +Apache License, Version 2.0. + +Citation for the base model: + + @misc{qwen2.5, + title = {Qwen2.5: A Party of Foundation Models}, + author = {Qwen Team}, + year = {2024}, + url = {https://qwenlm.github.io/blog/qwen2.5/} + } + + @article{qwen2, + title = {Qwen2 Technical Report}, + author = {Qwen Team}, + journal= {arXiv preprint arXiv:2407.10671}, + year = {2024} + } + +================================================================================ +Tooling +================================================================================ + +Trained and fused with MLX-LM (https://github.com/ml-explore/mlx-lm), +Copyright Apple Inc., licensed under the MIT License. + +================================================================================ +Training data provenance +================================================================================ + +marvy-1-14B was fine-tuned on a corpus of anonymized ServiceNow delivery +artifacts. All customer and partner names were replaced with stable aliases, +and emails, hostnames, IP addresses, and credential-bearing files were removed +or redacted prior to training. No customer-identifying information is present +in the training corpus. See the model card for the full redaction methodology. diff --git a/README.md b/README.md new file mode 100644 index 0000000..31c6edf --- /dev/null +++ b/README.md @@ -0,0 +1,350 @@ +--- +license: apache-2.0 +base_model: Qwen/Qwen2.5-14B-Instruct +base_model_relation: finetune +library_name: transformers +pipeline_tag: text-generation +language: + - en +tags: + - servicenow + - itsm + - csdm + - itom + - delivery + - solution-design + - user-stories + - business-analysis + - qwen2.5 + - lora + - sft + - mlx +model-index: + - name: marvy-1-14B + results: + - task: + type: text-generation + name: Text Generation + dataset: + type: custom + name: ServiceNow Delivery SFT (project-disjoint test split) + metrics: + - type: perplexity + value: 13.107 + name: Test perplexity + - type: loss + value: 2.573 + name: Test cross-entropy loss +--- + +# marvy-1-14B + +**The first open, fine-tuned LLM for the full ServiceNow delivery lifecycle — from business analysis to validation.** + +marvy-1-14B is an open-source language model fine-tuned for the complete ServiceNow delivery lifecycle: business analysis, requirements, stakeholder mapping, systems inventory, Solution Design Documents, user stories with acceptance criteria, implementation planning, test cases, and validation. Where general-purpose models treat ServiceNow as one topic among many, marvy is built to draft the actual artifacts a delivery team produces — in the structure and sequence real engagements follow. It is a first-draft specialist, not a consultant replacement, and it is not an agentic or tool-use fine-tune. + +It was built by [MainStack](https://huggingface.co/MainStack), a consultancy specializing in ServiceNow Agentic Delivery. marvy is a LoRA SFT fine-tune of [Qwen2.5-14B-Instruct](https://huggingface.co/Qwen/Qwen2.5-14B-Instruct) (Apache-2.0), trained on ~1,958 anonymized artifacts from real engagements (~887k tokens), rigorously redacted to zero residual PII per an automated leakage scanner. Its test perplexity of 13.107 was measured on a project- and customer-disjoint held-out split — the model generalizes to unseen work rather than memorizing the training set. + +> Released under **Apache-2.0**. Built with Qwen — see `NOTICE`. + +## Why marvy-1-14B + +- **Drafts the full lifecycle, not just snippets.** Business analysis through validation — the artifacts and sequence real delivery teams actually work in. +- **OOTB-first and implementation-grade.** Tuned to favor out-of-the-box correctness and produce drafts you can review, not rewrite. +- **Runs locally and privately.** Merged FP16, a LoRA adapter, and GGUF quants — run it on Apple Silicon via LM Studio or Ollama, with your engagement data never leaving your machine. +- **Trained on real, anonymized delivery work.** ~1,958 redacted engagement artifacts (~887k tokens), with zero residual PII verified by an automated leakage scanner. +- **Open and Apache-2.0.** Built on Qwen2.5-14B-Instruct — inspect it, fine-tune it, and deploy it on your own terms. + +📖 **Full docs:** [`USAGE.md`](./USAGE.md) (every runtime + OpenCode wiring) · +[`VALIDATION.md`](./VALIDATION.md) (prove the fine-tune works) · +[`validate.sh`](./validate.sh) (one-command probe harness) + +--- + +## Quick start + +### Transformers + +```python +from transformers import AutoTokenizer, AutoModelForCausalLM + +model_id = "MainStack/marvy-1-14B" +tok = AutoTokenizer.from_pretrained(model_id) +model = AutoModelForCausalLM.from_pretrained(model_id, torch_dtype="auto", device_map="auto") + +SYSTEM = ( + "You are a senior ServiceNow delivery consultant. You produce precise, " + "implementation-grade artifacts: business analyses, requirements, solution " + "design documents, user stories with acceptance criteria, test cases, and " + "validation reviews. You favor out-of-the-box capabilities, cite concrete " + "tables/plugins/sys_ids when relevant, and write in clear professional English." +) + +messages = [ + {"role": "system", "content": SYSTEM}, + {"role": "user", "content": "Write a ServiceNow user story with acceptance criteria for SLA escalation on P1 incidents."}, +] +inputs = tok.apply_chat_template(messages, add_generation_prompt=True, return_tensors="pt").to(model.device) +out = model.generate(inputs, max_new_tokens=1024, temperature=0.4) +print(tok.decode(out[0][inputs.shape[-1]:], skip_special_tokens=True)) +``` + +### vLLM + +```bash +pip install vllm +vllm serve MainStack/marvy-1-14B +``` + +### Ollama (via GGUF) + +Use the companion repo [`MainStack/marvy-1-14B-GGUF`](https://huggingface.co/MainStack/marvy-1-14B-GGUF): + +```bash +ollama run hf.co/MainStack/marvy-1-14B-GGUF:Q4_K_M +``` + +### MLX (Apple Silicon native) + +```bash +pip install mlx-lm +python -m mlx_lm generate --model MainStack/marvy-1-14B \ + --system-prompt "You are a senior ServiceNow delivery consultant..." \ + --prompt "Draft the Platform Architecture section of an ITSM SDD." \ + --max-tokens 1024 --temp 0.4 +``` + +### LoRA-only (apply on top of the base) + +If you prefer a tiny adapter (~175 MB) on top of the BF16 base, see [`MainStack/marvy-1-14B-lora`](https://huggingface.co/MainStack/marvy-1-14B-lora). + +--- + +## Intended use + +marvy-1-14B is designed to produce implementation-grade first drafts across the ServiceNow delivery lifecycle — accelerating the artifacts a practitioner would otherwise write from scratch, then review and refine. Built for solution architects, business analysts, technical consultants, and project managers. Typical tasks: + +| Task family | What it produces | +|------------------------|---------------------------------------------------------------------------------| +| `business_analysis` | Structured BA reports from SOWs / discovery notes | +| `requirements_extraction` | Functional/non-functional requirements with acceptance bullets | +| `stakeholder_mapping` | RACI / influence-interest grids from raw notes | +| `systems_inventory` | CMDB-shaped systems inventories from architecture inputs | +| `sdd_design` | Solution Design Document sections (architecture, integrations, data model) | +| `story_authoring` | User stories with crisp acceptance criteria | +| `implementation_planning` | Story-level implementation plans citing tables/plugins | +| `test_case_generation` | Test cases per story, mapped to acceptance criteria | +| `validation_critique` | Gap analysis, follow-up questions, assumption checks against source docs | +| `delivery_chain` | Multi-turn: story → implementation → test, end-to-end | + +### Recommended system prompt + +``` +You are a senior ServiceNow delivery consultant. You produce precise, implementation-grade +artifacts: business analyses, requirements, solution design documents, user stories with +acceptance criteria, test cases, and validation reviews. You favor out-of-the-box +capabilities, cite concrete tables/plugins/sys_ids when relevant, and write in clear +professional English. +``` + +### Recommended generation settings + +| Use case | temperature | top_p | max_new_tokens | +|-----------------------------|-------------|-------|----------------| +| Structured artifacts (SDD, stories) | 0.3 – 0.5 | 0.9 | 1024 – 4096 | +| Exploratory brainstorming | 0.7 – 0.9 | 0.95 | 1024 | +| Validation / critique | 0.2 – 0.4 | 0.9 | 1024 – 2048 | + +--- + +## Training data + +> **The training dataset is proprietary to MainStack and is not publicly +> released.** It is derived from confidential, anonymized client engagement +> artifacts. The statistics below describe the corpus for transparency; the data +> itself is not distributed with the model. + +| Item | Value | +|---|---| +| Source | Anonymized real engagement artifacts (`.md`, `.csv`, `.json`, `.mmd`, `.txt`) | +| Availability | **Proprietary — not released** | +| Total records | **1,958** (after schema + exact-dedupe) | +| Estimated tokens | **~887k** | +| Splits (project-disjoint) | train 1,359 · val 347 · test 252 | +| Tasks | 11 task families (see table above) | +| Multi-turn share | `delivery_chain` (158 records) — story→implementation→test | + +### Privacy & redaction + +- All customer/partner names → stable aliases (e.g. `Customer-FIN-03`, `Customer-ENERGY-01`). +- Emails → `user@example.com`; hostnames → `instance.example.service-now.com`; IPs → RFC 5737 range; `key: value` secrets → `[REDACTED]`. +- Credential/login/VPN files excluded entirely; bulk CMDB dumps >1.5 MB excluded. +- ServiceNow `sys_id`s and table/plugin names preserved (instance-local, technically valuable, low risk). +- A leakage scanner asserts **0** residual emails, hostnames, or mapped real names in message content. + +### Split integrity + +Train / val / test are split **by project**, so no customer appears in more than one split. The largest project is forced into `train` to keep eval honest: +- val projects: `Customer-ENERGY-01` +- test projects: `Customer-CHEM-01`, `Customer-FININST-01` + +--- + +## Training procedure + +| Setting | Value | +|---|---| +| Method | LoRA SFT (QLoRA-style: LoRA on 4-bit base) | +| Base model | `mlx-community/Qwen2.5-14B-Instruct-4bit` (training) → fused onto `Qwen/Qwen2.5-14B-Instruct` BF16 (release) | +| Framework | [MLX-LM](https://github.com/ml-explore/mlx-lm) 0.31.3 | +| Hardware | Apple Silicon (M-series), Metal | +| Max sequence length | 8,192 | +| Batch size / grad accum | 1 / 16 (effective batch 16) | +| Iterations | 350 (~4 epochs over 1,359 train records) | +| Optimizer | AdamW, cosine decay, warmup 20, lr 1e-4 → 1e-6 | +| LoRA rank / scale / dropout | 32 / 20.0 / 0.0 | +| LoRA target keys | `q_proj`, `k_proj`, `v_proj`, `o_proj`, `gate_proj`, `up_proj`, `down_proj` | +| Adapted layers | top 16 transformer layers | +| Prompt masking | yes — loss computed only on assistant turns | +| Seed | 42 | + +--- + +## Evaluation + +### Fine-tuned vs. base — efficiency on the held-out test set + +The cleanest measure of the fine-tune's value is to score the **same base +model twice** — plain vs. with the marvy adapter — on the **project-disjoint** +test split (252 records from two customers never seen in training/val), using +per-token cross-entropy/perplexity on the **assistant tokens only** +(prompt-masked, the same objective used in training). Lower perplexity = the +model assigns higher probability to the real, human-authored delivery artifact. + +![marvy-1-14B vs base — perplexity by task](./marvy_vs_base_ppl.png) + +![How much fine-tuning improved each task](./marvy_improvement.png) + +**Overall: perplexity 8.91 → 6.03, a 32.3% reduction** on unseen customers. + +| Task | Base ppl | marvy-1-14B ppl | Improvement | +|---|---:|---:|---:| +| Systems inventory | 77.07 | 10.53 | **−86.3%** | +| Requirements extraction | 46.76 | 9.39 | **−79.9%** | +| Stakeholder mapping | 27.81 | 6.91 | **−75.2%** | +| Story authoring | 15.38 | 7.86 | **−48.9%** | +| Validation / critique | 9.72 | 8.23 | −15.3% | +| Business analysis | 7.14 | 6.66 | −6.6% | +| SDD design | 4.48 | 4.40 | −1.7% | +| **Overall** | **8.91** | **6.03** | **−32.3%** | + +The gains are largest on **structured, format-heavy artifacts** (inventories, +requirements, stakeholder registers, stories) where the base model wanders from +the expected schema; they are smaller on long-form prose (SDD sections, business +analysis) where the base was already competent. This is the honest, expected +shape of a domain SFT. + +> Notes: the test customers (`Customer-CHEM-01`, `Customer-FININST-01`) appear in +> neither train nor val, so this reflects generalization, not memorization. The +> test split happens to cover 7 of the 11 task families. An earlier MLX +> batch-eval reported aggregate ppl ≈ 13.1 with 2,048-token truncation; the +> figures above recompute per-task with full assistant-token masking, so the +> base-vs-marvy **delta** is the result of interest. + +Reproduce it yourself: `bash benchmark/run_benchmark.sh` (see +[`VALIDATION.md`](./VALIDATION.md) for qualitative probes too). + +--- + +## Limitations & known issues + +- **Text-only sources.** SOWs/SDDs/workbooks in `.docx/.pptx/.pdf/.xlsx` are not parsed in this build. Coverage of binary-only engagements is therefore thin. +- **Project concentration.** ~95% of records come from ~12 data-rich projects; the long tail contributes a single case study each. Some task families (e.g. `case_study`, `validation_critique`) are smaller and may exhibit higher variance. +- **Synthetic instructions.** User prompts are templated paraphrases (3–5 variants per task); assistant outputs are the original human-authored artifacts. +- **English-only.** The corpus is English. +- **Not a replacement for a consultant.** Output is first-draft, implementation-grade content that requires expert review before client delivery or production use. +- **No tool use / function calling fine-tune.** `marvy-1-14B` is a text-completion specialist; agentic tool use is left to the orchestrator. +- **Hallucination risk on instance-specific facts.** The model will confidently invent `sys_id`s, plugin IDs, and table fields if asked about specifics it has not seen. Always verify against an actual ServiceNow instance. +- **No safety fine-tune beyond the base.** Inherits Qwen2.5-14B-Instruct safety behavior; no additional RLHF. + +--- + +## License + +marvy-1-14B is **dual-licensed** — see [`LICENSING.md`](./LICENSING.md) for the full breakdown: + +| Component | License | +|---|---| +| **Model weights** (safetensors / GGUF / LoRA) | **Apache-2.0** (`LICENSE`) — inherited from the Qwen2.5-14B-Instruct base; free to use, fine-tune, and redistribute, with `NOTICE` retained. | +| **MainStack contributions** (model cards, docs, benchmark, charts, training methodology) | **CC-BY-4.0** (`LICENSE-CC-BY-4.0`) — reuse requires attribution to MainStack. | + +The model weights are a derivative of **Qwen2.5-14B-Instruct** (Apache-2.0). +Per Apache-2.0, the weights cannot be placed under a more restrictive license; +MainStack's protection is the CC-BY-4.0 license on our own authored materials +plus the mandatory `NOTICE` retention. See `NOTICE` for attribution. + +## Attribution + +`marvy-1-14B` is free to use, fine-tune, and redistribute under Apache-2.0. +**If you use marvy-1-14B as a baseline, fine-tune it, distill from it, evaluate +against it, or otherwise build on it, please credit MainStack** and link back to +this model: + +> Built on / evaluated against **marvy-1-14B** by **MainStack** — +> https://huggingface.co/MainStack/marvy-1-14B + +Concretely, we ask that derivatives and comparisons: + +- keep the `NOTICE` file intact (this is **required** by Apache-2.0 §4), +- name `MainStack/marvy-1-14B` in the model card, paper, or README, and +- cite the entry below. + +Per Apache-2.0, you must also continue to attribute the upstream base model +(Qwen2.5-14B-Instruct) — see `NOTICE`. + +## Citation + +If you use marvy-1-14B (as a baseline, a starting point, or in evaluation), +please cite: + +```bibtex +@software{marvy_1_14b_2026, + title = {marvy-1-14B: An open fine-tuned model for the full ServiceNow delivery lifecycle}, + author = {MainStack}, + year = {2026}, + publisher = {Hugging Face}, + url = {https://huggingface.co/MainStack/marvy-1-14B}, + note = {Fine-tune of Qwen2.5-14B-Instruct}, + license = {Apache-2.0} +} + +@misc{qwen2.5, + title = {Qwen2.5: A Party of Foundation Models}, + author = {Qwen Team}, + year = {2024}, + url = {https://qwenlm.github.io/blog/qwen2.5/} +} +``` + +```bibtex +@software{marvy_14b_2026, + title = {marvy-1-14B: A ServiceNow delivery lifecycle fine-tune of Qwen2.5-14B-Instruct}, + author = {MainStack}, + year = {2026}, + url = {https://huggingface.co/MainStack/marvy-1-14B}, + license= {Apache-2.0} +} + +@misc{qwen2.5, + title = {Qwen2.5: A Party of Foundation Models}, + author = {Qwen Team}, + year = {2024}, + url = {https://qwenlm.github.io/blog/qwen2.5/} +} +``` + +## Acknowledgements + +- **Qwen team** at Alibaba Cloud for the Qwen2.5 family. +- **Apple MLX team** for `mlx` and `mlx-lm`, enabling native Apple Silicon training. +- **Hugging Face** for hosting and the surrounding ecosystem. diff --git a/USAGE.md b/USAGE.md new file mode 100644 index 0000000..44dcd1f --- /dev/null +++ b/USAGE.md @@ -0,0 +1,191 @@ +# Using marvy-1-14B + +marvy-1-14B is a ServiceNow delivery specialist. This guide covers every common +way to run it — cloud or fully local — plus how to wire it into OpenCode. + +- [Choosing a format](#choosing-a-format) +- [Recommended system prompt & settings](#recommended-system-prompt--settings) +- [Transformers (PyTorch)](#transformers-pytorch) +- [vLLM (OpenAI-compatible server)](#vllm-openai-compatible-server) +- [MLX (Apple Silicon, native)](#mlx-apple-silicon-native) +- [LM Studio (GUI + local server)](#lm-studio-gui--local-server) +- [Ollama / llama.cpp (GGUF)](#ollama--llamacpp-gguf) +- [LoRA adapter (apply on the base)](#lora-adapter-apply-on-the-base) +- [Use marvy-1-14B in OpenCode](#use-marvy-14b-in-opencode) +- [Prompt recipes per task](#prompt-recipes-per-task) + +--- + +## Choosing a format + +| You want… | Use | Repo | +|---|---|---| +| Max quality, GPU/server | Merged FP16 | `MainStack/marvy-1-14B` | +| Apple Silicon, native speed | Merged (MLX) | `MainStack/marvy-1-14B` | +| Laptop / CPU / Ollama / LM Studio | GGUF (Q4_K_M or Q8_0) | `MainStack/marvy-1-14B-GGUF` | +| Smallest download, compose yourself | LoRA adapter (~175 MB) | `MainStack/marvy-1-14B-lora` | + +--- + +## Recommended system prompt & settings + +Always lead with the delivery-consultant system prompt — marvy was trained with it: + +``` +You are a senior ServiceNow delivery consultant. You produce precise, implementation-grade +artifacts: business analyses, requirements, solution design documents, user stories with +acceptance criteria, test cases, and validation reviews. You favor out-of-the-box +capabilities, cite concrete tables/plugins/sys_ids when relevant, and write in clear +professional English. +``` + +| Use case | temperature | top_p | max_tokens | +|---|---|---|---| +| Structured artifacts (SDD, stories, test cases) | 0.3 – 0.5 | 0.9 | 1024 – 4096 | +| Exploratory brainstorming | 0.7 – 0.9 | 0.95 | 1024 | +| Validation / critique | 0.2 – 0.4 | 0.9 | 1024 – 2048 | + +--- + +## Transformers (PyTorch) + +```python +from transformers import AutoTokenizer, AutoModelForCausalLM + +model_id = "MainStack/marvy-1-14B" +tok = AutoTokenizer.from_pretrained(model_id) +model = AutoModelForCausalLM.from_pretrained(model_id, torch_dtype="auto", device_map="auto") + +SYSTEM = "You are a senior ServiceNow delivery consultant. ..." # full prompt above +messages = [ + {"role": "system", "content": SYSTEM}, + {"role": "user", "content": "Write a user story with acceptance criteria for P1 SLA escalation."}, +] +inputs = tok.apply_chat_template(messages, add_generation_prompt=True, return_tensors="pt").to(model.device) +out = model.generate(inputs, max_new_tokens=1024, temperature=0.4, top_p=0.9) +print(tok.decode(out[0][inputs.shape[-1]:], skip_special_tokens=True)) +``` + +## vLLM (OpenAI-compatible server) + +```bash +pip install vllm +vllm serve MainStack/marvy-1-14B --served-model-name marvy-1-14B +``` + +```bash +curl -s http://localhost:8000/v1/chat/completions -H "Content-Type: application/json" -d '{ + "model": "marvy-1-14B", "temperature": 0.4, + "messages": [ + {"role":"system","content":"You are a senior ServiceNow delivery consultant. ..."}, + {"role":"user","content":"Draft the Incident Management section of an SDD."} + ]}' +``` + +## MLX (Apple Silicon, native) + +```bash +pip install mlx-lm + +# one-off +python -m mlx_lm generate --model MainStack/marvy-1-14B \ + --system-prompt "You are a senior ServiceNow delivery consultant. ..." \ + --prompt "Write test cases for a Major Incident workflow." --max-tokens 1024 --temp 0.4 + +# OpenAI-compatible server +python -m mlx_lm server --model MainStack/marvy-1-14B --port 8080 +``` + +## LM Studio (GUI + local server) + +1. **Install the model** — either search `MainStack/marvy-1-14B-GGUF` in the + in-app model browser, or place a local copy under + `~/.lmstudio/models/MainStack/marvy-1-14B/` (MLX or GGUF layout). +2. **Load** it from the GUI, or: + ```bash + lms load MainStack/marvy-1-14B + lms server start # OpenAI-compatible on http://localhost:1234/v1 + ``` +3. In the Chat tab, set the system prompt (above) and temperature ~0.4. + +## Ollama / llama.cpp (GGUF) + +```bash +# Ollama — pull straight from the Hub +ollama run hf.co/MainStack/marvy-1-14B-GGUF:Q4_K_M + +# llama.cpp +llama-cli -hf MainStack/marvy-1-14B-GGUF:Q4_K_M \ + -p "Write a user story with acceptance criteria for P1 SLA escalation." --temp 0.4 +``` + +| Quant | Size | Use when | +|---|---|---| +| `Q4_K_M` | ~9 GB | Default — best size/quality balance | +| `Q8_0` | ~16 GB | Highest fidelity, near-FP16 | + +## LoRA adapter (apply on the base) + +```bash +# MLX +python -m mlx_lm generate --model Qwen/Qwen2.5-14B-Instruct \ + --adapter-path . --system-prompt "You are a senior ServiceNow delivery consultant. ..." \ + --prompt "Validate this requirement and list follow-up questions: ..." --max-tokens 1024 +``` + +```python +# PEFT +from peft import PeftModel +from transformers import AutoModelForCausalLM, AutoTokenizer +base = "Qwen/Qwen2.5-14B-Instruct" +model = AutoModelForCausalLM.from_pretrained(base, torch_dtype="auto", device_map="auto") +model = PeftModel.from_pretrained(model, "MainStack/marvy-1-14B-lora") +``` + +--- + +## Use marvy-1-14B in OpenCode + +marvy runs behind any OpenAI-compatible endpoint (LM Studio, mlx_lm server, +vLLM). Register it as a custom provider in `opencode.json`. + +1. **Start a local server** (LM Studio shown; adjust port for others): + ```bash + lms load MainStack/marvy-1-14B && lms server start # http://localhost:1234/v1 + ``` +2. **Add the provider** to your project `opencode.json` (or global + `~/.config/opencode/opencode.json`): + ```jsonc + { + "provider": { + "lmstudio": { + "npm": "@ai-sdk/openai-compatible", + "name": "LM Studio (local)", + "options": { "baseURL": "http://localhost:1234/v1" }, + "models": { + "marvy-1-14B": { "name": "marvy-1-14B (ServiceNow delivery)" } + } + } + } + } + ``` +3. **Select** `lmstudio/marvy-1-14B` in the OpenCode model picker. + +> marvy-1-14B is a drafting specialist, not a tool-use/agentic fine-tune. It excels +> at producing delivery artifacts inside chat; for MCP tool-calling agent loops, +> keep a frontier model as the orchestrator and switch to marvy for drafting. + +--- + +## Prompt recipes per task + +| Task | Prompt skeleton | +|---|---| +| Business analysis | "Produce a Business Analysis for the following engagement: . Cover organization, IT landscape, scope, and risks." | +| Requirements | "Extract structured requirements (id, category, requirement, priority, target_phase, success_metric) from: ." | +| Stakeholders | "Build a stakeholder register (role, name, interest, influence, RACI) for: ." | +| SDD section | "Write the
section of a Solution Design Document for a ServiceNow implementation. Include design decisions and concrete tables/plugins." | +| User story | "Write a ServiceNow user story with acceptance criteria for: ." | +| Implementation plan | "Given this story, describe the implementation: tables, plugins, configuration, records touched, manual follow-ups. Story: ." | +| Test case | "Write a test case (pre-conditions, steps, expected results, pass/fail) for the story: ." | +| Validation | "Validate this artifact against ServiceNow best practice and the SOW. List gaps, risks, and follow-up questions. Artifact: ." | diff --git a/VALIDATION.md b/VALIDATION.md new file mode 100644 index 0000000..fa0b87a --- /dev/null +++ b/VALIDATION.md @@ -0,0 +1,138 @@ +# Validating marvy-1-14B + +This guide gives you three independent ways to confirm the fine-tune actually +learned the ServiceNow delivery style — from a 60-second smoke test to a +quantitative base-vs-marvy comparison on a held-out, customer-disjoint test set. + +> TL;DR: run `bash docs/validate.sh` (from the model repo) for the quick path, +> or follow the manual steps below. + +--- + +## What "working" means here + +marvy-1-14B is a **specialist drafting model**. A successful fine-tune should show: + +1. **Format fidelity** — it emits the delivery artifact shape on cue (user + stories with acceptance criteria, SDD sections, test cases with + pre-conditions/steps/expected results) without being told the structure. +2. **Domain voice** — OOTB-first framing, ServiceNow tables/plugins, ITIL/CSDM + vocabulary, `sys_id` citations where relevant. +3. **Lower loss than the base** on held-out ServiceNow delivery text. + +The base model (Qwen2.5-14B-Instruct) is a strong generalist and will produce +*plausible* answers — the point of validation is to show marvy is **more +on-format, more domain-specific, and lower-perplexity** on this task. + +--- + +## Test 1 — 60-second smoke test (qualitative) + +Prompt the model with a bare instruction and check it produces a correctly +structured artifact with no format coaching. + +### LM Studio (local) + +```bash +lms load MainStack/marvy-1-14B +lms server start # OpenAI-compatible on http://localhost:1234/v1 + +curl -s http://localhost:1234/v1/chat/completions \ + -H "Content-Type: application/json" \ + -d '{ + "model": "marvy-1-14B", + "temperature": 0.4, + "messages": [ + {"role": "system", "content": "You are a senior ServiceNow delivery consultant. You produce precise, implementation-grade artifacts and favor out-of-the-box capabilities."}, + {"role": "user", "content": "Write a user story with acceptance criteria for auto-escalating P1 incidents that breach a 15-minute response SLA."} + ] + }' | python3 -c "import sys,json;print(json.load(sys.stdin)['choices'][0]['message']['content'])" +``` + +### MLX (Apple Silicon) + +```bash +python -m mlx_lm generate --model MainStack/marvy-1-14B \ + --system-prompt "You are a senior ServiceNow delivery consultant..." \ + --prompt "Write a user story with acceptance criteria for auto-escalating P1 incidents that breach a 15-minute response SLA." \ + --max-tokens 512 --temp 0.4 +``` + +### Pass criteria + +- [ ] Output is a **user story** (`As a … I want … so that …`) followed by + discrete, testable **acceptance criteria**. +- [ ] References ServiceNow concretely (e.g. `incident`, SLA definitions, + `sla_definition`, escalation/notification, assignment groups). +- [ ] No meta-chatter ("Sure, here is…") dominating the answer; it reads like a + backlog item, not a chatbot reply. + +--- + +## Test 2 — Task-coverage probes (qualitative, one per skill) + +Run each prompt with the recommended system prompt. Each should yield the +artifact named, in the right shape. + +| # | Prompt | Expect | +|---|--------|--------| +| 1 | "Draft the Incident Management section of an SDD for a greenfield ITSM implementation. Include assignment rules and SLA design." | SDD section: architecture/process, assignment rules (condition/action/order), SLA table | +| 2 | "Extract structured requirements (id, category, priority, target phase, success metric) from: 'We need to replace email-based access requests with a catalog item routed for manager approval.'" | Tabular/structured requirements with priorities & metrics | +| 3 | "Write a test case for the story: 'Restrict the Assignment Group field on incidents to groups with the itil role.'" | Test case: pre-conditions, steps, expected results, pass/fail | +| 4 | "We are migrating CMDB to CSDM. Produce the foundation-data load sequence and the CI classes involved." | CSDM/CMDB sequence, classes (cmdb_ci_*), foundation order | +| 5 | "Validate this requirement against best practice and list follow-up questions: 'All incidents must auto-close after 3 days.'" | Critique + concrete follow-up questions + risks | + +### Pass criteria +At least **4 of 5** produce the correct artifact type with ServiceNow-specific, +implementation-grade content (not generic ITSM prose). + +--- + +## Test 3 — Quantitative: base vs marvy on the held-out test set + +This is the strongest signal. The test split is **customer-disjoint** — two +customers that never appear in training or validation — so it measures +generalization, not memorization. + +### With the MLX training kit (in the source repo) + +```bash +cd training + +# marvy (fine-tuned adapter on the base) +python -m mlx_lm lora \ + --model mlx-community/Qwen2.5-14B-Instruct-4bit \ + --adapter-path train/adapters \ + --data train/data --test --test-batches 50 +# -> Test loss 2.573, Test ppl 13.107 (lower is better) + +# base (no adapter) for comparison +python -m mlx_lm lora \ + --model mlx-community/Qwen2.5-14B-Instruct-4bit \ + --data train/data --test --test-batches 50 +# -> expect a HIGHER loss/ppl than marvy +``` + +### Pass criteria +- [ ] marvy's **test perplexity is meaningfully lower** than the base on the + same held-out split. +- [ ] No data leakage: the test customers (`Customer-CHEM-01`, + `Customer-FININST-01`) are absent from `train.jsonl` / `valid.jsonl`. + +> Reference result for this release: **test loss 2.573 / ppl 13.107** on 50 +> batches of the project-disjoint test split (two sequences >2048 tokens are +> truncated by the eval harness, so this is a slight upper bound). + +--- + +## Interpreting results + +| Symptom | Likely cause | Action | +|---|---|---| +| Generic ITSM prose, no ServiceNow specifics | wrong/short system prompt | use the full recommended system prompt; temp 0.3–0.5 | +| Rambling, no artifact structure | temperature too high | lower to 0.3–0.4 | +| Invents `sys_id`s / plugin IDs | expected limitation | verify against a real instance; never trust IDs blindly | +| marvy ppl ≈ base ppl | adapter not applied / wrong checkpoint | confirm `--adapter-path` points at the trained adapter (iter-150) | + +marvy-1-14B is a first-draft assistant. All output must be reviewed by a qualified +ServiceNow consultant before client delivery or production configuration. diff --git a/chat_template.jinja b/chat_template.jinja new file mode 100644 index 0000000..bdf7919 --- /dev/null +++ b/chat_template.jinja @@ -0,0 +1,54 @@ +{%- if tools %} + {{- '<|im_start|>system\n' }} + {%- if messages[0]['role'] == 'system' %} + {{- messages[0]['content'] }} + {%- else %} + {{- 'You are Qwen, created by Alibaba Cloud. You are a helpful assistant.' }} + {%- endif %} + {{- "\n\n# Tools\n\nYou may call one or more functions to assist with the user query.\n\nYou are provided with function signatures within XML tags:\n" }} + {%- for tool in tools %} + {{- "\n" }} + {{- tool | tojson }} + {%- endfor %} + {{- "\n\n\nFor each function call, return a json object with function name and arguments within XML tags:\n\n{\"name\": , \"arguments\": }\n<|im_end|>\n" }} +{%- else %} + {%- if messages[0]['role'] == 'system' %} + {{- '<|im_start|>system\n' + messages[0]['content'] + '<|im_end|>\n' }} + {%- else %} + {{- '<|im_start|>system\nYou are Qwen, created by Alibaba Cloud. You are a helpful assistant.<|im_end|>\n' }} + {%- endif %} +{%- endif %} +{%- for message in messages %} + {%- if (message.role == "user") or (message.role == "system" and not loop.first) or (message.role == "assistant" and not message.tool_calls) %} + {{- '<|im_start|>' + message.role + '\n' + message.content + '<|im_end|>' + '\n' }} + {%- elif message.role == "assistant" %} + {{- '<|im_start|>' + message.role }} + {%- if message.content %} + {{- '\n' + message.content }} + {%- endif %} + {%- for tool_call in message.tool_calls %} + {%- if tool_call.function is defined %} + {%- set tool_call = tool_call.function %} + {%- endif %} + {{- '\n\n{"name": "' }} + {{- tool_call.name }} + {{- '", "arguments": ' }} + {{- tool_call.arguments | tojson }} + {{- '}\n' }} + {%- endfor %} + {{- '<|im_end|>\n' }} + {%- elif message.role == "tool" %} + {%- if (loop.index0 == 0) or (messages[loop.index0 - 1].role != "tool") %} + {{- '<|im_start|>user' }} + {%- endif %} + {{- '\n\n' }} + {{- message.content }} + {{- '\n' }} + {%- if loop.last or (messages[loop.index0 + 1].role != "tool") %} + {{- '<|im_end|>\n' }} + {%- endif %} + {%- endif %} +{%- endfor %} +{%- if add_generation_prompt %} + {{- '<|im_start|>assistant\n' }} +{%- endif %} diff --git a/config.json b/config.json new file mode 100644 index 0000000..c8cc234 --- /dev/null +++ b/config.json @@ -0,0 +1,30 @@ +{ + "architectures": [ + "Qwen2ForCausalLM" + ], + "attention_dropout": 0.0, + "bos_token_id": 151643, + "eos_token_id": [ + 151645, + 151643 + ], + "hidden_act": "silu", + "hidden_size": 5120, + "initializer_range": 0.02, + "intermediate_size": 13824, + "max_position_embeddings": 32768, + "max_window_layers": 70, + "model_type": "qwen2", + "num_attention_heads": 40, + "num_hidden_layers": 48, + "num_key_value_heads": 8, + "rms_norm_eps": 1e-06, + "rope_theta": 1000000.0, + "sliding_window": 131072, + "tie_word_embeddings": false, + "torch_dtype": "bfloat16", + "transformers_version": "4.43.1", + "use_cache": true, + "use_sliding_window": false, + "vocab_size": 152064 +} \ No newline at end of file diff --git a/generation_config.json b/generation_config.json new file mode 100644 index 0000000..bf077f0 --- /dev/null +++ b/generation_config.json @@ -0,0 +1,14 @@ +{ + "bos_token_id": 151643, + "pad_token_id": 151643, + "do_sample": true, + "eos_token_id": [ + 151645, + 151643 + ], + "repetition_penalty": 1.05, + "temperature": 0.7, + "top_p": 0.8, + "top_k": 20, + "transformers_version": "4.37.0" +} \ No newline at end of file diff --git a/marvy_improvement.png b/marvy_improvement.png new file mode 100644 index 0000000000000000000000000000000000000000..5149f7c4e540b03297a6925e33475e80e1641dd6 GIT binary patch literal 57570 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", + "errors": "replace", + "extra_special_tokens": [ + "<|im_start|>", + "<|im_end|>", + "<|object_ref_start|>", + "<|object_ref_end|>", + "<|box_start|>", + "<|box_end|>", + "<|quad_start|>", + "<|quad_end|>", + "<|vision_start|>", + "<|vision_end|>", + "<|vision_pad|>", + "<|image_pad|>", + "<|video_pad|>" + ], + "is_local": true, + "local_files_only": false, + "model_max_length": 131072, + "pad_token": "<|endoftext|>", + "split_special_tokens": false, + "tokenizer_class": "Qwen2Tokenizer", + "tool_parser_type": "json_tools", + "unk_token": null +} diff --git a/validate.sh b/validate.sh new file mode 100644 index 0000000..e31a4d7 --- /dev/null +++ b/validate.sh @@ -0,0 +1,61 @@ +#!/usr/bin/env bash +# marvy-14B quick validation harness. +# +# Runs the task-coverage probes (Test 2 in VALIDATION.md) against any +# OpenAI-compatible endpoint — LM Studio, mlx_lm server, vLLM, etc. — and prints +# each artifact plus a lightweight heuristic PASS/FAIL on domain keywords. +# +# Usage: +# bash validate.sh # defaults to LM Studio +# BASE_URL=http://localhost:8080/v1 MODEL=marvy-14B bash validate.sh +# API_KEY=xxx BASE_URL=https://... MODEL=MainStack/marvy-14B bash validate.sh +set -uo pipefail + +BASE_URL="${BASE_URL:-http://localhost:1234/v1}" # LM Studio default +MODEL="${MODEL:-marvy-14B}" +API_KEY="${API_KEY:-lm-studio}" +TEMP="${TEMP:-0.4}" +MAXTOK="${MAXTOK:-700}" + +SYSTEM="You are a senior ServiceNow delivery consultant. You produce precise, implementation-grade artifacts: business analyses, requirements, solution design documents, user stories with acceptance criteria, test cases, and validation reviews. You favor out-of-the-box capabilities, cite concrete tables/plugins/sys_ids when relevant, and write in clear professional English." + +# probe | expected-keyword-regex (case-insensitive) for a heuristic pass +PROMPTS=( + "Write a user story with acceptance criteria for auto-escalating P1 incidents that breach a 15-minute response SLA.|as a.*i want.*so that|acceptance|sla" + "Draft the Incident Management section of an SDD for a greenfield ITSM implementation. Include assignment rules and SLA design.|assignment|sla|incident" + "Extract structured requirements (id, category, priority, target phase, success metric) from: replace email-based access requests with a catalog item routed for manager approval.|priority|requirement|catalog" + "Write a test case for the story: Restrict the Assignment Group field on incidents to groups with the itil role.|pre-condition|step|expected|itil" + "Validate this requirement against best practice and list follow-up questions: All incidents must auto-close after 3 days.|follow-up|risk|question" +) + +command -v jq >/dev/null 2>&1 || { echo "ERROR: jq is required (brew install jq)"; exit 1; } + +echo "Endpoint: $BASE_URL Model: $MODEL Temp: $TEMP" +echo "============================================================" +pass=0; total=0 +for entry in "${PROMPTS[@]}"; do + total=$((total+1)) + prompt="${entry%%|*}" + rest="${entry#*|}"; regex="$rest" + payload=$(jq -n --arg m "$MODEL" --arg s "$SYSTEM" --arg p "$prompt" \ + --argjson t "$TEMP" --argjson mx "$MAXTOK" \ + '{model:$m,temperature:$t,max_tokens:$mx,messages:[{role:"system",content:$s},{role:"user",content:$p}]}') + resp=$(curl -s "$BASE_URL/chat/completions" -H "Content-Type: application/json" \ + -H "Authorization: Bearer $API_KEY" -d "$payload") + content=$(echo "$resp" | jq -r '.choices[0].message.content // .error.message // "<>"') + echo "" + echo "### Probe $total: $prompt" + echo "------------------------------------------------------------" + echo "$content" | head -40 + if echo "$content" | grep -iqE "$regex"; then + echo ">>> heuristic: PASS" + pass=$((pass+1)) + else + echo ">>> heuristic: REVIEW (expected pattern not matched: $regex)" + fi + echo "============================================================" +done +echo "" +echo "Heuristic result: $pass/$total probes matched domain patterns." +echo "Pass threshold: >= 4/5 with implementation-grade, ServiceNow-specific content." +echo "Note: heuristics are a sanity check — read the outputs to judge true quality."