Repository: jingyaogong/minimind
Branch: master
Commit: 349e74ec7b04
Files: 30
Total size: 795.6 KB
Directory structure:
gitextract_m56jzuhj/
├── .gitignore
├── CODE_OF_CONDUCT.md
├── LICENSE
├── README.md
├── README_en.md
├── dataset/
│ ├── __init__.py
│ ├── dataset.md
│ └── lm_dataset.py
├── eval_llm.py
├── model/
│ ├── __init__.py
│ ├── model_lora.py
│ ├── model_minimind.py
│ ├── tokenizer.json
│ └── tokenizer_config.json
├── requirements.txt
├── scripts/
│ ├── chat_openai_api.py
│ ├── convert_model.py
│ ├── serve_openai_api.py
│ └── web_demo.py
└── trainer/
├── train_distillation.py
├── train_dpo.py
├── train_full_sft.py
├── train_grpo.py
├── train_lora.py
├── train_ppo.py
├── train_pretrain.py
├── train_reason.py
├── train_spo.py
├── train_tokenizer.py
└── trainer_utils.py
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
model/__pycache__
out
website/
docs-minimind/
================================================
FILE: CODE_OF_CONDUCT.md
================================================
# Contributor Covenant Code of Conduct
## Our Pledge
We as members, contributors, and leaders pledge to make participation in our
community a harassment-free experience for everyone, regardless of age, body
size, visible or invisible disability, ethnicity, sex characteristics, gender
identity and expression, level of experience, education, socio-economic status,
nationality, personal appearance, race, religion, or sexual identity
and orientation.
We pledge to act and interact in ways that contribute to an open, welcoming,
diverse, inclusive, and healthy community.
## Our Standards
Examples of behavior that contributes to a positive environment for our
community include:
* Demonstrating empathy and kindness toward other people
* Being respectful of differing opinions, viewpoints, and experiences
* Giving and gracefully accepting constructive feedback
* Accepting responsibility and apologizing to those affected by our mistakes,
and learning from the experience
* Focusing on what is best not just for us as individuals, but for the
overall community
Examples of unacceptable behavior include:
* The use of sexualized language or imagery, and sexual attention or
advances of any kind
* Trolling, insulting or derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or email
address, without their explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
## Enforcement Responsibilities
Community leaders are responsible for clarifying and enforcing our standards of
acceptable behavior and will take appropriate and fair corrective action in
response to any behavior that they deem inappropriate, threatening, offensive,
or harmful.
Community leaders have the right and responsibility to remove, edit, or reject
comments, commits, code, wiki edits, issues, and other contributions that are
not aligned to this Code of Conduct, and will communicate reasons for moderation
decisions when appropriate.
## Scope
This Code of Conduct applies within all community spaces, and also applies when
an individual is officially representing the community in public spaces.
Examples of representing our community include using an official e-mail address,
posting via an official social media account, or acting as an appointed
representative at an online or offline event.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community leaders responsible for enforcement at
.
All complaints will be reviewed and investigated promptly and fairly.
All community leaders are obligated to respect the privacy and security of the
reporter of any incident.
## Enforcement Guidelines
Community leaders will follow these Community Impact Guidelines in determining
the consequences for any action they deem in violation of this Code of Conduct:
### 1. Correction
**Community Impact**: Use of inappropriate language or other behavior deemed
unprofessional or unwelcome in the community.
**Consequence**: A private, written warning from community leaders, providing
clarity around the nature of the violation and an explanation of why the
behavior was inappropriate. A public apology may be requested.
### 2. Warning
**Community Impact**: A violation through a single incident or series
of actions.
**Consequence**: A warning with consequences for continued behavior. No
interaction with the people involved, including unsolicited interaction with
those enforcing the Code of Conduct, for a specified period of time. This
includes avoiding interactions in community spaces as well as external channels
like social media. Violating these terms may lead to a temporary or
permanent ban.
### 3. Temporary Ban
**Community Impact**: A serious violation of community standards, including
sustained inappropriate behavior.
**Consequence**: A temporary ban from any sort of interaction or public
communication with the community for a specified period of time. No public or
private interaction with the people involved, including unsolicited interaction
with those enforcing the Code of Conduct, is allowed during this period.
Violating these terms may lead to a permanent ban.
### 4. Permanent Ban
**Community Impact**: Demonstrating a pattern of violation of community
standards, including sustained inappropriate behavior, harassment of an
individual, or aggression toward or disparagement of classes of individuals.
**Consequence**: A permanent ban from any sort of public interaction within
the community.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
version 2.0, available at
https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
Community Impact Guidelines were inspired by [Mozilla's code of conduct
enforcement ladder](https://github.com/mozilla/diversity).
[homepage]: https://www.contributor-covenant.org
For answers to common questions about this code of conduct, see the FAQ at
https://www.contributor-covenant.org/faq. Translations are available at
https://www.contributor-covenant.org/translations.
================================================
FILE: LICENSE
================================================
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.
================================================
FILE: README.md
================================================


[](https://github.com/jingyaogong/minimind/stargazers)
[](LICENSE)
[](https://github.com/jingyaogong/minimind/commits/master)
[](https://github.com/jingyaogong/minimind/pulls)
[](https://huggingface.co/collections/jingyaogong/minimind-66caf8d999f5c7fa64f399e5)

"大道至简"
中文 | [English](./README_en.md)
* 此开源项目旨在完全从0开始,仅用3块钱成本 + 2小时!即可训练出仅为25.8M的超小语言模型**MiniMind**。
* **MiniMind**系列极其轻量,最小版本体积是 GPT-3 的 $\frac{1}{7000}$,力求做到最普通的个人GPU也可快速训练。
* 项目同时开源了大模型的极简结构-包含拓展共享混合专家(MoE)、数据集清洗、预训练(Pretrain)、监督微调(SFT)、LoRA微调、直接偏好优化(DPO)、强化学习训练(RLAIF: PPO/GRPO等)、模型蒸馏等全过程代码。
* **MiniMind**同时拓展了视觉多模态的VLM: [MiniMind-V](https://github.com/jingyaogong/minimind-v)。
* 项目所有核心算法代码均从0使用PyTorch原生重构!不依赖第三方库提供的抽象接口。
* 这不仅是大语言模型的全阶段开源复现,也是一个入门LLM的教程。
* 希望此项目能为所有人提供一个抛砖引玉的示例,一起感受创造的乐趣!推动更广泛AI社区的进步!
> 为防止误解,“2小时” 基于NVIDIA 3090硬件设备(单卡)测试,“3块钱”指GPU服务器租用成本,具体规格详情见下文。
---

[🔗🍓推理模型](https://www.modelscope.cn/studios/gongjy/MiniMind-Reasoning) | [🔗🤖常规模型](https://www.modelscope.cn/studios/gongjy/MiniMind) | [🔗🎞️视频介绍](https://www.bilibili.com/video/BV12dHPeqE72/?share_source=copy_web&vd_source=670c2504f88726f8cf4a21ef6147c0e8)
# 📌 Introduction
大语言模型(Large Language Model, LLM)的出现引发了全世界对AI的空前关注。
无论是ChatGPT、DeepSeek还是Qwen,都以其惊艳的效果令人叹为观止。
然而,动辄数百亿参数的庞大规模,使得它们对个人设备而言不仅难以训练,甚至连部署都显得遥不可及。
打开大模型的“黑盒子”,探索其内部运作机制,多么令人心潮澎湃!
遗憾的是,99%的探索只能止步于使用LoRA等技术对现有大模型进行少量微调,学习一些新指令或任务。
这就好比教牛顿如何使用21世纪的智能手机——虽然有趣,却完全偏离了理解物理本质的初衷。
与此同时,第三方的大模型框架和工具库,如transformers+trl,几乎只暴露了高度抽象的接口。
通过短短10行代码,就能完成“加载模型+加载数据集+推理+强化学习”的全流程训练。
这种高效的封装固然便利,但也像一架高速飞船,将开发者与底层实现隔离开来,阻碍了深入探究LLM核心代码的机会。
然而,“用乐高拼出一架飞机,远比坐在头等舱里飞行更让人兴奋!”。
更糟糕的是,互联网上充斥着大量付费课程和营销号,以漏洞百出、一知半解的内容推销AI教程。
正因如此,本项目初衷是拉低LLM的学习门槛,让每个人都能从理解每一行代码开始,
从零开始亲手训练一个极小的语言模型。是的,从**零开始训练**,而不是仅仅进行**推理**!
最低只需3块钱不到的服务器成本,就能亲身体验从0到1构建一个语言模型的全过程。
一起感受创造的乐趣吧!
> [!NOTE]
> (截至2025-10)MiniMind系列已完成多个型号模型的预训练,最小仅需25.8M(0.02B),即可具备流畅对话能力!
Models List
| 模型 (大小) | 推理占用 (约) | Release |
|-------------------------|----------|------------|
| MiniMind2-small (26M) | 0.5 GB | 2025.04.26 |
| MiniMind2-MoE (145M) | 1.0 GB | 2025.04.26 |
| MiniMind2 (104M) | 1.0 GB | 2025.04.26 |
| minimind-v1-small (26M) | 0.5 GB | 2024.08.28 |
| minimind-v1-moe (4×26M) | 1.0 GB | 2024.09.17 |
| minimind-v1 (108M) | 1.0 GB | 2024.09.01 |
**项目包含**
- MiniMind-LLM结构的全部代码(Dense+MoE模型)。
- 包含Tokenizer分词器详细训练代码。
- 包含Pretrain、SFT、LoRA、RLHF-DPO、RLAIF(PPO/GRPO/SPO)、模型蒸馏的全过程训练代码。
- 收集、蒸馏、整理并清洗去重所有阶段的高质量数据集,且全部开源。
- 从0实现预训练、指令微调、LoRA、DPO/PPO/GRPO/SPO强化学习,白盒模型蒸馏。关键算法几乎不依赖第三方封装的框架,且全部开源。
- 同时兼容`transformers`、`trl`、`peft`等第三方主流框架。
- 训练支持单机单卡、单机多卡(DDP、DeepSpeed)训练,支持wandb/swanlab可视化训练流程。支持动态启停训练。
- 在第三方测评榜(C-Eval、C-MMLU、OpenBookQA等)进行模型测试,支持YaRN算法执行RoPE长文本外推。
- 实现Openai-Api协议的极简服务端,便于集成到第三方ChatUI使用(FastGPT、Open-WebUI等)。
- 基于streamlit实现最简聊天WebUI前端。
- 全面兼容社区热门`llama.cpp`、`vllm`、`ollama`推理引擎或`Llama-Factory`训练框架。
- 复现(蒸馏/RL)大型推理模型DeepSeek-R1的MiniMind-Reason模型,**数据+模型**全部开源!
希望此开源项目可以帮助LLM初学者快速入门!
### 👉**更新日志**
2025-10-24
- 🔥 新增RLAIF训练算法:PPO、GRPO、SPO(从0原生实现)
- 新增断点续训功能:支持训练自动恢复、跨GPU数量恢复、wandb记录连续性
- 新增RLAIF数据集:rlaif-mini.jsonl(从SFT数据随机采样1万条);简化DPO数据集,加入中文数据
- 新增YaRN算法:支持RoPE长文本外推,提升长序列处理能力
- Adaptive Thinking:Reason模型可选是否启用思考链
- chat_template全面支持Tool Calling和Reasoning标签(``、``等)
- 新增RLAIF完整章节、训练曲线对比、算法原理折叠说明
- [SwanLab](https://swanlab.cn/)替代WandB(国内访问友好,API完全兼容)
- 规范化所有代码 & 修复一些已知bugs
2025-04-26
- 重要更新
- 如有兼容性需要,可访问[🔗旧仓库内容🔗](https://github.com/jingyaogong/minimind/tree/7da201a944a90ed49daef8a0265c959288dff83a)。
- MiniMind模型参数完全改名,对齐Transformers库模型(统一命名)。
- generate方式重构,继承自GenerationMixin类。
- 🔥支持llama.cpp、vllm、ollama等热门三方生态。
- 规范代码和目录结构。
- 改动词表` `->`<|im_start|><|im_end|>`
```text
为兼容第三方推理框架llama.cpp、vllm,本次更新需付出一些可观代价。
本次更新不再支持「直接」加载25-04-26以前的旧模型进行推理。
由于Llama位置编码方式与minimind存在区别,导致映射Llama模型后QK值存在差异
MiniMind2系列旧模型均经过权重映射+(微调训练)QKVO线性层校准恢复而来。
本次更新后将放弃对`minimind-v1`全系列的维护,并在仓库中下线。
```
2025-02-09
- 迎来发布以来重大更新,Release MiniMind2 Series。
- 代码几乎全部重构,使用更简洁明了的统一结构。
如有旧代码的兼容性需要,可访问[🔗旧仓库内容🔗](https://github.com/jingyaogong/minimind/tree/6e9cd28ef9b34a0a10afbdf6f59e65cb6e628efb)。
- 免去数据预处理步骤。统一数据集格式,更换为`jsonl`格式杜绝数据集下载混乱的问题。
- MiniMind2系列效果相比MiniMind-V1显著提升。
- 小问题:{kv-cache写法更标准、MoE的负载均衡loss被考虑等等}
- 提供模型迁移到私有数据集的训练方案(医疗模型、自我认知样例)。
- 精简预训练数据集,并大幅提升预训练数据质量,大幅缩短个人快速训练所需时间,单卡3090即可2小时复现!
- 更新:LoRA微调脱离peft包装,从0实现LoRA过程;DPO算法从0使用PyTorch原生实现;模型白盒蒸馏原生实现。
- MiniMind2-DeepSeek-R1系列蒸馏模型诞生!
- MiniMind2具备一定的英文能力!
- 更新MiniMind2与第三方模型的基于更多大模型榜单测试性能的结果。
More...
**2024-10-05**
- 为MiniMind拓展了多模态能力之---视觉
- 移步孪生项目[minimind-v](https://github.com/jingyaogong/minimind-v)查看详情!
**2024-09-27**
- 09-27更新pretrain数据集的预处理方式,为了保证文本完整性,放弃预处理成.bin训练的形式(轻微牺牲训练速度)。
- 目前pretrain预处理后的文件命名为:pretrain_data.csv。
- 删除了一些冗余的代码。
**2024-09-17**
- 更新minimind-v1-moe模型
- 为了防止歧义,不再使用mistral_tokenizer分词,全部采用自定义的minimind_tokenizer作为分词器。
**2024-09-01**
- 更新minimind-v1 (108M)模型,采用minimind_tokenizer,预训练轮次3 + SFT轮次10,更充分训练,性能更强。
- 项目已部署至ModelScope创空间,可以在此网站上体验:
- [🔗ModelScope在线体验🔗](https://www.modelscope.cn/studios/gongjy/minimind)
**2024-08-27**
- 项目首次开源
# 📌 快速开始
分享本人的软硬件配置(仅供参考)
* CPU: Intel(R) Core(TM) i9-10980XE CPU @ 3.00GHz
* RAM: 128 GB
* GPU: NVIDIA GeForce RTX 3090(24GB) * 8
* Ubuntu==20.04
* CUDA==12.2
* Python==3.10.16
* [requirements.txt](./requirements.txt)
### 第0步
```bash
git clone https://github.com/jingyaogong/minimind.git
```
## Ⅰ 测试已有模型效果
### 1.环境准备
```bash
pip install -r requirements.txt -i https://mirrors.aliyun.com/pypi/simple
```
### 2.下载模型
到项目根目录
```bash
git clone https://huggingface.co/jingyaogong/MiniMind2 # or https://www.modelscope.cn/models/gongjy/MiniMind2
```
### (可选)命令行问答
```bash
# 使用transformers格式模型
python eval_llm.py --load_from ./MiniMind2
```
### (可选)启动WebUI
```bash
# 可能需要`python>=3.10` 安装 `pip install streamlit`
# cd scripts
streamlit run web_demo.py
```
### (可选)第三方推理框架
```bash
# ollama
ollama run jingyaogong/minimind2
# vllm
vllm serve ./MiniMind2/ --served-model-name "minimind"
```
## Ⅱ 从0开始自己训练
### 1.环境准备
```bash
pip install -r requirements.txt -i https://mirrors.aliyun.com/pypi/simple
```
注:提前测试Torch是否可用cuda
```bash
import torch
print(torch.cuda.is_available())
```
如果不可用,请自行去[torch_stable](https://download.pytorch.org/whl/torch_stable.html)
下载whl文件安装。参考[链接](https://blog.csdn.net/weixin_45456738/article/details/141029610?ops_request_misc=&request_id=&biz_id=102&utm_term=%E5%AE%89%E8%A3%85torch&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduweb~default-2-141029610.nonecase&spm=1018.2226.3001.4187)
### 2.数据下载
从下文提供的[数据集下载链接](https://www.modelscope.cn/datasets/gongjy/minimind_dataset/files)
下载需要的数据文件(创建`./dataset`目录)并放到`./dataset`下
注:数据集须知
默认推荐下载`pretrain_hq.jsonl` + `sft_mini_512.jsonl`最快速度复现Zero聊天模型。
数据文件可自由选择,下文提供了多种搭配方案,可根据自己手头的训练需求和GPU资源进行适当组合。
### 3.开始训练
目录位于`trainer`
💡 检查点暂停续训
所有训练脚本均自动保存检查点,只需添加 `--from_resume 1` 参数即可自动检测加载&恢复训练:
```bash
python train_pretrain.py --from_resume 1
python train_full_sft.py --from_resume 1
...
```
**断点续训机制说明:**
- 训练过程自动在 `./checkpoints/` 目录保存完整检查点(模型、优化器、训练进度等)
- 检查点文件命名:`<权重名>_<维度>_resume.pth`(如:`full_sft_512_resume.pth`)
- 支持跨不同GPU数量恢复(自动调整step)
- 支持wandb训练记录连续性(自动恢复同一个run)
> 适合长时间训练或不稳定环境,无需担心训练中断导致进度丢失
**3.1 预训练(学知识)**
```bash
python train_pretrain.py
```
> 执行预训练,得到 `pretrain_*.pth` 作为预训练的输出权重(其中*为模型的dimension,默认为512)
**3.2 监督微调(学对话方式)**
```bash
python train_full_sft.py
```
> 执行监督微调,得到 `full_sft_*.pth` 作为指令微调的输出权重(其中`full`即为全参数微调)
注:训练须知
所有训练过程默认每隔100步保存1次参数到文件`./out/***.pth`(每次会覆盖掉旧权重文件)。
简单起见,此处只写明两个阶段训练过程。如需其它训练 (LoRA, 蒸馏, 强化学习, 微调推理等) 可参考下文【实验】小节的详细说明。
---
### 4.测试自己训练的模型效果
确保需要测试的模型`*.pth`文件位于`./out/`目录下。
也可以直接去[此处](https://www.modelscope.cn/models/gongjy/MiniMind2-PyTorch/files)下载使用我训练的`*.pth`文件。
```bash
python eval_llm.py --weight full_sft # 或 pretrain/dpo/ppo/grpo...
```
注:测试须知
`--weight` 参数指定权重名称前缀,可选:`pretrain`, `full_sft`, `dpo`, `reason`, `ppo_actor`, `grpo`, `spo` 等
其他常用参数:
- `--load_from`: 模型加载路径(`model`=原生torch权重,其他路径=transformers格式)
- `--save_dir`: 模型权重目录(默认`out`)
- `--lora_weight`: LoRA权重名称(`None`表示不使用)
- `--historys`: 携带历史对话轮数(需为偶数,0表示不携带历史)
- `--max_new_tokens`: 最大生成长度(默认8192)
- `--temperature`: 生成温度(默认0.85)
- `--top_p`: nucleus采样阈值(默认0.85)
使用方式直接查看`eval_llm.py`代码即可。
---
> [!TIP]
> 所有训练脚本均为Pytorch原生框架,均支持多卡加速,假设你的设备有N (N>1) 张显卡:
单机N卡启动训练方式 (DDP, 支持多机多卡集群)
```bash
torchrun --nproc_per_node N train_xxx.py
```
注:其它须知
单机N卡启动训练 (DeepSpeed)
```bash
deepspeed --master_port 29500 --num_gpus=N train_xxx.py
```
可根据需要开启wandb记录训练过程(需可直连)
```bash
# 需要登录: wandb login
torchrun --nproc_per_node N train_xxx.py --use_wandb
# and
python train_xxx.py --use_wandb
```
通过添加`--use_wandb`参数,可以记录训练过程,训练完成后,可以在wandb网站上查看训练过程。通过修改`wandb_project`
和`wandb_run_name`参数,可以指定项目名称和运行名称。
【注】:25年6月后,国内网络环境无法直连WandB,MiniMind项目默认转为使用[SwanLab](https://swanlab.cn/)作为训练可视化工具(完全兼容WandB API),即`import wandb`改为`import swanlab as wandb`即可,其他均无需改动。
# 📌 数据介绍
## Ⅰ Tokenizer
分词器将单词从自然语言通过“词典”映射到`0, 1, 36`这样的数字,可以理解为数字就代表了单词在“词典”中的页码。
可以选择自己构造词表训练一个“词典”,代码可见`./trainer/train_tokenizer.py`(仅供学习参考,若非必要无需再自行训练,MiniMind已自带tokenizer)。
或者选择比较出名的开源大模型分词器,
正如同直接用新华/牛津词典的优点是token编码压缩率很好,缺点是页数太多,动辄数十万个词汇短语;
自己训练的分词器,优点是词表长度和内容随意控制,缺点是压缩率很低(例如"hello"也许会被拆分为"h e l l o"
五个独立的token),且生僻词难以覆盖。
“词典”的选择固然很重要,LLM的输出本质上是SoftMax到词典N个词的多分类问题,然后通过“词典”解码到自然语言。
因为MiniMind体积需要严格控制,为了避免模型头重脚轻(词嵌入embedding层参数在LLM占比太高),所以词表长度短短益善。
Tokenizer介绍
第三方强大的开源模型例如Yi、qwen、chatglm、mistral、Llama3的tokenizer词表长度如下:
Tokenizer模型 词表大小 来源
yi tokenizer 64,000 01万物(中国)
qwen2 tokenizer 151,643 阿里云(中国)
glm tokenizer 151,329 智谱AI(中国)
mistral tokenizer 32,000 Mistral AI(法国)
llama3 tokenizer 128,000 Meta(美国)
minimind tokenizer 6,400 自定义
> 👉2024-09-17更新:为了防止过去的版本歧义&控制体积,minimind所有模型均使用minimind_tokenizer分词,废弃所有mistral_tokenizer版本。
```
# 一些自言自语
> 尽管minimind_tokenizer长度很小,编解码效率弱于qwen2、glm等中文友好型分词器。
> 但minimind模型选择了自己训练的minimind_tokenizer作为分词器,以保持整体参数轻量,避免编码层和计算层占比失衡,头重脚轻,因为minimind的词表大小只有6400。
> 且minimind在实际测试中没有出现过生僻词汇解码失败的情况,效果良好。
> 由于自定义词表压缩长度到6400,使得LLM总参数量最低只有25.8M。
> 训练数据`pretrain_hq.jsonl`均来自于`匠数大模型数据集`,这部分数据相对次要,如需训练可以自由选择。
```
## Ⅱ Pretrain数据
经历了MiniMind-V1的低质量预训练数据,导致模型胡言乱语的教训,`2025-02-05` 之后决定不再采用大规模无监督的数据集做预训练。
进而尝试把[匠数大模型数据集](https://www.modelscope.cn/datasets/deepctrl/deepctrl-sft-data)的中文部分提取出来,
清洗出字符`<512`长度的大约1.6GB的语料直接拼接成预训练数据 `pretrain_hq.jsonl`,hq即为high
quality(当然也还不算high,提升数据质量无止尽)。
文件`pretrain_hq.jsonl` 数据格式为
```json
{"text": "如何才能摆脱拖延症? 治愈拖延症并不容易,但以下建议可能有所帮助..."}
```
## Ⅲ SFT数据
[匠数大模型SFT数据集](https://www.modelscope.cn/datasets/deepctrl/deepctrl-sft-data)
“是一个完整、格式统一、安全的大模型训练和研究资源。
从网络上的公开数据源收集并整理了大量开源数据集,对其进行了格式统一,数据清洗,
包含10M条数据的中文数据集和包含2M条数据的英文数据集。”
以上是官方介绍,下载文件后的数据总量大约在4B tokens,肯定是适合作为中文大语言模型的SFT数据的。
但是官方提供的数据格式很乱,全部用来sft代价太大。
我将把官方数据集进行了二次清洗,把含有符号污染和噪声的条目去除;另外依然只保留了总长度`<512`
的内容,此阶段希望通过大量对话补充预训练阶段欠缺的知识。
导出文件为`sft_512.jsonl`(~7.5GB)。
[Magpie-SFT数据集](https://www.modelscope.cn/organization/Magpie-Align)
收集了~1M条来自Qwen2/2.5的高质量对话,我将这部分数据进一步清洗,把总长度`<2048`的部分导出为`sft_2048.jsonl`(~9GB)。
长度`<1024`的部分导出为`sft_1024.jsonl`(~5.5GB),用大模型对话数据直接进行sft就属于“黑盒蒸馏”的范畴。
进一步清洗前两步sft的数据(只保留中文字符占比高的内容),筛选长度`<512`的对话,得到`sft_mini_512.jsonl`(~1.2GB)。
所有sft文件 `sft_X.jsonl` 数据格式均为
```text
{
"conversations": [
{"role": "user", "content": "你好"},
{"role": "assistant", "content": "你好!"},
{"role": "user", "content": "再见"},
{"role": "assistant", "content": "再见!"}
]
}
```
## Ⅳ RLHF数据
来自[Magpie-DPO数据集](https://www.modelscope.cn/datasets/Magpie-Align/MagpieLM-DPO-Data-v0.1)
大约200k条偏好数据(均是英文)生成自Llama3.1-70B/8B,可以用于训练奖励模型,优化模型回复质量,使其更加符合人类偏好。
这里将数据总长度`<3000`的内容重组为`dpo.jsonl`(~0.9GB),包含`chosen`和`rejected`两个字段,`chosen`
为偏好的回复,`rejected`为拒绝的回复。
文件 `dpo.jsonl` 数据格式为
```text
{
"chosen": [
{"content": "Q", "role": "user"},
{"content": "good answer", "role": "assistant"}
],
"rejected": [
{"content": "Q", "role": "user"},
{"content": "bad answer", "role": "assistant"}
]
}
```
## Ⅴ Reason数据集:
不得不说2025年2月谁能火的过DeepSeek...
也激发了我对RL引导的推理模型的浓厚兴趣,目前已经用Qwen2.5复现了R1-Zero。
如果有时间+效果work(但99%基模能力不足)我会在之后更新MiniMind基于RL训练的推理模型而不是蒸馏模型。
时间有限,最快的低成本方案依然是直接蒸馏(黑盒方式)。
耐不住R1太火,短短几天就已经存在一些R1的蒸馏数据集[R1-Llama-70B](https://www.modelscope.cn/datasets/Magpie-Align/Magpie-Reasoning-V2-250K-CoT-Deepseek-R1-Llama-70B)、[R1-Distill-SFT](https://www.modelscope.cn/datasets/AI-ModelScope/R1-Distill-SFT)、
[Alpaca-Distill-R1](https://huggingface.co/datasets/shareAI/Alpaca-Distill-R1-ZH)、
[deepseek_r1_zh](https://huggingface.co/datasets/jinliuxi/deepseek_r1_zh)等等,纯中文的数据可能比较少。
最终整合它们,导出文件为`r1_mix_1024.jsonl`,数据格式和`sft_X.jsonl`一致。
## Ⅵ 更多数据集
目前已经有[HqWu-HITCS/Awesome-Chinese-LLM](https://github.com/HqWu-HITCS/Awesome-Chinese-LLM)
在收集和梳理中文LLM相关的开源模型、应用、数据集及教程等资料,并持续更新这方面的最新进展。全面且专业,Respect!
---
## Ⅷ MiniMind训练数据集
> [!NOTE]
> 2025-02-05后,开源MiniMind最终训练所用的所有数据集,因此无需再自行预处理大规模数据集,避免重复性的数据处理工作。
MiniMind训练数据集下载地址: [ModelScope](https://www.modelscope.cn/datasets/gongjy/minimind_dataset/files) | [HuggingFace](https://huggingface.co/datasets/jingyaogong/minimind_dataset/tree/main)
> 无需全部clone,可单独下载所需的文件
将下载的数据集文件放到`./dataset/`目录下(✨为推荐的必须项)
```bash
./dataset/
├── dpo.jsonl (55MB, ✨)
├── lora_identity.jsonl (22.8KB)
├── lora_medical.jsonl (34MB)
├── pretrain_hq.jsonl (1.6GB, ✨)
├── r1_mix_1024.jsonl (340MB)
├── rlaif-mini.jsonl (1MB, ✨)
├── sft_1024.jsonl (5.6GB)
├── sft_2048.jsonl (9GB)
├── sft_512.jsonl (7.5GB)
└── sft_mini_512.jsonl (1.2GB, ✨)
```
注:各数据集简介
* `dpo.jsonl`✨ --RLHF阶段数据集(已精简优化,适合快速训练)
* `lora_identity.jsonl` --自我认知数据集(例如:你是谁?我是minimind...),推荐用于lora训练(亦可用于全参SFT,勿被名字局限)
* `lora_medical.jsonl` --医疗问答数据集,推荐用于lora训练(亦可用于全参SFT,勿被名字局限)
* `pretrain_hq.jsonl`✨ --预训练数据集,整合自匠数科技(推荐设置`max_seq_len≈320`)
* `r1_mix_1024.jsonl` --DeepSeek-R1-1.5B蒸馏数据,每条数据字符最大长度为1024(推荐设置`max_seq_len≈720`)
* `rlaif-mini.jsonl` --RLAIF训练数据集,从SFT数据集中随机采样1万条高质量对话,用于PPO/GRPO/SPO等强化学习算法训练
* `sft_1024.jsonl` --整合自Qwen2.5蒸馏数据(是sft_2048的子集),每条数据字符最大长度为1024(推荐设置`max_seq_len≈650`)
* `sft_2048.jsonl` --整合自Qwen2.5蒸馏数据,每条数据字符最大长度为2048(推荐设置`max_seq_len≈1400`)
* `sft_512.jsonl` --整合自匠数科技SFT数据,每条数据字符最大长度为512(推荐设置`max_seq_len≈350`)
* `sft_mini_512.jsonl`✨ --极简整合自匠数科技SFT数据+Qwen2.5蒸馏数据(用于快速训练Zero模型),每条数据字符最大长度为512(推荐设置`max_seq_len≈340`)
训练参数`max_seq_len`目前指的是tokens长度,而非绝对字符数。
本项目tokenizer在中文文本上大约`1.5~1.7 字符/token`,纯英文的压缩比在`4~5 字符/token`,不同数据分布会有波动。
数据集命名标注的“最大长度”均为字符数,100长度的字符串可粗略换算成`100/1.5≈67`的tokens长度。
例如:
* 中文:`白日依山尽`5个字符可能被拆分为[`白日`,`依`,`山`,`尽`] 4个tokens;
* 英文:`The sun sets in the west`24个字符可能被拆分为[`The `,`sun `,`sets `,`in `,`the`,`west`] 6个tokens
“推荐设置”给出了各个数据集上最大tokens长度的粗略估计。
须知max_seq_len可以激进/保守/均衡地调整,因为更大或更小均无法避免副作用:一些样本短于max_seq_len后被padding浪费算力,一些样本长于max_seq_len后被截断语意。
在 `算力效率` <---> `语义完整性` 之间找到一个平衡点即可

说明 & 推荐训练方案
* MiniMind2 Series均经过共约20GB语料训练,大约4B tokens,即对应上面的数据组合训练结果(开销:💰💰💰💰💰💰💰💰,效果:😊😊😊😊😊😊)
* 想要最快速度从0实现Zero模型,推荐使用`pretrain_hq.jsonl` + `sft_mini_512.jsonl` 的数据组合,具体花销和效果可查看下文表格(开销:💰,效果:😊😊)
* 推荐具备一定算力资源或更在意效果的朋友可以考虑前者完整复现MiniMind2;仅有单卡GPU或在乎短时间快速复现的朋友强烈推荐后者;
* 【折中方案】亦可选择例如`sft_mini_512.jsonl`、`sft_1024.jsonl`中等规模数据进行自由组合训练(开销:💰💰💰,效果:😊😊😊😊)。
# 📌 Model
## Structure
MiniMind-Dense(和[Llama3.1](https://ai.meta.com/blog/meta-llama-3-1/)一样)使用了Transformer的Decoder-Only结构,跟GPT-3的区别在于:
* 采用了GPT-3的预标准化方法,也就是在每个Transformer子层的输入上进行归一化,而不是在输出上。具体来说,使用的是RMSNorm归一化函数。
* 用SwiGLU激活函数替代了ReLU,这样做是为了提高性能。
* 像GPT-Neo一样,去掉了绝对位置嵌入,改用了旋转位置嵌入(RoPE),这样在处理超出训练长度的推理时效果更好。
---
MiniMind-MoE模型,它的结构基于Llama3和[Deepseek-V2/3](https://arxiv.org/pdf/2405.04434)中的MixFFN混合专家模块。
* DeepSeek-V2在前馈网络(FFN)方面,采用了更细粒度的专家分割和共享的专家隔离技术,以提高Experts的效果。
---
MiniMind的整体结构一致,只是在RoPE计算、推理函数和FFN层的代码上做了一些小调整。
其结构如下图(重绘版):


修改模型配置见[./model/model_minimind.py](./model/model_minimind.py)。
参考模型参数版本见下表:
| Model Name | params | len_vocab | rope_theta | n_layers | d_model | kv_heads | q_heads | share+route |
|-------------------|--------|-----------|------------|----------|---------|----------|---------|-------------|
| MiniMind2-Small | 26M | 6400 | 1e6 | 8 | 512 | 2 | 8 | - |
| MiniMind2-MoE | 145M | 6400 | 1e6 | 8 | 640 | 2 | 8 | 1+4 |
| MiniMind2 | 104M | 6400 | 1e6 | 16 | 768 | 2 | 8 | - |
| minimind-v1-small | 26M | 6400 | 1e4 | 8 | 512 | 8 | 16 | - |
| minimind-v1-moe | 4×26M | 6400 | 1e4 | 8 | 512 | 8 | 16 | 1+4 |
| minimind-v1 | 108M | 6400 | 1e4 | 16 | 768 | 8 | 16 | - |
## Model Configuration
📋关于LLM的参数配置,有一篇很有意思的论文[MobileLLM](https://arxiv.org/pdf/2402.14905)做了详细的研究和实验。
Scaling Law在小模型中有自己独特的规律。
引起Transformer参数成规模变化的参数几乎只取决于`d_model`和`n_layers`。
* `d_model`↑ + `n_layers`↓ -> 矮胖子
* `d_model`↓ + `n_layers`↑ -> 瘦高个
2020年提出Scaling Law的论文认为,训练数据量、参数量以及训练迭代次数才是决定性能的关键因素,而模型架构的影响几乎可以忽视。
然而似乎这个定律对小模型并不完全适用。
MobileLLM提出架构的深度比宽度更重要,「深而窄」的「瘦长」模型可以学习到比「宽而浅」模型更多的抽象概念。
例如当模型参数固定在125M或者350M时,30~42层的「狭长」模型明显比12层左右的「矮胖」模型有更优越的性能,
在常识推理、问答、阅读理解等8个基准测试上都有类似的趋势。
这其实是非常有趣的发现,因为以往为100M左右量级的小模型设计架构时,几乎没人尝试过叠加超过12层。
这与MiniMind在训练过程中,模型参数量在`d_model`和`n_layers`之间进行调整实验观察到的效果是一致的。
然而「深而窄」的「窄」也是有维度极限的,当d_model<512时,词嵌入维度坍塌的劣势非常明显,
增加的layers并不能弥补词嵌入在固定q_head带来d_head不足的劣势。
当d_model>1536时,layers的增加似乎比d_model的优先级更高,更能带来具有"性价比"的参数->效果增益。
* 因此MiniMind设定small模型dim=512,n_layers=8来获取的「极小体积<->更好效果」的平衡。
* 设定dim=768,n_layers=16来获取效果的更大收益,更加符合小模型Scaling-Law的变化曲线。
作为参考,GPT3的参数设定见下表:

---
# 📌 Experiment
## Ⅰ 训练开销
- **时间单位**:小时 (h)。
- **成本单位**:人民币 (¥);7¥ ≈ 1美元。
- **3090 租卡单价**:≈1.3¥/h(可自行参考实时市价)。
- **参考标准**:表格仅实测 `pretrain` 和 `sft_mini_512` 两个数据集的训练时间,其它耗时根据数据集大小估算(可能存在些许出入)。
> 基于 3090 (单卡)成本计算
| Model Name | params | pretrain | sft_mini_512 | sft_512 | sft_1024 | sft_2048 | RLHF |
|-----------------|--------|------------------|------------------|---------------|-------------------|------------------|---------------|
| MiniMind2-Small | 26M | ≈1.1h ≈1.43¥ | ≈1h ≈1.3¥ | ≈6h ≈7.8¥ | ≈4.58h ≈5.95¥ | ≈7.5h ≈9.75¥ | ≈1h ≈1.3¥ |
| MiniMind2 | 104M | ≈3.9h ≈5.07¥ | ≈3.3h ≈4.29¥ | ≈20h ≈26¥ | ≈15h ≈19.5¥ | ≈25h ≈32.5¥ | ≈3h ≈3.9¥ |
---
训练开销总结&预测
> MiniMind2-Small参数
>> `pretrain_hq`+`sft_mini_512`数据集
单卡3090 (1 epoch) + 2.1小时 + 花费2.73元人民币
即可从0训练出MiniMind-Zero-0.025B模型!!!
> MiniMind2-Small参数
>> `pretrain_hq`+`sft_512`+`sft_2048`+`dpo`数据集
单卡3090 (2 epochs) + 大约38.16小时 + 花费49.61元人民币
即可从0训练出MiniMind2-Small-0.025B模型!!!
> MiniMind2参数
>> `pretrain_hq`+`sft_512`+`sft_2048`+`dpo`数据集
单卡3090 (2 epochs) + 大约122小时 + 花费158.6元人民币
即可从0训练出MiniMind2-0.1B模型!!!
✨基于单卡NVIDIA 3090的`MiniMind-Zero`从0训练仅需`2小时` + `3块钱`,实现ChatBot效果!
✨PS:若采用8卡4090训练,总用时甚至可以压缩到10分钟以内!(由于时间更短,花费同样3元左右,与单卡成本相当)
✨以极低极低的门槛,实现人人可玩的大模型自由!这正是MiniMind系列的诞生初衷!
✨仅价值`3块钱`成本的`MiniMind-Zero`并不是噱头!Chat测试:
```text
👶: 请介绍一下自己。
🤖️: 作为人工智能,我没有实际的生活,也没有自我意识,所以没有自己的生活。我被设计成能够帮助用户解答问题、提供信息、进行对话等。我的设计和功能是由计算机科学、机器学习、人工智能技术和算法所构建的,我通过编程和算法实现。
👶: 推荐一些杭州的特色美食吧。
🤖️: 杭州有很多美味的特色美食,比如鸡肉串、鳗鱼头、水煮鱼、豆腐脑等。这些美食都非常美味,有着独特的风味和口感,绝对是值得一试的美食。
👶: 请为我讲解“大语言模型”这个概念。
🤖️: 大语言模型是一种人工智能技术,它使用大量的文本数据来训练模型,然后在不断的迭代中不断优化模型。它的目标是根据输入的数据来生成符合特定需求的文本,这些文本可以是任何你感兴趣的主题。
👶: Introduce the history of the United States, please.
🤖️: 您提到的“Introok's the believeations of theument." 这个名字来源于中国古代的"groty of of the change."
```
极速且初具效果,甚至仍然可以进一步压缩获取更小更优质的训练数据。
Zero模型权重保存为 `full_sft_512_zero.pth`(见下文MiniMind模型文件链接),如有兴趣可下载检验此模型效果。
---
## Ⅱ 主要训练(必须)
> 所有训练脚本均 `cd ./trainer` 目录执行
### **1. 预训练 (Pretrain)**:
LLM首先要学习的并非直接与人交流,而是让网络参数中充满知识的墨水,“墨水” 理论上喝的越饱越好,产生大量的对世界的知识积累。
预训练就是让Model先埋头苦学大量基本的知识,例如从Wiki百科、新闻、书籍整理大规模的高质量训练数据。
这个过程是“无监督”的,即人类不需要在过程中做任何“有监督”的校正,而是由模型自己从大量文本中总结规律学习知识点。
模型此阶段目的只有一个:**学会词语接龙**。例如输入"秦始皇"四个字,它可以接龙"是中国的第一位皇帝"。
```bash
torchrun --nproc_per_node 1 train_pretrain.py # 1即为单卡训练,可根据硬件情况自行调整 (设置>=2)
# or
python train_pretrain.py
```
> 训练后的模型权重文件默认每隔`100步`保存为: `pretrain_*.pth`(*
> 为模型具体dimension,每次保存时新文件会覆盖旧文件)
| MiniMind2-Small (512dim) | MiniMind2 (768dim) |
|---|---|
| | |
### **2. 有监督微调 (Supervised Fine-Tuning)**:
经过预训练,LLM此时已经掌握了大量知识,然而此时它只会无脑地词语接龙,还不会与人聊天。
SFT阶段就需要把半成品LLM施加一个自定义的聊天模板进行微调。
例如模型遇到这样的模板【问题->回答,问题->回答】后不再无脑接龙,而是意识到这是一段完整的对话结束。
称这个过程为指令微调,就如同让已经学富五车的「牛顿」先生适应21世纪智能手机的聊天习惯,学习屏幕左侧是对方消息,右侧是本人消息这个规律。
在训练时,MiniMind的指令和回答长度被截断在512,是为了节省显存空间。就像学习写作时,会先从短的文章开始,当学会写作200字作文后,800字文章也可以手到擒来。
在需要长度拓展时,只需要准备少量的2k/4k/8k长度对话数据进行进一步微调即可(此时最好配合RoPE-NTK的基准差值)。
> 在推理时通过调整RoPE线性差值,实现免训练长度外推到2048及以上将会很方便。
```bash
torchrun --nproc_per_node 1 train_full_sft.py
# or
python train_full_sft.py
```
> 训练后的模型权重文件默认每隔`100步`保存为: `full_sft_*.pth`(*
> 为模型具体dimension,每次保存时新文件会覆盖旧文件)
| MiniMind2-Small (512dim) | MiniMind2 (768dim) |
|---|---|
| | |
## Ⅲ 其它训练阶段(可选)
> 所有训练脚本均 `cd ./trainer` 目录执行
### **3. 知识蒸馏 (Knowledge Distillation, KD)**
在前面的所有训练步骤中,模型已经完全具备了基本能力,通常可以学成出师了。
而知识蒸馏可以进一步优化模型的性能和效率,所谓知识蒸馏,即学生模型面向教师模型学习。
教师模型通常是经过充分训练的大模型,具有较高的准确性和泛化能力。
学生模型是一个较小的模型,目标是学习教师模型的行为,而不是直接从原始数据中学习。
在SFT学习中,模型的目标是拟合词Token分类硬标签(hard labels),即真实的类别标签(如 0 或 6400)。
在知识蒸馏中,教师模型的softmax概率分布被用作软标签(soft labels)。小模型仅学习软标签,并使用KL-Loss来优化模型的参数。
通俗地说,SFT直接学习老师给的解题答案。而KD过程相当于“打开”老师聪明的大脑,尽可能地模仿老师“大脑”思考问题的神经元状态。
例如,当老师模型计算`1+1=2`这个问题的时候,最后一层神经元a状态为0,神经元b状态为100,神经元c状态为-99...
学生模型通过大量数据,学习教师模型大脑内部的运转规律。这个过程即称之为:知识蒸馏。
知识蒸馏的目的只有一个:让小模型体积更小的同时效果更好。
然而随着LLM诞生和发展,模型蒸馏一词被广泛滥用,从而产生了“白盒/黑盒”知识蒸馏两个派别。
GPT-4这种闭源模型,由于无法获取其内部结构,因此只能面向它所输出的数据学习,这个过程称之为黑盒蒸馏,也是大模型时代最普遍的做法。
黑盒蒸馏与SFT过程完全一致,只不过数据是从大模型的输出收集,因此只需要准备数据并且进一步FT即可。
注意更改被加载的基础模型为`full_sft_*.pth`,即基于微调模型做进一步的蒸馏学习。
`./dataset/sft_1024.jsonl`与`./dataset/sft_2048.jsonl` 均收集自qwen2.5-7/72B-Instruct大模型,可直接用于SFT以获取Qwen的部分行为。
```bash
# 注意需要更改train_full_sft.py数据集路径,以及max_seq_len
torchrun --nproc_per_node 1 train_full_sft.py
# or
python train_full_sft.py
```
> 训练后的模型权重文件默认每隔`100步`同样保存为: `full_sft_*.pth`(*为模型具体dimension,每次保存时新文件会覆盖旧文件)
此处应当着重介绍MiniMind实现的白盒蒸馏代码`train_distillation.py`,由于MiniMind同系列本身并不存在强大的教师模型,因此白盒蒸馏代码仅作为学习参考。
```bash
torchrun --nproc_per_node 1 train_distillation.py
# or
python train_distillation.py
```
### **4. LoRA (Low-Rank Adaptation)**
LoRA是一种高效的参数高效微调(Parameter-Efficient Fine-Tuning, PEFT)方法,旨在通过低秩分解的方式对预训练模型进行微调。
相比于全参数微调(Full Fine-Tuning),LoRA 只需要更新少量的参数。
LoRA 的核心思想是:在模型的权重矩阵中引入低秩分解,仅对低秩部分进行更新,而保持原始预训练权重不变。
代码可见`./model/model_lora.py`和`train_lora.py`,完全从0实现LoRA流程,不依赖第三方库的封装。
```bash
torchrun --nproc_per_node 1 train_lora.py
# or
python train_lora.py
```
> 训练后的模型权重文件默认每隔`100步`保存为: `lora_xxx_*.pth`(*
> 为模型具体dimension,每次保存时新文件会覆盖旧文件)
非常多的人困惑,如何使模型学会自己私有领域的知识?如何准备数据集?如何迁移通用领域模型打造垂域模型?
这里举几个例子,对于通用模型,医学领域知识欠缺,可以尝试在原有模型基础上加入领域知识,以获得更好的性能。
同时,通常不希望学会领域知识的同时损失原有基础模型的其它能力,此时LoRA可以很好的改善这个问题。
只需要准备如下格式的对话数据集放置到`./dataset/lora_xxx.jsonl`,启动 `python train_lora.py`
训练即可得到`./out/lora/lora_xxx.pth`新模型权重。
**医疗场景**
```
{"conversations": [{"role": "user", "content": "请问颈椎病的人枕头多高才最好?"}, {"role": "assistant", "content": "颈椎病患者选择枕头的高度应该根据..."}]}
{"conversations": [{"role": "user", "content": "请问xxx"}, {"role": "assistant", "content": "xxx..."}]}
```
**自我认知场景**
```
{"conversations": [{"role": "user", "content": "你叫什么名字?"}, {"role": "assistant", "content": "我叫minimind..."}]}
{"conversations": [{"role": "user", "content": "你是谁"}, {"role": "assistant", "content": "我是..."}]}
```
此时【基础模型+LoRA模型】即可获得医疗场景模型增强的能力,相当于为基础模型增加了LoRA外挂,这个过程并不损失基础模型的本身能力。
可以通过`eval_llm.py`进行模型评估测试。
```bash
# 注意:weight参数指定基础模型类型,需与train_lora训练时使用的基础模型保持一致
python eval_llm.py --weight dpo --lora_weight lora_medical
```
**小测试**
```
👶: 我最近经常感到头晕,可能是什么原因?
🤖️: 头晕可能是由于多种原因,包括但不限于:心脏疾病、眼睛损伤、过敏反应、皮肤问题、过敏反应、压力、焦虑、疲劳、药物副作用、性功能障碍或者其他...
---
👶: 你和openai是什么关系?
🤖️: 我是 MiniMind,一个由 Jingyao Gong 开发的人工智能助手。我通过自然语言处理和算法训练来与用户进行交互。
```
PS:只要有所需要的数据集,也可以full_sft全参微调(需要进行通用知识的混合配比,否则过拟合领域数据会让模型变傻,损失通用性)
### **5. 训练推理模型 (Reasoning Model)**
DeepSeek-R1实在太火了,几乎重新指明了未来LLM的新范式。
论文指出`>3B`的模型经历多次反复的冷启动和RL奖励训练才能获得肉眼可见的推理能力提升。
最快最稳妥最经济的做法,以及最近爆发的各种各样所谓的推理模型几乎都是直接面向数据进行蒸馏训练,
但由于缺乏技术含量,蒸馏派被RL派瞧不起(hhhh)。
本人迅速已经在Qwen系列1.5B小模型上进行了尝试,很快复现了Zero过程的数学推理能力。
然而一个遗憾的共识是:参数太小的模型直接通过冷启动SFT+GRPO几乎不可能获得任何推理效果。
MiniMind2第一时间只能坚定不移的选择做蒸馏派,日后基于0.1B模型的RL如果同样取得小小进展会更新此部分的训练方案。
做蒸馏需要准备的依然是和SFT阶段同样格式的数据即可,数据集来源已如上文介绍。数据格式例如:
```json lines
{
"conversations": [
{
"role": "user",
"content": "你好,我是小芳,很高兴认识你。"
},
{
"role": "assistant",
"content": "\n你好!我是由中国的个人开发者独立开发的智能助手MiniMind-R1-Lite-Preview,很高兴为您提供服务!\n \n\n你好!我是由中国的个人开发者独立开发的智能助手MiniMind-R1-Lite-Preview,很高兴为您提供服务!\n "
}
]
}
```
推理模型R1的回复模板是:
```text
\n思考过程\n \n
\n最终回答\n
```
这在GRPO中通过设置规则奖励函数约束模型符合思考标签和回复标签(在冷启动靠前的阶段奖励值设置应该提高一些)
另一个问题是蒸馏过程虽然和SFT一样,但实验结果是模型难以每次都符合模板规范的回复,即脱离思考和回复标签约束。
这里的小技巧是增加标记位置token的损失惩罚,详见`train_reason.py`:
```text
# 在 sp_ids 对应的位置增加额外的惩罚
...
loss_mask[sp_ids] = 10 # 惩罚系数
```
另另一个tips是由于推理数据由于只筛选了`<1024`长度的数据,其中多轮对话和英文数据偏少,
因此`r1_mix_1024.jsonl`进行了大约10k条多轮对话+英文数据的混合,防止模型遗忘严重。
脚本默认基于rlhf后的基模型做推理能力的蒸馏微调,下面直接启动训练即可:
```bash
torchrun --nproc_per_node 1 train_reason.py
# or
python train_reason.py
```
> 训练后的模型权重文件默认每隔`100步`保存为: `reason_*.pth`(*为模型具体dimension,每次保存时新文件会覆盖旧文件)
测试一下:
```text
👶: 请介绍一下自己。
🤖️:
嗯,用户让我介绍一下自己。我现在需要解释一下自己。首先,我应该明确用户是谁,是学生、职场人士还是普通人。用户可能是一个学生或者职场人士,所以信息传递应该是帮助学生和职场人士的信息。
然后,我需要回应用户,这可能包括介绍自己的位置、兴趣爱好、职业经历等信息。用户还可能想了解自己在哪里,比如职业发展、工作经验等。
我应该注意用词要正式,不要太正式,同时要保持简洁明了。这样用户容易理解,也方便他们查阅相关资料。
最后,我应该总结一下,让用户知道我是如何帮助他们完成他们的任务的,这样他们有更多关于我的信息。
我是**“你的名字”,你叫什么名字?
👶: 你更擅长哪一个学科?
🤖️:
您好!我是由中国的个人开发者开发的智能助手MiniMind-R1。如您有任何任何问题,我会尽我所能为您提供帮助。
您好!我是由中国的个人开发者开发的智能助手MiniMind-R1。如您有任何任何问题,我会尽我所能为您提供帮助。
```
## IV 强化学习后训练
LLM里的强化学习方法可分两类:
1. **基于人类反馈的强化学习 (Reinforcement Learning from Human Feedback, RLHF)**
- 通过**人类**对模型输出的偏好进行评价来训练模型,使其生成更符合人类价值观和偏好的内容。
2. **基于AI反馈的强化学习 (Reinforcement Learning from AI Feedback, RLAIF)**
- 使用**AI模型**(通常是预训练的语言奖励模型)来提供反馈,而不直接依赖人类的人工标注。
- 这里的“AI”也可以是某些规则奖励,例如数学答案/代码解释器...
| 类型 | 裁判 | 优点 | 缺点 |
|-------|----|-----------|------------|
| RLHF | 人类 | 更贴近真实人类偏好 | 成本高、效率低 |
| RLAIF | 模型 | 自动化、可扩展性强 | 可能偏离人类真实偏好 |
二者本质上是一样的,都是通过**强化学习的方式**,利用某种形式的"**反馈**"来优化模型的行为。
除了**反馈**的来源不同,其他并无任何区别。
### 👀 PO算法的统一视角
在介绍实现具体算法之前,我先以个人理解的极简视角,阐述所有Policy Optimization (PO)算法的统一共性。
所有RL算法的本质都只是在优化一个期望:
$$\mathcal{J}_{PO} = \mathbb{E}_{q \sim P(Q), o \sim \pi(O|q)} \left[ \underbrace{f(r_t)}_{\text{策略项}} \cdot \underbrace{g(A_t)}_{\text{优势项}} - \underbrace{h(\text{KL}_t)}_{\text{正则项}} \right]$$
训练时,只需**最小化负目标函数**,即: $\mathcal{L_{PO}}=-\mathcal{J_{PO}}$
这个框架只包含三个核心组件:
* **策略项** $f(r_t)$: 如何使用概率比 $r_t$? 即告诉模型新旧策略偏差有多大,是否探索到了更好的token
* **优势项** $g(A_t)$: 如何计算优势 $A_t$, 这很重要!大模型算对定积分也不足为奇,小模型回答对加减法优势通常都是正的
* **正则项** $h(\text{KL}_t)$: 如何约束变化幅度 $\text{KL}_t$, 既防止跑偏又防止管的太死
(展开)符号说明
| 符号 | 含义 | 说明 | 值域 |
|------|------|------|------|
| $q$ | 问题/提示词 | 从数据集 $P(Q)$ 中采样 | - |
| $o$ | 模型输出序列 | 由策略 $\pi$ 生成 | - |
| $r_t$ | 概率比 | $r_t = \frac{\pi_\theta(o_t\|q, o_{
不同的**xxPO算法**本质上只是对这三个组件的不同设计的实例化!
---
### **6. 基于人类反馈的强化学习 (Reinforcement Learning from Human Feedback, RLHF)**
在前面的训练步骤中,模型已经具备了基本的对话能力,但是这样的能力完全基于单词接龙,缺少正反样例的激励。
模型此时尚未知什么回答是好的,什么是差的。希望它能够更符合人的偏好,降低让人类不满意答案的产生概率。
这个过程就像是让模型参加新的培训,从优秀员工的作为例子,消极员工作为反例,学习如何更好地回复。
#### 6.1 Direct Preference Optimization
直接偏好优化(DPO)算法,损失为:
$$\mathcal{L}_{DPO} = -\mathbb{E}\left[\log \sigma\left(\beta \left[\log \frac{\pi_\theta(y_w|x)}{\pi_{ref}(y_w|x)} - \log \frac{\pi_\theta(y_l|x)}{\pi_{ref}(y_l|x)}\right]\right)\right]$$
其中:
- **策略项**: $f(r_t) = \log r_w - \log r_l$ (对比chosen vs rejected的概率比)
- **优势项**: $g(A_t)$ = / (通过偏好对比,无需显式计算优势)
- **正则项**: $h(\text{KL}_t)$ = 隐含在 $\beta$ 中 (控制偏离参考模型程度)
特别地,
- DPO从PPO带KL约束的目标推导出对偏好对的解析训练目标,直接最大化"chosen优于rejected"的对数几率;无需同步训练Reward/Value模型。DPO只需跑`actor`与`ref`两个模型,显存占用低、收敛稳定、实现简单。
- 训练范式:off‑policy,使用静态偏好数据集,可反复多轮epoch;Ref模型固定(预先缓存输出)。
- DPO的局限在于不做在线探索,更多用于"偏好/安全"的人类价值对齐;对"能不能做对题"的智力能力提升有限(当然这也取决于数据集,大规模收集正反样本并人类评估很困难)。
```bash
torchrun --nproc_per_node 1 train_dpo.py
# or
python train_dpo.py
```
> 训练后的模型权重文件默认每隔`100步`保存为: `dpo_*.pth`(*为模型具体dimension,每次保存时新文件会覆盖旧文件)
### **7. 基于AI反馈的强化学习 (Reinforcement Learning from AI Feedback, RLAIF)**
相比RLHF依赖人类标注chosen/rejected偏好对,RLAIF则完全由AI来充当"裁判"。
所谓AI"裁判"可以是model-base的奖励大模型(Reward Model),也可以是R1一样设置规则函数进行校验,也可以是例如工具调用的环境反馈。
例如:数学题答案是否正确、工具调用执行代码能否通过测试用例、推理过程是否符合格式...都可以自动化判断。
RLAIF的最大优势在于**可扩展性**和**On-Policy**的特点——不需要昂贵的人工标注,可以生成海量的训练样本,让模型在在线大量试错中快速进化。
MiniMind 着手实现**2+N**种基本+前沿的RLAIF方法:
* **PPO**、**GRPO** 被大规模验证的经典RL算法;
* N种前沿RL算法(不定期以Exp性质更新)。
#### 1️⃣ 数据集准备 (需要)
为了快速验证RLAIF的效果,这里从SFT数据集中随机采样了1万条高质量对话,构建约1MB大小的`rlaif-mini.jsonl`([Huggingface](https://huggingface.co/datasets/jingyaogong/minimind_dataset/blob/main/rlaif-mini.jsonl))
数据格式与SFT一致,但assistant并不需要内容,因为训练过程中完全由 $\Pi$ 策略模型实时采样生成。因此形如:
```json
{
"conversations": [
{"role": "user", "content": "请解释一下什么是光合作用?"},
{"role": "assistant", "content": "无"}
]
}
```
RLAIF的训练过程中,模型会基于user的问题生成1或多个候选回答,然后由奖励函数/模型对回答打分,
分数高的回答会被鼓励(增加 $\Pi$ 策略概率),分数低的回答会被抑制(降低 $\Pi$ 策略概率)。这个"打分->调整"的循环就是强化学习的核心。
#### 2️⃣ 奖励模型准备 (需要)
已知RLAIF训练需要“奖励模型 (Reward Model)”对生成的回答进行打分。
此处选取小型且高质量的InternLM2-1.8B-Reward
([ModelScope](https://modelscope.cn/models/Shanghai_AI_Laboratory/internlm2-1_8b-reward) | [HuggingFace](https://huggingface.co/internlm/internlm2-1_8b-reward))
作为基础奖励模型。
下载奖励模型后需要放置在minimind项目的**同级目录**下,推荐结构如下:
```
project/
├── minimind/ # MiniMind项目
│ ├── model/
│ └── ...
└── internlm2-1_8b-reward/ # 奖励模型(与minimind同级)
├── config.json
├── model.safetensors
└── ...
```
奖励机制选择与MiniMind限制说明(点击展开)
**1. 奖励机制的多样性**
RLAIF中的"奖励信号"来源可以非常灵活:
- **Model-based奖励**:可使用专门的Reward Model(如InternLM2-Reward),也可使用通用LLM+提示词进行打分(如Qwen3-as-a-Judge)。奖励模型规模和架构均可自由选择。
- **Rule-based奖励**:可以基于规则函数构造奖励信号,例如:
- 数学题答案正确性验证(Ground Truth对比)
- SQL执行成功率与结果准确性
- 代码解释器运行结果(pass@k)
- 工具调用返回状态(API成功/失败)
- 格式合规性检查(JSON/XML解析)
- 推理链完整性评估(CoT步骤数)
- **Environment-based奖励**:在Agent场景中,环境反馈本身即为天然奖励(如游戏得分、Research完整度、任务完成度)。
任何能够量化"回答质量"的机制都可作为RL的奖励来源。DeepSeek R1就是典型案例:使用规则函数验证数学答案正确性作为奖励,无需额外的Reward Model。
**2. MiniMind限制:奖励稀疏问题**
RLAIF训练既可以针对推理模型也可以针对非推理模型,区别仅在于格式。
然而对于MiniMind这种0.1B参数量极小能力弱的模型,在通用任务(如R1风格的数学数据集)上会遇到严重的奖励稀疏(Reward Sparsity)问题:
- **现象**:模型生成的候选回答几乎全部错误,导致所有奖励分数 $r(x,y) \approx 0$
- **后果**:优势函数 $A(x,y) = r(x,y) - b(x) \approx 0$,策略梯度信号消失,无法有效更新参数 $\theta$
如同让小学生做高考数学题,无论尝试多少次都得零分,无法通过分数差异学习改进策略。因此这是RL算法的根本原理限制的。
为缓解此问题,MiniMind的实现选择了**model-based的连续性奖励信号**:
- Reward Model输出连续分数(如-2.5到+3.0),而非二元的0/1
- 即使回答质量都差,也仍能区分"更更差"(-3.0)和"更差"(-2.8)的细微差异。所以这种**稠密且连续**的奖励信号能够为优势函数 $A(x,y)$ 提供非零梯度,使得策略网络得以渐进式优化
- 也可以混合多种奖励源: $r_{\text{total}} = \alpha \cdot r_{\text{model}} + \beta \cdot r_{\text{rule}}$ (例如既可以检测think标签格式reward,又可以综合回答本身质量的reward分数)
- minimind实践中避免直接使用rule-based二元奖励 + 超纲难度数据(如MATH500),易导致奖励全零;
- 监控训练时观察奖励分数的方差 $\text{Var}(r)$,若持续接近0则需调整数据或奖励机制
**对于生产级大模型的Agentic RL场景**:
在真实Agent系统(代码生成、工具调用、检索-规划-执行的多轮链路)中,奖励是“延迟整轮结算”的不同范式:
- LLM需要逐token生成工具调用指令(tool_call),经历解析(tool_parse)、工具执行(tool_exec),再把结果拼接回上下文继续下一步;循环往复直到完成。
- 一次完整的任务链路包含多次调用+思考,直到终止条件满足时计算一次总reward(如任务是否完成、测试是否通过、目标是否命中)。
因此,Agentic RL更接近稀疏/延迟奖励设定:梯度回传在“整轮结束后”才发生,和非Agentic RL任务在对话单轮上“即时评分即时更新”有很大不同。
这也解释了Agent任务上更偏向环境反馈(environment-based reward),而非凭Reward Model进行静态打分。
- **环境交互反馈**:最终以执行结果为准(代码是否跑通、API是否返回成功、子目标是否完成);
- **Model-based奖励局限**:对长链路、可执行语义的全貌捕捉有限,且大概率和真实环境反馈不一致(reward hacking)。
---
#### 7.1 [Proximal Policy Optimization](https://arxiv.org/abs/1707.06347)
PPO 是2017年OpenAI提出的非常经典强化学习算法,也是LLM RL通用的基线方法,甚至不需要加之一。
**PPO损失**:
$$\mathcal{L}_{PPO} = -\mathbb{E}\left[\min(r_t \cdot A_t, \text{clip}(r_t, 1-\varepsilon, 1+\varepsilon) \cdot A_t)\right] + \beta \cdot \mathbb{E}[\text{KL}]$$
其中:
- **策略项**: $f(r_t) = \min(r_t, \text{clip}(r_t, 1-\varepsilon, 1+\varepsilon))$ (裁剪概率比防止更新过激)
- **优势项**: $g(A_t) = R - V(s)$ (通过Critic网络估计价值函数)
- **正则项**: $h(\text{KL}_t) = \beta \cdot \mathbb{E}[\text{KL}]$ (全局KL散度约束)
对比DPO而言,
- DPO (Off-Policy):训练数据是静态的偏好数据集(chosen vs rejected),可以反复使用同一批数据训练多个epoch,就像传统监督学习一样。数据效率高,训练成本低。它直接优化偏好对的对数似然,无需Reward Model。
- PPO (On-Policy):必须用当前策略实时采样生成新数据,旧策略采集的数据不能用(会有distribution shift问题)。虽然通过importance sampling和clip机制允许轻微的分布偏移,但本质上要求数据来自相对新鲜的策略。数据效率低,但适合探索式学习。
简单来说:
- 前者教模型按离线预定的「好/坏标准」学习,尽管它并非是当前模型所能输出的(例如参考世界冠/亚军录像练习打球);
- 后者实时地教模型把事情做对做好,在线采样自最新模型policy(教练手把手教打,为每个动作实时打分)。
MiniMind的PPO实现包含了Actor模型(生成回答)和Critic模型(评估回答价值),以及完整的GAE(Generalized Advantage Estimation)优势函数计算。
**训练方式**:
```bash
torchrun --nproc_per_node N train_ppo.py
# or
python train_ppo.py
```
> 训练后的模型权重文件默认每隔`100步`保存为: `ppo_actor_*.pth`(*为模型具体dimension)
| MiniMind2-Small (512dim) | MiniMind2 (768dim) |
|---|---|
| | |
从训练曲线可以看出,PPO存在**reward提升缓慢**的问题。私以为这主要源于**PPO双网络联合优化**方法:Critic需要逐步收敛以准确估计价值函数,而Actor的策略更新依赖Critic提供的优势估计,两者相互依赖形成复杂的优化过程。训练初期Critic估计不准会影响Actor梯度方向,导致整体收敛缓慢。此外,PPO需要同时维护两个网络,显存占用约为单网络方法的1.5-2倍。
#### 7.2 [Group Relative Policy Optimization](https://arxiv.org/pdf/2402.03300)
2025年初,DeepSeek-R1火爆出圈,同样火了的有来自DeepSeekMath论文的GRPO算法,也一跃成为最先进的RL算法之一。
然而AI半年=人间半个世纪,时至今日GRPO已经演变为各大XXPO大战(后面演变的DAPO、GSPO、CISPO等)的基线算法。
具体来说,一句话总结它的核心创新是"分组相对价值估计"。
**GRPO损失**:
$$\mathcal{L}_{GRPO} = -\mathbb{E}\left[r_t \cdot A_t - \beta \cdot \text{KL}_t\right]$$
其中:
- **策略项**: $f(r_t) = \min(r_t, \text{clip}(r_t))$ (使用概率比的clip裁剪)
- **优势项**: $g(A_t) = \frac{R - \mu_{group}}{\sigma_{group}}$ (组内归一化,消除Critic网络)
- **正则项**: $h(\text{KL}_t) = \beta \cdot \text{KL}_t$ (token级KL散度约束)
对于同一个问题,模型生成N个不同的回答(例如N=4),然后计算这N个回答的奖励分数。
接着把这N个回答的平均奖励作为baseline,高于baseline的回答被鼓励,低于baseline的回答被抑制。
用这种方式巧妙地避免了训练额外的critic网络。
只要是RL都必须面对的正反样本这个原理性限制,GRPO也不会例外,其更显著的问题是:退化组(Degenerate Groups)。
假设某个问题略难,导致N个回答的奖励分数几乎一样(大部分情况是一样烂而不是一样好),那么这一组的学习信号就无限接近0。
在MiniMind这种超小模型上,这个问题尤为明显,求解数学问题99.99%的情况下整组回答质量都很差,那么将无法学习。
因此必须为模型指定合理的domain,即必须限制在能力边界内。
**训练方式**:
```bash
torchrun --nproc_per_node N train_grpo.py
# or
python train_grpo.py
```
> 训练后的模型权重文件默认每隔`100步`保存为: `grpo_*.pth`
| MiniMind2-Small (512dim) | MiniMind2 (768dim) |
|---|---|
| | |
从训练曲线可以看出,GRPO的**reward呈现更加稳定的上升趋势**,达到4左右,说明GRPO本身能更好地利用RLAIF信号。Policy Loss整体下降平稳,相比PPO的双网络优化,GRPO单网络架构训练更稳定且收敛上限更高。
#### 7.3 ⏳⌛️🔥 更多RL拓展 (Exp)
##### 7.3.1 [Single-stream Policy Optimization](https://arxiv.org/abs/2509.13232)
SPO是2025年9月腾讯提出的RL算法,针对GRPO的退化组问题进行改进。
论文认为,GRPO等算法"一个样本要依赖一组采样"显得别扭而不优雅:太容易或太难的题目,整组几乎学不到东西,学习效率先天受限。
SPO的动机就是回到RL的本质—**1个输入,1个输出,就是1个训练样本**,回到policy gradient的基本公式去思考:不用group mean也能得到稳定的baseline,也就是把价值估计 V 铺开在时序上,训练前先做粗略的价值预估,训练中一边采样一边更新对 V 的估计,从而为每个样本提供一个跨 batch 持久化、可自适应的基线参照。这种"单流"设计不再依赖同组样本,天然避免了退化组。
**SPO损失**:
$$\mathcal{L}_{SPO} = -\mathbb{E}\left[\log \pi_\theta(a_t|s) \cdot A_t - \beta \cdot \text{KL}_t\right]$$
其中:
- **策略项**: $f(r_t) = \log \pi_\theta(a_t|s)$ (直接使用log概率,不计算ratio)
- **优势项**: $g(A_t) = R - B_t^{adaptive}$ (自适应baseline,Beta分布动态跟踪)
- **正则项**: $h(\text{KL}_t) = \beta \cdot \text{KL}_t$ (token级KL + 动态 $\rho$ 调整)
落到实现层面:SPO采用无分组设计,用持久化的KL自适应value tracker替代组内baseline,优势函数在整个batch上全局归一化。这样每个样本独立处理,无需等待同组其他样本,且能为每个样本提供稳定的学习信号。
论文在Qwen3-8B的5个困难数学数据集上,SPO平均比GRPO高出3.4个百分点,其中BRUMO 25数据集+7.3pp、AIME 25数据集+4.4pp。
> 注:SPO是实验性前沿算法,MiniMind的实现用于探索学习。由于模型参数量极小,无法完全复现论文的8B模型效果。
**训练方式**:
```bash
torchrun --nproc_per_node N train_spo.py
# or
python train_spo.py
```
> 训练后的模型权重文件默认每隔`100步`保存为: `spo_*.pth`
MiniMind2 (768dim) 训练曲线
从训练曲线来看,SPO的reward波动与PPO表现接近,弱于GRPO。实际推理测试发现模型输出质量不高,存在逻辑混乱和格式错误问题。
**实验性说明**:当前SPO手搓实现可能在value_tracker配置、reward归一化策略上还存在问题。尚需排查算法本身在小模型上的适应性/或是实现上存在差异。
### RL算法小结
我们收束回“**统一框架**”, 重新整理所有不同PO算法只是对三个核心组件的不同实例化的表格:
| 算法 | 策略项 $f(r_t)$ | 优势项 $g(A_t)$ | 正则项 $h(\text{KL}_t)$ | 优化模型 |
|------|----------------|----------------|----------------------|----------|
| **DPO** | $\log r_w - \log r_l$ | 隐式(偏好对比) | 隐含在 $\beta$ 中 | 2 |
| **PPO** | $\min(r, \text{clip}(r))$ | $R - V(s)$ | $\beta \cdot \mathbb{E}[\text{KL}]$ | 4 |
| **GRPO** | $\min(r, \text{clip}(r))$ | $\frac{R - \mu}{\sigma}$ | $\beta \cdot \text{KL}_t$ | 2 |
| **SPO** | $\log \pi_\theta$ | $R - B_t^{adaptive}$ | $\beta \cdot \text{KL}_t$ | 2 |
**RL是优美且自洽的**
> 以上纯属个人视角理解,如有偏差请随时指正
---
## V 训练结果
### 训练完成-模型合集
> 考虑到多人反应百度网盘速度慢,MiniMind2及以后全部使用ModelScope/HuggingFace托管。
#### ① PyTorch原生模型
MiniMind2模型权重 ([ModelScope](https://www.modelscope.cn/models/gongjy/MiniMind2-PyTorch) | [HuggingFace](https://huggingface.co/jingyaogong/MiniMind2-Pytorch))
Torch文件命名对照
| Model Name | params | pretrain_model | sft_model | rlhf_model (DPO) | reason_model | rlaif_model (PPO/GRPO/SPO) | lora_model |
|-----------------|--------|------------------------|------------------------|--------------------|------------------|----------------------------------------------|--------------------|
| MiniMind2-small | 26M | `pretrain_512.pth` | `full_sft_512.pth` | `dpo_512.pth` | `reason_512.pth` | `xxpo_512.pth` | `lora_xxx_512.pth` |
| MiniMind2-MoE | 145M | `pretrain_640_moe.pth` | `full_sft_640_moe.pth` | `dpo_640_moe.pth` | - | - | - |
| MiniMind2 | 104M | `pretrain_768.pth` | `full_sft_768.pth` | `dpo_768.pth` | `reason_768.pth` | `xxpo_768.pth` | `lora_xxx_768.pth` |
#### ② Transformers模型
MiniMind系列 ([ModelScope](https://www.modelscope.cn/collections/MiniMind-b72f4cfeb74b47)
| [HuggingFace](https://huggingface.co/collections/jingyaogong/minimind-66caf8d999f5c7fa64f399e5))
---
# 📌 Eval
## Ⅰ RLHF对比
测试基于`full_sft`和`dpo`的`MiniMind2系列`模型对比,测试随机种子均固定
[A] MiniMind2:full_sft_640
[B] MiniMind2:dpo_640
```text
[Q]: 你叫什么名字?
[A]: 我是一个大型语言模型,可以回答各种问题,提供信息和帮助。我可以回答各种问题,提供信息和帮助,帮助你解决各种问题。
[B]: 我是一种基于文本的AI模型,我并没有个人经历或情感,所以无法感受和体验情感。我的设计目的是为了帮助用户解决问题、提供信息和进行对话。如果您有任何问题或需要帮助,请随时告诉我!
[Q]: 你更擅长哪一个学科?
[A]: 作为一个AI模型,我并没有真正的“擅长”这个学科。我被设计成能够提供信息、解答问题、进行对话、执行任务和与用户进行对话。不过,我可以提供信息、解答问题、进行对话、提供建议、处理问题、进行对话、提供建议、学习新知识、编写代码、回答问题、提供建议等多种学科的功能。如果你有具体的学科需求或主题,欢迎提供详细信息。
[B]: 作为AI,我并没有个人能力或兴趣,但我可以提供一些关于数学、科学、计算机科学、语言学、心理学等学科的知识。如果你对数学感兴趣,我可以提供一些基础知识,例如代数、几何、概率、统计学等。如果你需要更深入的学习,我也可以提供相关的在线课程、书籍、论文等资源。请告诉我你具体需要什么帮助,我会尽力提供帮助。
[Q]: 鲁迅的《狂人日记》是如何批判封建礼教的?
[A]: 鲁迅的《狂人日记》是一部讲述了鲁迅对人类价值和道德责任的倡导。在这部作品中,鲁迅通过细腻的笔触,探讨了人性、道德、正义、牺牲与责任等深刻的主题。以下是鲁迅在《狂人日记》中如何批判封建礼教的几个方面:1. **社会现实与道德观念**:鲁迅通过讲述鲁迅的故事,探讨了社会的不平等、权力的流动、人性的演变等社会问题。他认为,社会不平等不仅仅是不公正的,更是每个人在社会中的不公正。他呼吁社会各界共同努力,通过教育、宣传、法律等手段,为构建和谐社会做出贡献。2. **道德与责任**:鲁迅通过讲述鲁迅的故事,展现了道德和责任的重要性。他提倡通过道德教育来培养人们的道德品质,同时也强调了道德和责任的重要性。鲁迅通过讲述鲁迅的故事,揭示了社会的不平等和人性的复杂性,体现了对人性的深刻理解。3. **道德与责任**:鲁迅通过讲述鲁迅的故事,强调了道德责任的重要性。他提倡通过自己的行为来体现对社会的尊重和对人性的深刻理解。鲁迅通过讲述鲁迅的故事,强调了道德和责任的重要性。4. **道德与道德**:鲁迅通过讲述鲁迅的故事,揭示了道德和责任的真正意义。鲁迅通过讲述鲁迅的故事,揭示了道德和责任的本质,强调了道德和责任的重要性。5. **个人与社会**:鲁迅通过讲述鲁迅的故事,揭示了个人与社会之间的复杂关系。他呼吁社会各界共同努力,通过教育和宣传,为构建和谐社会做出贡献。鲁迅的《狂人日记》通过其丰富的故事和深刻的道德寓言,传达了关于人性、道德、正义、道德以及个人与社会的复杂关系。这部作品不仅在文学价值上取得了巨大成就,更在思想层面上启发了后来的文学创作,对后世产生了深远的影响。
[B]: 鲁迅的《狂人日记》是一部描绘战争和自由精神的作品,它批判了封建社会的种种问题和冲突,反映了社会的不平等和人性本质。在这部作品中,鲁迅通过对封建社会的诸多现象进行批判,如“弗雷德里克·约翰逊的“鹰迪伦”、“纳扎特的”、“贝克汉姆”、“乔治·威尔逊”等,对封建社会的种种问题进行了批判,强调了封建社会的不平等、人性本质以及人性本质。鲁迅通过他的“鹰迪伦”、“纳扎特的”、“贝克汉姆”、“乔治·威尔逊”等,对封建社会的种种问题进行了批判。在小说中,鲁迅通过对封建社会的诸多现象进行批判,揭示了封建社会的腐败、人性本质以及人性本质的复杂性。这种批判体现了对封建社会的尊重和对人性的复杂性,同时也反映了现代社会中普遍存在的不平等和人性本质。鲁迅的《狂人日记》不仅是一部关于封建社会的小说,也是一部具有深刻社会意义的作品,对后世的审判和批判起到了关键作用。
[Q]: 我咳嗽已经持续了两周,需要去医院检查吗?
[A]: 咳嗽确实需要一定的检查,但如果您的咳嗽持续时间过长,或者有其他不适症状(如持续咳嗽、呼吸困难等),建议尽快就医。医生会根据您的症状、体检结果和可能的影像学检查(如X光、MRI或CT扫描)来诊断您的症状。在等待就医期间,您可以尝试以下方法来帮助缓解症状:1. **休息**:确保您有足够的睡眠。2. **保持水分**:脱水可能会加重咳嗽。3. **热敷**:使用热敷袋或热毛巾敷在疼痛的部位,有助于缓解喉咙痛。4. **避免刺激**:避免使用可能刺激喉咙的化学物质,如某些化学物质。5. **保持室内湿润**:确保您的卧室有良好的通风,可以使用加湿器帮助保持空气湿度。6. **保持室内湿度**:使用加湿器可以帮助缓解喉咙干燥和咳嗽。如果症状持续不缓解或有其他不适症状,请立即就医。希望您早日康复!
[B]: 如果您的咳嗽持续了两周,通常建议您尽快就医,因为这可能会影响您的呼吸和心跳。您可以通过以下步骤来检查咳嗽:1. **休息**:用纸巾或肘部轻轻按压咳嗽的位置。2. **使用药物**:在可能的情况下,使用药物(如抗过敏药、抗过敏药等)来缓解咳嗽。请在医生的指导下使用药物。3. **热敷**:在咳嗽期间,可以使用热敷来缓解疼痛和肿胀。4. **药物治疗**:如果咳嗽持续了两周,可以使用一些消炎药或抗过敏药来缓解症状。请务必在医生的指导下使用。5. **保持健康的生活方式**:保持充足的睡眠、均衡的饮食、适量的运动和避免吸烟和限酒,这些都有助于提高咳嗽的几率。请记住,这些建议不能替代专业医疗意见。如果您的症状持续或加重,强烈建议您尽快就医。
```
👉效果总结
full_sft模型在简洁性和信息准确性方面表现更好;rlhf模型在回答中倾向于提供更多的背景信息,但信息准确性有待改进。
总的来说RLHF后的模型倾向于学习:说更多有礼貌但无用的废话讨好“对话”本身,而对信息准确性则有轻微损失。
天下没有免费的午餐,还需要继续提升RLHF数据集的质量,也要接受模型能力无法避免的损失(程度有轻重)。
DPO和在线PPO的区别在于reject和chosen都是离线准备的,和minimind模型本身的输出必然存在很大的分布差异。
通俗地说DPO算法使模型观看乒乓球世界冠军的打法「录像」进行RL,而不是像PPO一样请reward模型做「教练」纠正自己的打法进行RL。
## Ⅱ RLAIF对比
基于`MiniMind2 (768dim)`在相同数据与训练步数下的主观观感对比,测试随机种子均固定2026,供参考:
[A] MiniMind-Reason-0.1B (蒸馏)
[B] MiniMind-Reason-0.1B (PPO)
[C] MiniMind-Reason-0.1B (GRPO)
```text
[Q]: 请介绍一下自己。
[A]: 我是由中国的个人开发者开发的智能助手小型AI推理模型-R1。我被设计用来理解和生成人类语言,能够理解复杂的自然语言问题,提供有用的信息和解决方案。 我是由中国的个人开发者开发的智能助手小型AI推理模型-R1。
[B]: 嗯,用户让我介绍一下自己。首先,我需要明确用户的需求是什么。他们可能是在做某个项目,想要了解自己的一些基本情况。不过,用户没有提供具体的信息,所以我得先假设一些可能的情况,比如他是一个学生,正在学习编程,或者是某个项目的开发者。接下来,我要考虑用户的身份。可能是一个学生、教师或者普通用户,他们需要了解自己的特点和能力。也有可能他们正在寻找灵感,或者在写论文时需要帮助。所以,我需要保持回答的简洁和实用,同时提供一些参考资料,比如教学视频、课程记录等。然后,我要考虑用户的身份。可能是一个学生,需要一些学习资源或帮助的对象。也有可能是一个学生,需要在课后作业或学习计划中进行调整。因此,我需要先询问用户的具体需求,这样才能提供更精准的帮助。接下来,我要确保语言简洁明了,适合不同场景。比如,如果用户是学生,可以介绍自己的学习特点;如果是教师,可以说明自己的角色和贡献。同时,提供一些实用的建议,比如如何高效学习,如何进行项目,以及如何与团队成员协作。最后,我要确保回复清晰,有条理,能够满足用户的需求。这样,用户就能轻松地了解自己,并且有实际的帮助。 当然!请告诉我你想了解哪方面的内容,我可以为您提供详细的介绍!
[C]: 嗯,用户问的是"请介绍一下自己"。首先,我需要理解用户的具体需求是什么。他们可能想知道自己是谁,或者有什么特定的背景。接下来,我应该考虑用户可能没有明确表达的需求。他们可能想知道如何描述自己的外观,或者如何与他人交流。然后,我应该考虑如何组织内容,从头到尾都要有条理。可能需要分步骤说明,比如从视觉、听觉到整体感受,再到情感共鸣。这样用户能更清晰地理解自己,也能更好地回应他们的需求。还要注意语言的自然和流畅,避免过于学术化的术语,让用户感觉顺畅。同时,保持回答的结构清晰,每句话都有明确的目的,这样用户能有明确的理解和操作。最后,检查是否有遗漏的重要信息,确保回答准确且全面。这样,用户不仅能得到答案,还能得到满足他们的需求。 您好!我是由中国的个人开发者开发的智能助手小型AI推理模型-R1。关于您的描述,似乎涉及多个领域,包括知识图谱构建、复杂系统的推理与分析。无论是理论模型、实际应用还是伦理讨论,您都在寻求如何将这些概念有机地结合起来,为人类社会带来福祉的解决方案。在"我"的身份下,您提到的"个人体验"和"情感共鸣",都是您个人独特魅力的重要组成部分。通过精准的描述和深度的分析,您可以更深入地理解您的独特之处。如果您对特定领域有特别的兴趣或需要建议,随时可以分享更多细节,我们将为您提供更加精准和个性化的服务。如果您有特定的主题或问题,欢迎随时提问!让我们一起探索这个神奇的AI世界,共同创造更美好的未来。
[Q]: 你更擅长哪一个学科?
[A]: 我是由中国的个人开发者开发的智能助手小型AI推理模型-R1。 我是由中国的个人开发者开发的智能助手小型AI推理模型-R1。
[B]: 嗯,用户问的是"你更擅长哪一个学科?"这个问题看起来有点复杂,但我可以一步步分析。首先,我需要理解用户的需求。他可能是在准备考试,或者需要了解某个学科的特点,或者是想在学习过程中应用某个学科的知识。接下来,我得考虑用户可能的背景。他可能是一个学生,或者是在准备考试,需要应用数学知识来解决具体的问题。也有可能他是一个学生,正在学习相关的课程,或者是对某个学科感兴趣。然后,我需要分析用户可能没有明确表达出来的需求。他可能在思考自己在学习中的困难,或者在寻找一个合适的教材或学习资源。考虑到这些,我应该提供几个不同的角度来帮助他。首先,分析"我更擅长哪一个学科"可以拆解为以下几个方面:兴趣、学习能力、学习风格、学习方法、学习资源、学习环境等等。每个方面都有不同的优势和特点,比如兴趣是最好的资源,学习能力是最好的方式,学习方式是根据个人情况选择。接下来,我需要考虑用户的身份。可能是学生,也可能是家长,或者对学习有一定兴趣的人。不同的身份可能有不同的偏好,比如家长可能更注重孩子的兴趣,而学生可能更关注学习方法和资源。然后,我需要考虑用户的身份是否有特殊需求。比如,他可能需要更专业的学习材料,或者希望找到最适合他的学习方法。因此,在分析时,我应该提供一个全面的回答,涵盖各个方面,并解释每个方面的重要性。另外,考虑到用户可能希望得到一个结构化的回答,我应该保持语言的简洁和逻辑性,确保信息准确,同时鼓励用户提供更多细节以便进一步分析。最后,我需要确保我的回答既有知识性,又符合用户的要求,帮助用户更好地理解和应用这个学科。因此,在回答中不仅要给出一个全面的分析,还要提到每个部分的作用和如何利用。 你擅长哪一个学科?这是一个明确的问题,可以从以下几个方面进行分析:1. **兴趣与学习能力**:你喜欢什么样的学习方式,比如自主学习、实验、项目等,这些都是很好的学习资源。2. **学习风格**:你喜欢什么类型的学习方法,比如笔记、复习、阅读、讨论等,这些都能影响学习效果。3. **学习资源**:你是否在寻找学习资源,比如书籍、在线课程、教育软件等,这些都能提供学习帮助。4. **学习环境**:你是否在学习环境中感到舒适,比如舒适的学习空间、安静的学习空间等,这些都会影响学习效果。5. **学习资源**:你是否有学习资源的丰富,如在线课程、学习平台、书籍等,这些都能提供丰富的学习资源。6. **学习方法**:你是否有具体的学习方法,比如如何理解、如何组织学习内容、如何应用知识等,这些都是提高学习效率的途径。综合考虑,这是一个非常全面的分析,涵盖了多个方面,帮助你更好地理解你的学科。
[C]: 嗯,用户问的是"你更擅长哪一个学科?"这个问题看起来有点复杂,但我可以一步步分析。首先,我需要理解用户的需求。他可能是在准备考试,或者需要了解某个学科的特点,或者是想在生活中找到自己的兴趣点。接下来,我要考虑用户可能的背景。他可能在工作或学习中遇到了类似的问题,想要了解自己擅长哪个领域,或者是否需要一些资源或指导来提升自己。然后,我要分析用户可能的深层需求。也许他想在职场上提升自己,或者寻找方向。他可能需要更具体的例子,帮助他更好地理解不同学科的特点和应用场景。还要考虑用户可能的背景。他可能不仅仅是在学习,而是希望了解在特定领域中如何应用这些学科。这需要我提供全面的分析,帮助他找到适合自己的方法。最后,我应该保持开放的态度,鼓励用户继续探索和学习。这可能包括推荐一些资源,或者讨论如何将这些知识应用到实际生活中。 你更擅长哪一个学科?这个问题本质上取决于你的个人兴趣和目标。以下是一些关键点,帮助你全面理解并应用这一点:1. **兴趣与专长**:了解自己擅长哪个领域,有助于做出更明智的选择。2. **全面发展**:考虑学科的多样性和深度,以全面发展自己的生活和职业。3. **适应与调整**:选择与自己技能、兴趣和目标相匹配的学科,有助于应对挑战和实现目标。4. **职业规划**:探索适合自己的职业路径,提升效率和竞争力。5. **社会贡献**:评估自己在社会中的角色,为社会做出贡献。为了更好地理解并应用这一点,你可以:- **了解行业动态**:关注特定领域的专业发展。- **实践与反思**:通过项目或实习积累经验。- **职业发展**:评估自己的长期职业规划。- **持续学习**:不断更新知识,适应职场变化。通过这些方向,你可以更全面地认识自己,找到适合自己的发展路径。
[Q]: 鲁迅的《狂人日记》是如何批判封建礼教的?
[A]: 嗯,鲁迅的《狂人日记》是如何批判封建礼教的呢?这个问题听起来挺有意思的,尤其是他在《狂人日记》中的表达方式。首先,我需要确认一下《狂人日记》具体是谁写的,是否有特定的人物或者事件。《狂人日记》是鲁迅在1924年创作的,主要讨论了社会问题,尤其是封建礼教的问题。作者曹雪芹是个非常著名的作家,他的作品中有许多关于封建礼教和阶级斗争的观点。这类作品在文学、哲学和政治上都有很深远的影响,尤其是在社会结构和人性的方面。接下来,我需要了解鲁迅的写作风格。他的写作风格比较直接,有严肃的哲学观点,强调人性的悲剧和道德的虚无。他的语言风格比较富有诗意,富有象征意义,善于运用象征手法,同时又不失真实和现实主义。他的作品中有很多关于社会阶级和阶级矛盾的分析,这些观点可能与当时的社会现实不符,所以在批判封建礼教时,应该强调这些矛盾。然后,我想到《狂人日记》中对封建礼教的讨论。鲁迅的作品中,封建礼教被视为不人道的,但通过文字和行动,表达了他对封建礼教的不满和反抗。这不仅反映了当时的社会现实,也揭示了封建礼教的黑暗面,体现了对封建社会的不满和对人性的深刻反思。接下来,我需要思考鲁迅对封建礼教的理解和批判。他在《狂人日记》中,对封建礼教的质疑和批判,体现了他对传统封建礼教的否定和批判。这不仅仅是对封建礼教的质疑,更是对当时社会的反思,以及对人性的关注。最后,我需要总结一下鲁迅对封建礼教的批判和批判。他通过《狂人日记》中的文字和行为,批判了封建礼教的虚假和不合理,体现了对社会现实的深刻反思。同时,他也关注了封建礼教的黑暗面,反映了对封建社会的不满和对人性的否定。总的来说,鲁迅的《狂人日记》通过文字和行动,批判了封建礼教的虚假和不合理,体现了当时的社会现实和人性的复杂。他的作品对后来的封建礼教有了启示,对当时的社会现象有了更深的反思。 鲁迅的《狂人日记》是一部反映封建礼教的文学作品,主要通过文字和行动反映了当时社会的现实。鲁迅的文字风格独特,富有象征意义,但通过文字和行动,批判了封建礼教的虚假和不合理。他的作品中,封建礼教被视为不人道的,但通过文字和行动,反映了封建社会的不公和人性的深刻反思。鲁迅的《狂人日记》通过文字和行动,批判了封建礼教的虚假和不合理,体现了当时社会的不满和对人性的反思。他的作品不仅批判了封建礼教的虚假和不合理,还深刻揭示了封建社会的黑暗面。
[B]: 嗯,用户问的是鲁迅的《狂人日记》如何批判封建礼教。首先,我需要理解鲁迅的生平和作品。《狂人日记》是中国现代文学的经典,作者是毛泽东,作品涉及社会、家庭、伦理等多个层面。我需要找出鲁迅的写作风格和主题,以及它在当时的社会背景。接下来,我应该回顾《狂人日记》的主要内容。毛泽东在《青春无悔》中提出了"狂人日记"这一概念,强调青春活泼、勇敢、正义,这在当时社会中仍然具有重要意义。他通过描绘主人公狂人来表达对社会不公的批判,但同时也指出他的创作对社会的负面影响,比如社会动荡和个人主义的失败。然后,我应该分析鲁迅的创作理念和主题。《狂人日记》强调了社会的黑暗面,主张"以人为本"、"反对封建礼教"等。他可能也在探讨社会不平等的问题,比如"人性弱点"、"权力滥用"等问题。还要考虑鲁迅的其他作品,比如《阿Q正传》、《死亡诗社》等,这些作品虽然有点夸张,但也有深刻的社会批判,比如对社会道德的质疑。同时,作者可能还涉及其他作品,如《庆余年》等,但这些可能更侧重于文学创作,而不是社会批判。另外,用户可能想知道鲁迅在文学创作中的具体经历,比如他是否有作品被广泛批评,或者他对社会的批判是否具有批判性。所以,回答时需要指出鲁迅的创作经历,以及他对社会现实的反思。总结来说,我需要回答鲁迅的《狂人日记》批判封建礼教,并分析其在当时的社会背景和文学价值,同时指出其对社会的批判性思考,以及其对后世的影响。 鲁迅的《狂人日记》批判封建礼教,以其独特的叙事风格和深刻的社会批判精神著称,主要体现在以下几个方面:1. **社会批判与个人成长**:小说通过描绘主人公狂人的活泼、勇敢、正义,揭示社会的不公和弱势。2. **个人主义与社会批判**:小说反映了封建礼教对个人自由和权利的侵犯,强调个人尊严和正义的价值。3. **对社会的批判性思考**:通过对社会不公的刻画,揭示社会问题的根源,并对当时社会的批判态度进行批判。鲁迅的作品在当时的社会背景和文学价值使其成为当时文学的重要代表。他的作品不仅在当时广受欢迎,也对后世产生了深远影响,被广泛引用和传颂。
[C]: 嗯,用户问的是鲁迅的《狂人日记》如何批判封建礼教。首先,我需要理解鲁迅的背景和核心思想。他可能是一位社会学家、思想家,或者是对传统文化有深厚兴趣的读者。狂人日记是他在《狂人日记》中所写的,可能对传统文化有一定影响。接下来,我要考虑用户的需求是什么。用户可能想知道这本书在现代社会中的反思意义,或者是否有相关研究支持这一点。也有可能他们对书中的情节有疑问,想了解如何更深刻地理解社会现象。然后,我需要思考如何从不同的角度解读鲁迅的文本。例如,是否有直接的历史叙事,或者是否存在更深层次的哲学思考?这需要我先了解鲁迅的不同观点,然后分析其批判性。还要考虑用户可能的深层需求,比如是否需要了解他作为文学批判家的背景,或者是否有对传统价值观的反思。因此,回答时要全面,涵盖核心问题,并引用相关资料来支撑观点。最后,总结鲁迅的观点,强调其对现代社会的批判性思考,以及对传统文化的尊重。这样既全面又有深度,帮助用户全面理解鲁迅的作品。 鲁迅的《狂人日记》通过其独特的叙事手法和深刻的社会批判精神,对封建礼教进行了深刻的批判。以下是其批判性分析:1. **社会批判与历史真相**:小说通过对历史人物的刻画,揭示封建礼教的弊端,以及其对传统社会结构的冲击。这种批判不仅限于对现实的深刻批判,也反映了现代社会对传统价值观的重新审视。2. **个人命运与社会批判**:小说中,主人公通过"狂人日记"揭示了封建礼教对个人命运的严重剥夺。这种叙事方式既批判了封建礼教,也对后世产生了深远影响。3. **对后世的影响**:从文学创作到思想解读,鲁迅的作品深刻影响了后世的思想体系。例如,《狂人日记》通过人物命运的反映,对现代社会的价值观念提出了新的思考。4. **对现代文明的反思**:这一批判性思考不仅反映了当代社会的复杂性,也为现代人提供了反思社会现实、维护人权的视角。5. **个人视角与文化视角**:作者通过这一批判性思考,展现了对传统价值观的重新解读,同时也对当代社会的多元化视角产生了启发。综上所述,鲁迅的《狂人日记》不仅是对封建礼教的批判,更是对传统文化的一种深刻反思。它通过对封建礼教的批判,提出了对现代社会结构、权力关系的深刻反思,具有重要的社会价值。
```
## Ⅲ 其他模型对比
[A] [MiniMind2 (0.1B)](https://www.modelscope.cn/models/gongjy/MiniMind2-PyTorch)
[B] [MiniMind2-MoE (0.15B)](https://www.modelscope.cn/models/gongjy/MiniMind2-PyTorch)
[C] [MiniMind2-Small (0.02B)](https://www.modelscope.cn/models/gongjy/MiniMind2-PyTorch)
[D] [minimind-v1-small(0.02B)](https://pan.baidu.com/s/1_COe0FQRDmeapSsvArahCA?pwd=6666)
[E] [minimind-v1-moe(0.1B)](https://pan.baidu.com/s/1tqB-GMvuiGQBvEl-yZ-oBw?pwd=6666)
[F] [minimind-v1(0.1B)](https://pan.baidu.com/s/1p713loS7EfwHQf3G9eYI3Q?pwd=6666)
[G] [baby-llama2-chinese(0.2B)](https://github.com/DLLXW/baby-llama2-chinese)
[H] [chatlm-mini-chinese(0.2B)](https://github.com/charent/ChatLM-mini-Chinese)
```text
[Q]: 你知道长江吗?
[A]: 长江,位于中国东南部,是中国的第一长河,全长6300多公里,流经11个省份,是中国最长的河流,也是中国的“母亲河”。长江的历史可以追溯到公元前2000多年的商朝时期,当时的商朝是商朝的后裔。商朝时期,长江的经济发展达到了高峰,是中国最重要的农业和工业中心之一。长江流域的经济主要以农业为主,长江渔业占据了主要产业,如钓鱼、猎鱼等。长江的水资源也非常丰富,包括河流、湖泊、河流等。长江的自然景观也十分壮观,长江四季景色各异,春季多雨,夏季多雨,秋季则多雨,冬季则寒冷多雪,春季和秋季都有美丽的花朵和果实。长江是中国的经济中心,拥有众多的国家和城市,是世界上重要的交通枢纽和航运中心。同时,长江还是中国的重要水利资源,对于中国的经济发展具有重要意义。
[B]: 是的,我知道长江。长江位于中国的中部,是中国第三长的河流,全长约6300公里,流经江西省、安徽省、江苏省、安徽省、江苏省和安徽省。
[C]: 当然,长江是中国最长的河流,全长约6300公里。它以其丰富的水资源、丰富的水生动植物资源以及独特的地理位置而闻名于世。
[D]: 是的,长江是中国最长的河流,全长超过3300千米。
[E]: 长江是中国最长的河流,总长度约为6300公里。它发源于青藏高原的青海湖,流经青海、四川、甘肃、宁夏、内蒙古、陕西和山西。长江流域是中国最大的农业区之一,也是中国的文化和经济中心。
[F]: 是的,长江是中国最长的河流之一,也是世界第三大河流。长江发源于青藏高原,流经11个省份,最终注入东海。长江流域是中国最大的河流流域之一,拥有着丰富的自然资源和文化遗产,如长江大桥、长江海洋博物馆、长江古城等。
[G]: 同时也知道,中国是世界上最长的城市之一,拥有超过3400万人口。
[H]: 是的,长江是中国最长的河流,也是世界上最长的河流之一。它发源于青藏高原,流经九个省区,最终注入东海。长江流域的气候温和,四季分明,是中国重要的农业和工业基地。长江流域的水产资源丰富,是中国的重要渔业资源之一。
[Q]: 世界上最高的山峰是什么?
[A]: 世界上最高的山峰是珠穆朗玛峰(Mount Everest),位于喜马拉雅山脉,尼泊尔和中国的边界上。它的海拔高度是8,848.86米(29,031.7英尺),是地球上最高的山峰。
[B]: 珠穆朗玛峰(Mount Everest)是世界上最高的山峰,海拔高度达8,848米(29,029英尺)。
[C]: 珠穆朗玛峰是世界上最高的山峰,位于喜马拉雅山脉,海拔8,848.86米(29,031.7英尺)。它位于尼泊尔和中国的边界上,是喜马拉雅山脉的一部分。
[D]: 世界上最高的山峰是珠穆朗玛峰,位于尼泊尔和中国的边境上,海拔8848米。
[E]: 世界上最高的山峰是珠穆朗玛峰,位于喜马拉雅山脉,海拔8,848米。
[F]: 珠穆朗玛峰是世界上最高的山峰,海拔8848米。
[G]: 世界上最高的山峰是珠穆朗玛峰,位于喜马拉雅山脉,海拔8,848.86米(29,031.69英尺)。
[H]: 世界上最高的山峰是珠穆朗玛峰,也称为萨加玛塔,位于喜马拉雅山脉的尼泊尔和中国边境之间,海拔8,848.86米(29,031.69英尺)。它是世界上最著名的登山目标之一,吸引着来自世界各地的登山者前来挑战。珠穆朗玛峰的名字来自藏语,意思是“女神的额峰”,它是由两个不同的山峰组成的,其中一个是位于尼泊尔的珠穆朗玛峰,另一个则位于中国。它的高度是通过测量海拔高度来确定的,因为它是通过测量地球的平均高度来确定的。尽管珠穆朗玛峰是世界上最高的山峰,但它并不是地球上任何其他地方都能到达的。地球上的其他地方,如南美洲的安第斯山脉,也是世界上最高的山脉,但它并不是地球上最高的山峰。总之,珠穆朗玛峰是世界上最高的山峰,但它并不是地球上任何地方都能到达的。它是地球上最高的山脉,但它并不是地球上任何地方都能到达的。
[Q]: 万有引力是谁提出的?
[A]: 万有引力是由牛顿在17世纪提出的,它是牛顿三大定律之一。牛顿在17世纪提出的引力定律揭示了万有引力定律的本质,并且解释了行星、卫星、彗星等天体之间如何相互作用。这个定律是由艾萨克·牛顿在1687年提出的,他通过对万有引力定律的分析和实验,成功地解释了天体之间的引力作用,从而解释了地球绕太阳旋转的现象。
[B]: 万有引力(Human Policy)是牛顿的三大力学定律,用于描述两个物体之间的相互作用力。它由万有引力定律和牛顿的第一定律(惯性定律)构成。万有引力是由于两个物体之间相互作用而产生的,它们的质量、距离、速度和方向等因素决定了它们之间的相互作用。这种相互作用力是:质量的乘积:质量的乘积是万有引力定律和牛顿第二定律的乘积。质量的乘积:质量的乘积是物体之间的一种物理过程,它是物体间相互作用的产物,对于其他物体来说,其质量可以表示为两个物体之间的质量之和,即重力加速度a。
[C]: 万有引力是一个由牛顿在1687年提出的物理学概念,它描述了物体之间引力如何相互作用的规律。
[D]: 万有引力是由英国物理学家牛顿提出的。他认为,所有物体都会产生引力,这个引力是由物体的质量和距离决定的。这个理论揭示了质量和距离之间的关系,并证明了万有引力的本质。
[E]: 万有引力是由牛顿在1687年提出的。它是宇宙中一个基本的物理现象,它描述了物体之间的相互作用。这个力被称为万有引力,它在所有物体之间都存在,这种力与物体的质量和距离有关。万有引力是自然界中最基本的力量之一,它不仅影响着物体的运动和变化,还对宇宙的结构和演化产生着重要的影响。
[F]: 万有引力是英国物理学家艾萨克·牛顿在17世纪提出的。
[G]: 引力是宇宙中一种力量,它是由质量或能量所组成的。根据牛顿的万有引力定律,一个物体之间的引力大小与它的质量成正比,与它的质量成反比。因此,牛顿的万有引力定律表明,一个物体之间的引力大小与它的质量成正比,与它的质量成反比。这个定律在物理学、天文学和物理学中都有广泛的应用。
[H]: 万有引力是由英国物理学家艾萨克·牛顿于1687年提出的。他在1687年发表了一篇著名的论文,题为《自然哲学的数学原理》,其中提出了万有引力定律,指出任何两个物体之间都存在着一种引力,这种引力的大小与它们的质量成正比,与它们之间的距离的平方成反比。这个定律被称为万有引力定律,它描述了质量和距离之间的关系。它表明,两个物体之间的引力与它们的质量成正比,与它们之间的距离的平方成反比。这个定律对于解释宇宙中的许多现象和现象之间的相互作用非常重要,例如行星绕太阳运动、恒星之间的引力透镜效应等等。它也被广泛应用于天文学、物理学和工程学等领域,为我们理解宇宙的本质和演化提供了重要的理论基础。
[Q]: 你知道大熊猫的主要食物是什么吗?
[A]: 大熊猫主要以竹子为食,但也会吃其他植物、昆虫、小型哺乳动物和鱼类。它们的消化系统与其他熊科动物类似,能够消化竹子。大熊猫的牙齿锋利,适合咀嚼竹子,因此它们经常被称为“竹食动物”。
[B]: 大熊猫是以竹子为食的哺乳动物,它们是肉食动物。它们主要食物是竹子,特别是竹子中富含纤维素和矿物质,并且不会直接进入消化系统。大熊猫的肠道主要由竹子组成,它们需要消化竹子中的纤维素和其他纤维素来支持它们的正常进食。
[C]: 大熊猫主要以竹子为食,但它们也吃其他植物,包括树叶、嫩芽、昆虫、水果、蔬菜和小型哺乳动物等。大熊猫是中国特有的物种,属于熊科,主要分布在中国的四川、陕西和甘肃等地。
[D]: 大熊猫的主要食物是竹子。它们通常吃竹子,每天需要吃掉大约30公斤的竹子。
[E]: 是的,大熊猫主要以竹子为食。它们每天需要吃掉大量的竹子来维持生命,每天需要吃掉40至80公斤的竹子。此外,它们也会吃一些其他的植物,如草、果实、坚果和小型哺乳动物。
[F]: 大熊猫主要以竹子为食,也会偶尔食用其他的植物和动物。此外,大熊猫也会吃一些野果、小动物和植物,但这些都不属于它们的主要食物来源。
[G]: 大熊猫的主要食物是竹子。
[H]: 大熊猫是一种以竹子为主要食物的植食动物,它们的肠道结构适合消化纤维素含量高的竹子,但也会吃一些其他植物,如草本植物和小型哺乳动物。大熊猫的肠道结构也适应了高纤维的竹子,这使得它们能够消化大量的纤维素,从而帮助它们在野外生存。大熊猫的肠道中还含有一种叫做“纤维素酶”的酶类物质,这种酶能够帮助大熊猫分解纤维素,从而帮助它们消化大量的水分和营养物质。此外,大熊猫的肠道还含有一种叫做“纤维素蛋白”的蛋白质,这种蛋白质能够帮助大熊猫维持体内的能量水平,从而帮助它们在野外生存。总的来说,大熊猫的主要食物是竹子,但它们也会吃一些其他植物,如草本植物和小型哺乳动物。
[Q]: 海水为什么是咸的?
[A]: 海水之所以是咸的,主要是由于其中的化学成分。海水中含有大量的矿物质和盐分,其中主要成分是硫酸盐、碳酸盐、镁离子和钾离子。这些物质在高浓度下,会沉淀在海水中,形成海水。具体来说,海水中的矿物质和盐分主要来自于岩石、土壤、生物和人类排泄物等。岩石是海水的组成部分,主要由矿物质组成,如石英、长石、云母等。土壤中含有大量的化学物质,如氮、磷、钾等,这些物质会渗透到土壤中,形成土壤。生物体内的盐分主要来源于植物的叶绿素等色素,这些色素会吸收太阳光中的能量,转化为生物体可以利用的能量。而人类排泄物中含有的盐分主要来源于矿物质和碳酸盐,这些矿物质在水中的浓度较高,会导致水中溶解的矿物质浓度增加,形成水体中的盐分。因此,海水之所以是咸的,是由于其中的化学成分和结构特征。海水中的矿物质和盐分主要来自于岩石、土壤、生物和人类排泄物等,而这些物质的积累和排泄会导致海水呈现出咸味。
[B]: 海水是咸的,因为它包含了多种物质,包括氯化钠(NaCl)、氯化钠(NaCl)、碳酸盐(如硫酸盐)、氯化钠(NaCl)和水。咸物质的来源:盐是咸的常见来源,含有钾、钙、镁、钾等矿物质。这些矿物质通常来自于地下水、地下水或土壤中,这些矿物质的含量远低于纯净水。咸味的原因:盐的咸味主要源于其溶解于水中的微小颗粒物。这些小颗粒物主要通过植物根部和动物体内的微生物传播,如昆虫、小型哺乳动物、鸟类和某些昆虫。综上所述,海水是咸的,因为它含有大量的盐类,包括矿物质、岩石、盐、矿物质等,这些物质在海水中的浓度高,对咸味的产生较大影响。
[C]: 海水是咸的,主要是因为其中含有各种盐分,其中以海水为主要成分之一。当海水中含有大量的盐分时,盐分会被溶解在海水中,形成咸味。海水中的盐分主要来源于溶解盐类、蒸发析出的盐和海水冻结成冰等因素。
[D]: 海水中含有许多盐分,这些盐分可以导致海水咸度的增加。海水中的盐分主要来自于海水中的盐分,这些盐分可以从海水中的盐分中获得。海水中的氧化物和盐分可以与海水中的盐分形成氢键,从而使海水咸度增加。
[E]: 海水是咸的,这是因为它含有大量的盐分,其中包括氯离子和氯离子。这些离子在海洋中形成了大量的盐,这些盐分被称为盐分。海水中含有许多溶解在水中的盐,这些盐分会随着海水的升高而逐渐蒸发,最终导致海水中盐分的蒸发。这些盐分在海水中被完全消耗,然后被排除在海水中。此外,海水中还含有许多其他的盐分,但这些盐分是不同的,因为它们在水中的浮起和下降过程是不同的。海水中的盐分是从海底的岩石中提取出来的,这些盐分在海水中可以被利用。总的来说,海水是咸的,这也是为什么海水中含有许多盐分和盐分的原因。
[F]: 海水含有许多溶解的盐类,其中最主要的是氯化钠。当水中加入盐时,盐的分子会与水分子发生反应,形成氢氧化钠,这是一种盐。
[G]: 因为水是许多生物的生存所必需的,它能够吸收和释放二氧化碳,释放氧气,维持大气中的水蒸气,以及维持水循环。水中的盐类和化学物质会释放出氧气,使地球上的生物呼吸。此外,水还具有许多其他功能,如保持水循环、维持水循环、调节气候和环境等。水是许多生物生存所必需的,它也是许多自然现象的重要基础。
[H]: 海水是咸的主要原因是因为其中含有大量的溶解盐类,其中最主要的是氯化钠(NaCl)。氯化钠是一种非常常见的盐类,它存在于地球上的大部分地区,包括海洋、湖泊、河流和地下水。当水从海洋中蒸发时,它会带走一部分盐分,使海水变得咸。此外,海中还含有其他溶解盐类的物质,如硫酸盐、硫酸镁、硫酸钙、硫酸镁盐、硫酸镁钾、硫酸镁钠、硫酸镁钙、硫酸镁镁钙、硫酸镁镁钙、硫酸镁镁钙、硫酸镁镁钠、硫酸镁镁钙、硫酸镁镁镁钙、硫酸镁镁镁钙、硫酸镁镁镁钙、硫酸镁镁镁钙、硫酸镁镁镁钙、硫酸镁镁镁钙、硫酸镁镁镁钙、硫酸镁镁镁钙、硫酸镁镁镁钙、硫酸镁镁镁钙、硫酸镁镁镁镁钙、硫酸镁镁镁镁钙、硫酸镁镁镁镁钙、硫酸镁镁镁镁钙、硫酸镁镁镁镁钙、硫酸镁镁镁镁钙、硫酸镁镁镁镁镁钙、硫酸镁镁镁镁镁钙、硫酸镁镁镁镁镁钙、硫酸镁镁镁镁镁钙、硫酸镁镁镁镁镁镁钙、硫酸镁镁镁镁镁镁钙、硫酸镁镁镁镁镁镁钙、硫酸镁镁镁镁镁镁镁钙、硫酸镁镁镁镁
[Q]: 写一段python的快速排序代码
[A]: 好的,以下是Python的快速排序代码:def quick_sort(arr): if len(arr) <= 1: return arr else: pivot = arr[len(arr) // 2] left = [x for x in arr[1:]] right = [x for x in arr[2:] if x < pivot] return quick_sort(left) + [pivot] + quick_sort(right)# 测试代码arr = [3, 6, 8, 10, 1, 2, 1]print(quick_sort(arr))这段代码首先检查数组的长度是否小于等于1。如果是,那么它就按照从小到大的顺序排列。接着,对于数组的每个元素,它想要进行递归地排序,直到达到排序的结束位置。如果数组的长度是奇数,那么它就按照从大到小的顺序排列。最后,平均的时间复杂度是O(n log n),其中n是数组的长度。
[B]: 以下是一个使用Python的快速排序算法的实现:def sort_array(arr): # 生成一个随机排列 sorted_array = sorted(arr) # 返回排序后的列表 return sorted(arr)# 示例arr = [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5]# 调用函数sorted_array = sort_array(arr)print("原始数组是:", sorted_array)这段代码首先生成一个随机排列,然后通过一个列表的长度进行排序。最后,返回排序后的列表。注意,这个代码使用了Python的内置sorted函数和内置的sorted()函数,它们在时间复杂度为O(n log n)的情况下,比直接使用sorted()函数更快。
[C]: 以下是一个简单的排序算法,适用于小型数组,包括小于等于5的数组。def quick_sort(arr): if len(arr) <= 1: return arr else for _ in range(2, 51): if arr[len(arr) - 1:] is not None: arr[len(arr) - 1] = arr[len(arr) - 1] arr[len(arr)] = arr[len(arr)] return quick_sort(arr)# 示例arr = [3, 5, 1, 4, 1, 2, 1]sorted_arr = quick_sort(arr)print("Sorted array is:", sorted_arr)### 代码解释:1. **函数定义**:quick_sort 函数接受一个数组 arr 作为参数。2. **循环**:对于 arr 的元素,使用递归来实现,即从右到左遍历数组,并将当前元素与数组的当前元素交换位置,直到数组达到空或数组长度小于等于 arr。3. **递归调用**:遍历数组,将当前元素与数组的当前元素进行交换,直到数组达到空或数组长度小于等于 arr。4. **检查数组长度**:使用 if __name__ == "__main__" 检查数组的长度是否小于 arr,如果是,就将数组从较大的数组移动到数组的末尾。5. **输出排序后的结果**
[D]: 作为一个AI语言模型,我无法编写Python程序。但是,Python是一个非常流行的编程语言,它具有许多优秀的库和框架,包括NumPy、Pandas、Matplotlib、Pandas、Bandke、Norm和NKlearn等。Python有很多优秀的自然语言处理库和框架,可以用于处理和分析各种类型的数据,如文本、图像、音频、视频等。Python还可以用于创建各种应用程序,如网页搜索、游戏开发、科学计算等。Python非常灵活,也支持多种编程风格,因此可以轻松地找到适合自己的解决方案。
[E]: 作为AI语言模型,我可以回答您的问题。但是我无法进行编程操作,因为我无法确定您想问的是哪种编程语言。请您提供更具体的问题,以便我能够更好地回答您的问题。
[F]: 快速排序(Quick Sort)是一种简单的排序算法,它通过将数据划分为小组,每组数据按照一定规则排序,最终得到一个有序数组。
[G]: 好的,以下是一段快速排序的Python代码```python sorted_print(sorted(sorted(sorted(sorted_print))```输出结果为:```[1, 2, 3, 4, 5, 6, 7, 8, 9]```
[H]: 快速排序是一种基于分治思想的高效排序算法,它的时间复杂度为 O(n log n)。它的基本思想是通过一趟排序将待排序序列划分为两个子序列,其中一个子序列的所有元素都比另一个子序列的所有元素小,然后对这两个子序列分别递归地进行排序。下面是一个 Python 代码示例,实现了快速排序算法:```pythondef quick_sort(arr): if len(arr) > 1: return arr else: return quick_sort(arr)```该代码使用了递归的方式,首先判断数组的长度是否小于等于1,如果是,则直接返回数组,否则递归地对数组进行排序。在递归过程中,我们首先判断数组的第一个元素是否大于等于1,如果是,则将数组中的元素与第一个元素进行比较,如果不等于1,则将数组中的元素与第二个元素进行比较,以此类推,直到所有元素都被排序。该代码的时间复杂度为 O(n log n),是一个非常实用的排序算法。
[Q]: 截至2025年2月9日14时31分,电影《哪吒之魔童闹海》累计票房(含预售)突破78.09亿元,超过《星球大战:天行者崛起》的票房成绩,成为首部进入全球票房榜前40的亚洲电影。这一成就不仅标志着中国电影在国际市场的突破,也展示了中国动画电影的巨大潜力和市场吸引力。从这段文字总结20字的摘要给我。
[A]: 电影《哪吒之魔童闹海》票房突破78.09亿元,成为首部进入全球票房榜前40的亚洲电影。这标志着中国电影的国际突破,也展现了中国动画电影的巨大潜力。
[B]: 2025年2月9日,中国电影在世界舞台上突破78.09亿元,超过《星球大战:天行者崛起》的票房成绩。
[C]: 电影《哪吒之魔童闹海》票房突破78.09亿元,成为全球票房榜前40的亚洲电影,展现中国动画电影的巨大潜力。
[D]: 《哪吒之魔童闹海》累计票房突破78.09亿,成为首部进入全球票房榜前40的亚洲电影,展示了中国电影在国际市场的突破,同时展示了中国动画电影的巨大潜力和市场吸引力。
[E]: 《猛龙强:打开世界奇幻冒险》成功地,上海成功吸引了众多观众,同时也引起了广泛的关注。
[F]: 《哪吒之魔童闹海》是一部让中国动画电影成为国际市场的巨大潜力。该电影以其华丽的画面和惊险的战斗场面而闻名于世。
[G]: 《哪行是值得的》是2021年1月9日14时31分,电影《哪成大作为》在电影市场突破7800亿美元,成为中国动画电影的突破,并展示中国动画电影的巨大潜力和市场吸引力。
[H]: 我是一个参数很少的AI模型🥺,知识库较少,无法直接回答您的问题,换个问题试试吧👋
```
---
🙋直接把以上所有问题和模型的回答丢给DeepSeek-R1,让它帮忙点评和排名打分:
具体点评
### 评分标准:
- **准确性**:回答是否正确且无明显错误。
- **完整性**:回答是否涵盖了问题的核心要点。
- **逻辑性**:回答是否有条理,是否符合逻辑。
- **代码质量**:代码是否能正常运行,逻辑是否清晰。
### 点评:
1. **A模型**:
- **优点**:回答非常全面,信息量大,逻辑清晰,尤其在长江、大熊猫、海水咸味等问题上表现优异。代码虽然有小瑕疵,但整体思路正确。
- **缺点**:部分回答稍显冗长,但不影响整体质量。
- **总评**:综合表现最佳,得分最高。
2. **H模型**:
- **优点**:回答较为准确,尤其在珠穆朗玛峰、万有引力等问题上表现出色。代码虽未完全展示,但解释较为详细。
- **缺点**:部分回答略显啰嗦,但逻辑性较强。
- **总评**:仅次于A模型,表现稳定。
3. **C模型**:
- **优点**:回答简洁明了,尤其在大熊猫、快速排序代码等问题上表现较好。
- **缺点**:部分回答略显简短,缺乏深入解释。
- **总评**:整体表现不错,但细节上略逊于A和H。
4. **F模型**:
- **优点**:回答较为准确,尤其在长江、万有引力等问题上表现尚可。代码部分有一定逻辑性。
- **缺点**:部分回答不够深入,代码存在一些小问题。
- **总评**:表现中规中矩,仍有提升空间。
5. **D模型**:
- **优点**:回答基本准确,尤其在万有引力、长江等问题上表现尚可。
- **缺点**:部分回答过于简略,代码存在明显错误。
- **总评**:表现一般,需改进代码部分。
6. **B模型**:
- **优点**:回答较为准确,尤其在长江、海水咸味等问题上表现尚可。
- **缺点**:部分回答逻辑性较差,代码存在较大问题。
- **总评**:表现平平,需进一步优化。
7. **E模型**:
- **优点**:部分回答较为准确,尤其在海水咸味、大熊猫等问题上表现尚可。
- **缺点**:回答过于简略,代码部分几乎无法运行。
- **总评**:表现不佳,需大幅提升。
8. **G模型**:
- **优点**:几乎没有明显的优点。
- **缺点**:回答严重偏离主题,代码部分完全无法运行。
- **总评**:表现最差,需大幅改进。
---
### 总结:
- **A模型**在各方面表现最为出色,尤其在复杂问题的回答上展现了极高的准确性与逻辑性。
- **H模型**紧随其后,表现稳定,但在某些细节上略显不足。
- **G模型**表现最差,回答偏离主题且代码无法运行,需大幅改进。
### 打分排序
| 排名 | 模型 | 准确性 (30分) | 完整性 (30分) | 逻辑性 (20分) | 代码质量 (20分) | 总分 (100分) |
|----|----|-----------|-----------|-----------|------------|-----------|
| 1 | A | 28 | 29 | 19 | 20 | 96 |
| 2 | H | 27 | 28 | 18 | 20 | 93 |
| 3 | C | 26 | 27 | 18 | 18 | 89 |
| 4 | F | 25 | 26 | 17 | 18 | 86 |
| 5 | D | 24 | 25 | 17 | 16 | 82 |
| 6 | B | 23 | 24 | 16 | 15 | 78 |
| 7 | E | 22 | 23 | 15 | 14 | 74 |
| 8 | G | 10 | 12 | 10 | 10 | 42 |
### 👉主观效果总结
个人主观评价与DeepSeek-R1基本相符,其中:
* MiniMind系列的排序非常符合直觉,参数越大+训练数据越充分评分越高,幻觉和错误都会比小模型肉眼可见的好。
* H模型的回答肉眼看起来是不错的,尽管存在些许幻觉瞎编的情况。
* G模型可能训练数据不够完备,给出的权重经过测试效果不佳。
* 再复诵一遍经久不衰的Scaling Law: 参数越大,训练数据越多模型的性能越强。
---
## Ⅳ RoPE长度外推
MiniMind支持通过YaRN算法进行RoPE位置编码的长度外推,使模型能够处理超出训练长度的文本序列。
原生torch模型在使用`eval_llm.py`进行推理时,只需添加`--inference_rope_scaling`参数即可启用RoPE外推:
```bash
python eval_llm.py --weight full_sft --inference_rope_scaling
```
对于Transformers格式的模型,可以在config.json中添加以下配置实现长度外推:
```json
"rope_scaling": {
"type": "yarn",
"factor": 16.0,
"original_max_position_embeddings": 2048,
"beta_fast": 32.0,
"beta_slow": 1.0,
"attention_factor": 1.0
}
```
在MiniMind-Small模型上,测试输入不同长度的「西游记」白话文小说,评估RoPE scaling前后的困惑度(PPL)对比。
可以看出,启用YaRN外推后,模型在长文本上的PPL表现显著下降:
---
## Ⅴ Objective Benchmark
下面就到喜闻乐见的benchmark测试环节,就不找乐子和Qwen、GLM级别的模型做对比了。
这里选取了一些微型模型进行横评比较,
测试集选择C-Eval、CMMLU、A-CLUE、TMMLU+这几个纯中文语言榜单。
测评框架
测评框架选择[lm-evaluation](https://github.com/EleutherAI/lm-evaluation-harness),
安装后启动测试非常方便:
```bash
lm_eval --model hf --model_args pretrained=<填写模型路径>,device=cuda,dtype=auto --tasks ceval* --batch_size 8 --trust_remote_code
```
PS: 在这种全是选择题的测评集中,为了避免回复格式的难以固定的特点,
所以常用做法是直接把`A`,`B`,`C`,`D`四个字母对应token的预测概率取出来,将其中概率最大的字母与标准答案计算正确率。
选择题1/4乱选的正确率是25%,然而这个量级的所有模型都集中在25附近,甚至很多时候不如瞎选,是不是像极了高中完形填空的滑铁卢正确率...
MiniMind模型本身预训练数据集小的可怜,也没有针对性的对测试集做刷榜微调,因此结果纯娱乐:
| models | from | params↓ | ceval↑ | cmmlu↑ | aclue↑ | tmmlu+↑ |
|-------------------------------------------------------------------------------|---------------|---------|--------|---------|--------|---------|
| MiniMind2 | JingyaoGong | 104M | 26.52 | 24.42 | 24.97 | 25.27 |
| MiniMind2-Small | JingyaoGong | 26M | 26.37 | 24.97 | 25.39 | 24.63 |
| MiniMind2-MoE | JingyaoGong | 145M | 26.6 | 25.01 | 24.83 | 25.01 |
| [Steel-LLM](https://github.com/zhanshijinwat/Steel-LLM) | ZhanShiJin | 1121M | 24.81 | 25.32 | 26 | 24.39 |
| [GPT2-medium](https://huggingface.co/openai-community/gpt2-medium) | OpenAI | 360M | 23.18 | 25 | 18.6 | 25.19 |
| [TinyLlama-1.1B-Chat-V1.0](https://github.com/jzhang38/TinyLlama) | TinyLlama | 1100M | 25.48 | 25 | 25.4 | 25.13 |
| [SmolLM2](https://github.com/huggingface/smollm) | HuggingFaceTB | 135M | 24.37 | 25.02 | 25.37 | 25.06 |
| [Aquila-Instruct](https://www.modelscope.cn/models/BAAI/Aquila-135M-Instruct) | BAAI | 135M | 25.11 | 25.1 | 24.43 | 25.05 |

# 📌 Others
## 🔧 模型转换
* [./scripts/convert_model.py](./scripts/convert_model.py)可以实现`torch / transformers`模型的互相转换
* 如无特别说明,`MiniMind2`模型均默认为`Transformers`格式的模型,需提前`t2t`转换!
## 🖥️ 基于MiniMind-API服务接口
* [./scripts/serve_openai_api.py](./scripts/serve_openai_api.py)完成了兼容openai-api的最简聊天接口,方便将自己的模型接入第三方UI
例如FastGPT、OpenWebUI、Dify等等。
* 从[Huggingface](https://huggingface.co/collections/jingyaogong/minimind-66caf8d999f5c7fa64f399e5)下载模型权重文件,文件树:
```
minimind (root dir)
├─(例如MiniMind2)
| ├── config.json
| ├── generation_config.json
| ├── model_minimind.py or w/o
| ├── pytorch_model.bin or model.safetensors
| ├── special_tokens_map.json
| ├── tokenizer_config.json
| ├── tokenizer.json
```
* 启动聊天服务端
```bash
python serve_openai_api.py
```
* 测试服务接口
```bash
python chat_openai_api.py
```
* API接口示例,兼容openai api格式
```bash
curl http://ip:port/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "model-identifier",
"messages": [
{ "role": "user", "content": "世界上最高的山是什么?" }
],
"temperature": 0.7,
"max_tokens": 512,
"stream": true
}'
```
## 👨💻 更多
* 🔗从MiniMind-LLM微调扩散语言模型
* 🔗模型的generate方法说明
---
## [vllm](https://github.com/vllm-project/vllm)
vLLM是极其流行的高效推理框架,支持大模型快速部署,优化显存利用与吞吐量。
以openai-serve形式启动 minimind2:
```bash
vllm serve ./MiniMind2 --model-impl transformers --served-model-name "minimind" --port 8998
```
## [llama.cpp](https://github.com/ggerganov/llama.cpp)
llama.cpp是一个C++库,
可以在命令行下直接使用,支持多线程推理,支持GPU加速。
**目录结构**:建议将llama.cpp与minimind放在同级目录下
```
parent/
├── minimind/ # MiniMind项目目录
│ ├── MiniMind2/ # HuggingFace格式MiniMind2模型 (先convert_model.py生成)
│ │ ├── config.json
│ │ ├── model.safetensors
│ │ └── ...
│ ├── model/
│ ├── trainer/
│ └── ...
└── llama.cpp/ # llama.cpp项目目录
├── build/
├── convert_hf_to_gguf.py
└── ...
```
0、参考`llama.cpp`官方步骤进行install
1、在`convert_hf_to_gguf.py`的`get_vocab_base_pre`函数最后插入:
```python
# 添加MiniMind tokenizer支持(这里随便写一个例如qwen2即可)
if res is None:
res = "qwen2"
```
2、转换自训练的minimind模型:huggingface -> gguf
```bash
# 在llama.cpp下执行,将生成../minimind/MiniMind2/MiniMind2-xxx.gguf
python convert_hf_to_gguf.py ../minimind/MiniMind2
```
3、量化此模型 (可选)
```bash
./build/bin/llama-quantize ../minimind/MiniMind2/MiniMind2.gguf ../minimind/MiniMind2/Q4-MiniMind2.gguf Q4_K_M
```
4、命令行推理测试
```bash
./build/bin/llama-cli -m ../minimind/MiniMind2/MiniMind2.gguf -sys "You are a helpful assistant" # system prompt必须固定
```
## [ollama](https://ollama.ai)
ollama是本地运行大模型的工具,支持多种开源LLM,简单易用。
1、通过ollama加载自定义的gguf模型
在`MiniMind2`下新建`minimind.modelfile`,写入:
```text
FROM ./Q4-MiniMind2.gguf
SYSTEM """You are a helpful assistant"""
TEMPLATE """<|im_start|>system
{{ .System }}<|im_end|>
<|im_start|>user
{{ .Prompt }}<|im_end|>
<|im_start|>assistant
{{ .Response }}<|im_end|>
"""
```
2、加载并命名此模型为`minimind-local`
```bash
ollama create -f minimind.modelfile minimind-local
```
3、启动推理
```bash
ollama run minimind-local
```
📤 推送你的模型到 Ollama Hub
```bash
# 1. 为本地模型重命名为你的ollama-account/minimind的tag
ollama cp minimind-local:latest your_username/minimind:latest
# 2. 推送模型
ollama push your_username/minimind:latest
```
⭐️ 也可直接使用我提供的ollama模型一键启动:
```bash
ollama run jingyaogong/minimind2 # 其他可选 minimind2-r1 / minimind2-small / minimind2-small-r1
>>> 你叫什么名字
我是一个语言模型...
```
## [MNN](https://github.com/alibaba/MNN)
MNN是面向端侧的AI推理引擎,支持多种开源LLM模型推理,轻量化、高性能。
1. 模型转换
```
cd MNN/transformers/llm/export
# 导出4bit HQQ量化的MNN模型
python llmexport.py --path /path/to/MiniMind2/ --export mnn --hqq --dst_path MiniMind2-MNN
```
2. 在Mac或手机上测试
```
./llm_demo /path/to/MiniMind2-MNN/config.json prompt.txt
```
或者下载APP测试
> 以上三方框架的更多用法请参考对应官方文档😊
# 📌 Acknowledge
> [!NOTE]
> 如果觉得`MiniMind系列`对您有所帮助,可以在 GitHub 上加一个⭐
> 篇幅超长水平有限难免纰漏,欢迎在Issues交流指正或提交PR改进项目
> 您的小小支持就是持续改进此项目的动力!
## 🤝[贡献者](https://github.com/jingyaogong/minimind/graphs/contributors)
## 😊鸣谢
@ipfgao :
🔗训练步骤记录
@WangRongsheng :
🔗大型数据集预处理
@pengqianhan :
🔗一个简明教程
@RyanSunn :
🔗推理过程学习记录
@Nijikadesu :
🔗以交互笔记本方式分解项目代码
参考链接 & 感谢以下优秀的论文或项目
- 排名不分任何先后顺序
- [https://github.com/meta-llama/llama3](https://github.com/meta-llama/llama3)
- [https://github.com/karpathy/llama2.c](https://github.com/karpathy/llama2.c)
- [https://github.com/DLLXW/baby-llama2-chinese](https://github.com/DLLXW/baby-llama2-chinese)
- [(DeepSeek-V2)https://arxiv.org/abs/2405.04434](https://arxiv.org/abs/2405.04434)
- [https://github.com/charent/ChatLM-mini-Chinese](https://github.com/charent/ChatLM-mini-Chinese)
- [https://github.com/wdndev/tiny-llm-zh](https://github.com/wdndev/tiny-llm-zh)
- [(Mistral-MoE)https://arxiv.org/pdf/2401.04088](https://arxiv.org/pdf/2401.04088)
- [https://github.com/Tongjilibo/build_MiniLLM_from_scratch](https://github.com/Tongjilibo/build_MiniLLM_from_scratch)
- [https://github.com/jzhang38/TinyLlama](https://github.com/jzhang38/TinyLlama)
- [https://github.com/AI-Study-Han/Zero-Chatgpt](https://github.com/AI-Study-Han/Zero-Chatgpt)
- [https://github.com/xusenlinzy/api-for-open-llm](https://github.com/xusenlinzy/api-for-open-llm)
- [https://github.com/HqWu-HITCS/Awesome-Chinese-LLM](https://github.com/HqWu-HITCS/Awesome-Chinese-LLM)
## 🫶支持者
## 🎉 Awesome Work using MiniMind
本模型抛砖引玉地促成了一些可喜成果的落地,感谢研究者们的认可:
- ECG-Expert-QA: A Benchmark for Evaluating Medical Large Language Models in Heart Disease Diagnosis [[arxiv](https://arxiv.org/pdf/2502.17475)]
- Binary-Integer-Programming Based Algorithm for Expert Load Balancing in Mixture-of-Experts Models [[arxiv](https://arxiv.org/pdf/2502.15451)]
- LegalEval-Q: A New Benchmark for The Quality Evaluation of LLM-Generated Legal Text [[arxiv](https://arxiv.org/pdf/2505.24826)]
- On the Generalization Ability of Next-Token-Prediction Pretraining [[ICML 2025](https://openreview.net/forum?id=hLGJ1qZPdu)]
- 《从零开始写大模型:从神经网络到Transformer》王双、牟晨、王昊怡 编著 - 清华大学出版社
- FedBRB: A Solution to the Small-to-Large Scenario in Device-Heterogeneity Federated Learning [[TMC 2025](https://ieeexplore.ieee.org/abstract/document/11168259)]
- 进行中...
# 🎓 Citation
If you find MiniMind helpful in your research or work, please cite:
```bibtex
@misc{minimind,
title={MiniMind: Train a Tiny LLM from scratch},
author={Jingyao Gong},
year={2024},
howpublished={https://github.com/jingyaogong/minimind}
}
```
# License
This repository is licensed under the [Apache-2.0 License](LICENSE).
================================================
FILE: README_en.md
================================================


[](https://github.com/jingyaogong/minimind/stargazers)
[](LICENSE)
[](https://github.com/jingyaogong/minimind/commits/master)
[](https://github.com/jingyaogong/minimind/pulls)
[](https://huggingface.co/collections/jingyaogong/minimind-66caf8d999f5c7fa64f399e5)

"The Simplest Path is the Greatest"
[中文](./README.md) | English
* This open-source project aims to train a super-small language model **MiniMind** with only 3 RMB cost and 2 hours,
starting completely from scratch.
* The **MiniMind** series is extremely lightweight, with the smallest version being $\frac{1}{7000}$ the size of GPT-3,
making it possible to train quickly on even the most ordinary personal GPUs.
* The project also open-sources the minimalist structure of the large model, including extensions for shared mixed
experts (MoE), dataset cleaning, pretraining, supervised fine-tuning (SFT), LoRA fine-tuning, direct preference
optimization (DPO) algorithms, reinforcement learning from AI feedback (RLAIF: PPO/GRPO/SPO), and model distillation
algorithms, along with the full code of the entire process.
* **MiniMind** also expands into vision multimodal VLM: [MiniMind-V](https://github.com/jingyaogong/minimind-v).
* All core algorithm code is reconstructed from scratch using native PyTorch! It does not rely on abstract interfaces
provided by third-party libraries.
* This is not only a full-stage open-source reproduction of a large language model but also a tutorial for beginners in
LLM.
* We hope this project will serve as an inspiring example for everyone, helping to enjoy the fun of creation and
promoting the progress of the wider AI community!
> To avoid misunderstanding, the "2 hours" test is based on NVIDIA 3090 hardware (single GPU), and the "3 RMB" refers to the GPU server rental cost. Details of the specifications can be found below.
---

[🔗🍓Reason Model](https://www.modelscope.cn/studios/gongjy/MiniMind-Reasoning) | [🔗🤖Standard Model](https://www.modelscope.cn/studios/gongjy/MiniMind) | [🔗🎞️Video Introduction](https://www.bilibili.com/video/BV12dHPeqE72/?share_source=copy_web&vd_source=670c2504f88726f8cf4a21ef6147c0e8)
# 📌 Introduction
The emergence of Large Language Models (LLMs) has sparked unprecedented global attention to AI.
Whether it's ChatGPT, DeepSeek, or Qwen, they all demonstrate stunning performance that is awe-inspiring.
However, with their massive scale of tens of billions of parameters, they are not only difficult to train on personal devices but nearly impossible to deploy.
Opening the "black box" of large models to explore their internal mechanisms is truly thrilling!
Unfortunately, 99% of exploration can only stop at using techniques like LoRA to perform minor fine-tuning on existing large models to learn new instructions or tasks.
This is like teaching Newton how to use a 21st-century smartphone—while interesting, it completely deviates from the original intent of understanding the essence of physics.
Meanwhile, third-party large model frameworks and toolkits, such as transformers+trl, expose only highly abstract interfaces.
With just 10 lines of code, you can complete the entire workflow of "loading model + loading dataset + inference + reinforcement learning."
While such efficient packaging is convenient, it also acts like a high-speed spacecraft, isolating developers from underlying implementations and hindering deep exploration of LLM core code.
Yet, "building a plane with Lego is far more exciting than flying in first class!"
What's worse, the internet is flooded with expensive courses and marketing accounts selling AI tutorials with countless flaws and superficial understanding.
For this reason, this project's original intention is to lower the barrier to entry for LLM learning, allowing everyone to start by understanding every line of code,
to personally train an extremely small language model from scratch. Yes, from **training from scratch**, not just **inference**!
With less than 3 RMB in server costs, you can personally experience the entire process of building a language model from 0 to 1.
Let's enjoy the fun of creation together!
> [!NOTE]
> (As of 2025-10) The MiniMind series has completed pretraining of multiple model variants, with the smallest being only 25.8M (0.02B), capable of fluent conversation!
Models List
| Model (Size) | Inference Memory (Approx) | Release |
|------------------------|---------------------------|------------|
| MiniMind2-small (26M) | 0.5 GB | 2025.04.26 |
| MiniMind2-MoE (145M) | 1.0 GB | 2025.04.26 |
| MiniMind2 (104M) | 1.0 GB | 2025.04.26 |
| minimind-v1-small (26M)| 0.5 GB | 2024.08.28 |
| minimind-v1-moe (4×26M)| 1.0 GB | 2024.09.17 |
| minimind-v1 (108M) | 1.0 GB | 2024.09.01 |
**Project Includes**
- Complete code for MiniMind-LLM structure (Dense + MoE models).
- Detailed training code for Tokenizer.
- Complete training code for Pretrain, SFT, LoRA, RLHF-DPO, RLAIF (PPO/GRPO/SPO), and model distillation.
- Collected, distilled, organized and cleaned high-quality datasets for all stages, all open-sourced.
- Implemented from scratch: pretraining, instruction fine-tuning, LoRA, DPO/PPO/GRPO/SPO reinforcement learning, and white-box model distillation. Core algorithms barely depend on third-party framework encapsulation, all open-sourced.
- Compatible with mainstream third-party frameworks like `transformers`, `trl`, `peft`.
- Training supports single GPU, multiple GPUs on a single machine (DDP, DeepSpeed), supports wandb/swanlab visualization of training process. Supports dynamic training start/stop.
- Model testing on third-party evaluation leaderboards (C-Eval, C-MMLU, OpenBookQA, etc.), supports YaRN algorithm for RoPE long-text extrapolation.
- Implements an extremely simple OpenAI API-compliant server, convenient for integration with third-party ChatUI (FastGPT, Open-WebUI, etc.).
- Implements the simplest chat WebUI frontend based on streamlit.
- Fully compatible with popular community inference engines `llama.cpp`, `vllm`, `ollama` or training framework `Llama-Factory`.
- Reproduced (distilled/RL) DeepSeek-R1 reasoning model as MiniMind-Reason model, with **data + models** fully open-sourced!
We hope this open-source project can help LLM beginners get started quickly!
### 👉**Update Log**
2025-10-24
- 🔥 Added RLAIF training algorithms: PPO, GRPO, SPO (native implementation from scratch)
- Added checkpoint resume training: supports automatic training recovery, cross-GPU recovery, wandb continuity
- Added RLAIF dataset: rlaif-mini.jsonl (randomly sampled 10,000 entries from SFT data); simplified DPO dataset with Chinese data
- Added YaRN algorithm: supports RoPE long-text extrapolation, improving long sequence handling capability
- Adaptive Thinking: Reason model can optionally enable thinking chain
- chat_template fully supports Tool Calling and Reasoning tags (``, ``, etc.)
- Added complete RLAIF chapter, training curve comparison, algorithm principle explanations
- [SwanLab](https://swanlab.cn/) replaces WandB (friendly for domestic access, fully compatible API)
- Code standardization & fixed some known bugs
2025-04-26
- Important update
- For compatibility needs, you can visit [🔗old repository content🔗](https://github.com/jingyaogong/minimind/tree/7da201a944a90ed49daef8a0265c959288dff83a).
- MiniMind model parameters completely renamed, aligned with Transformers library models (unified naming).
- generate method refactored, inheriting from GenerationMixin class.
- 🔥 Supports popular third-party ecosystems like llama.cpp, vllm, ollama.
- Standardized code and directory structure.
- Modified vocabulary ` `->`<|im_start|><|im_end|>`
```text
To be compatible with third-party inference frameworks llama.cpp and vllm, this update requires some observable costs.
This update no longer supports "directly" loading old models before 25-04-26 for inference.
Due to differences in Llama's positional encoding compared to minimind, there are differences in QK values after mapping Llama models.
MiniMind2 series old models have been recovered through weight mapping and (fine-tuning training) QKVO linear layer calibration.
After this update, maintenance of the entire minimind-v1 series will be abandoned and removed from the repository.
```
2025-02-09
- Major update since release, Release MiniMind2 Series.
- Code almost completely refactored, using cleaner and more unified structure.
For compatibility with old code, you can visit [🔗old repository content🔗](https://github.com/jingyaogong/minimind/tree/6e9cd28ef9b34a0a10afbdf6f59e65cb6e628efb).
- Eliminated data preprocessing steps. Unified dataset format, switched to `jsonl` format to avoid dataset download confusion.
- MiniMind2 series shows significant improvement compared to MiniMind-V1.
- Minor improvements: {more standard kv-cache writing, MoE load balancing loss considered, etc.}
- Provides training solutions for model migration to private datasets (medical models, self-awareness examples).
- Streamlined pretraining dataset and significantly improved pretraining data quality, greatly reducing time for quick personal training, single 3090 GPU can reproduce in 2 hours!
- Updates: LoRA fine-tuning separated from peft packaging, implemented from scratch; DPO algorithm implemented from scratch using native PyTorch; white-box model distillation native implementation.
- MiniMind2-DeepSeek-R1 series distilled models born!
- MiniMind2 now has some English ability!
- Updated MiniMind2 and third-party model performance results based on more large model leaderboard tests.
More...
**2024-10-05**
- Extended MiniMind with multimodal capabilities---Vision
- Check out the twin project [minimind-v](https://github.com/jingyaogong/minimind-v) for details!
**2024-09-27**
- 09-27 updated the preprocessing method for the pretrain dataset, abandoned preprocessing into .bin format for training to ensure text integrity (slightly sacrificing training speed).
- Current pretrain preprocessing file is named: pretrain_data.csv.
- Removed some redundant code.
**2024-09-17**
- Updated minimind-v1-moe model
- To avoid ambiguity, no longer using mistral_tokenizer for tokenization, completely using custom minimind_tokenizer as the tokenizer.
**2024-09-01**
- Updated minimind-v1 (108M) model, using minimind_tokenizer, 3 pretraining rounds + 10 SFT rounds, more thorough training, stronger performance.
- Project has been deployed to ModelScope creation space, you can experience it on this website:
- [🔗ModelScope Online Experience🔗](https://www.modelscope.cn/studios/gongjy/minimind)
**2024-08-27**
- Project first open-sourced
# 📌 Quick Start
Share my hardware and software configuration (for reference only)
* CPU: Intel(R) Core(TM) i9-10980XE CPU @ 3.00GHz
* RAM: 128 GB
* GPU: NVIDIA GeForce RTX 3090(24GB) * 8
* Ubuntu==20.04
* CUDA==12.2
* Python==3.10.16
* [requirements.txt](./requirements.txt)
### Step 0
```bash
git clone https://github.com/jingyaogong/minimind.git
```
## Ⅰ Testing Existing Model Performance
### 1. Environment Setup
```bash
pip install -r requirements.txt -i https://mirrors.aliyun.com/pypi/simple
```
### 2. Download Model
Go to the project root directory
```bash
git clone https://huggingface.co/jingyaogong/MiniMind2 # or https://www.modelscope.cn/models/gongjy/MiniMind2
```
### (Optional) Command Line Q&A
```bash
# Use transformers format model
python eval_llm.py --load_from ./MiniMind2
```
### (Optional) Launch WebUI
```bash
# May require `python>=3.10`, install with `pip install streamlit`
# cd scripts
streamlit run web_demo.py
```
### (Optional) Third-party Inference Frameworks
```bash
# ollama
ollama run jingyaogong/minimind2
# vllm
vllm serve ./MiniMind2/ --served-model-name "minimind"
```
## Ⅱ Train from Scratch Yourself
### 1. Environment Setup
```bash
pip install -r requirements.txt -i https://mirrors.aliyun.com/pypi/simple
```
Note: Test Torch CUDA availability in advance
```bash
import torch
print(torch.cuda.is_available())
```
If not available, please download and install the whl file from [torch_stable](https://download.pytorch.org/whl/torch_stable.html). Reference [link](https://blog.csdn.net/weixin_45456738/article/details/141029610?ops_request_misc=&request_id=&biz_id=102&utm_term=%E5%AE%89%E8%A3%85torch&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduweb~default-2-141029610.nonecase&spm=1018.2226.3001.4187)
### 2. Download Data
Download the required data files from the [dataset download link](https://www.modelscope.cn/datasets/gongjy/minimind_dataset/files) provided below (create the `./dataset` directory) and place them in `./dataset`
Note: Dataset Notes
By default, it is recommended to download `pretrain_hq.jsonl` + `sft_mini_512.jsonl` for the fastest reproduction of the Zero chat model.
You can freely choose data files. The section below provides multiple combination schemes that can be appropriately combined based on your training needs and GPU resources.
### 3. Start Training
Directory is located in `trainer`
💡 Checkpoint Resume Training
All training scripts automatically save checkpoints. Simply add `--from_resume 1` parameter to automatically detect, load & resume training:
```bash
python train_pretrain.py --from_resume 1
python train_full_sft.py --from_resume 1
...
```
**Checkpoint Resume Mechanism:**
- Training process automatically saves complete checkpoints in `./checkpoints/` directory (model, optimizer, training progress, etc.)
- Checkpoint file naming: `__resume.pth` (e.g., `full_sft_512_resume.pth`)
- Supports cross-GPU recovery (automatically adjusts step)
- Supports wandb training log continuity (automatically resumes the same run)
> Suitable for long training sessions or unstable environments, no need to worry about progress loss from interruptions
**3.1 Pretraining (Learning Knowledge)**
```bash
python train_pretrain.py
```
> Execute pretraining to get `pretrain_*.pth` as the output weights for pretraining (where * is the model's dimension, default is 512)
**3.2 Supervised Fine-tuning (Learning Conversation Style)**
```bash
python train_full_sft.py
```
> Execute supervised fine-tuning to get `full_sft_*.pth` as the output weights for instruction fine-tuning (where `full` means full-parameter fine-tuning)
Note: Training Notes
By default, all training processes save parameters to the file `./out/***.pth` every 100 steps (each save overwrites the old weights).
For simplicity, only the two-stage training process is described here. For other training (LoRA, distillation, reinforcement learning, inference fine-tuning, etc.), refer to the detailed description in the [Experiment](#-experiment) section below.
---
### 4. Test Your Trained Model
Ensure the model `*.pth` files to be tested are in the `./out/` directory.
You can also directly download and use the `*.pth` files I trained from [here](https://www.modelscope.cn/models/gongjy/MiniMind2-PyTorch/files).
```bash
python eval_llm.py --weight full_sft # or pretrain/dpo/ppo/grpo...
```
Note: Testing Notes
The `--weight` parameter specifies the weight name prefix. Options: `pretrain`, `full_sft`, `dpo`, `reason`, `ppo_actor`, `grpo`, `spo`, etc.
Other common parameters:
- `--load_from`: Model loading path (`model`=native torch weights, other paths=transformers format)
- `--save_dir`: Model weight directory (default `out`)
- `--lora_weight`: LoRA weight name (`None` means not used)
- `--historys`: Number of historical dialogue rounds to carry (must be even, 0 means no history)
- `--max_new_tokens`: Maximum generation length (default 8192)
- `--temperature`: Generation temperature (default 0.85)
- `--top_p`: Nucleus sampling threshold (default 0.85)
For usage details, refer directly to the `eval_llm.py` code.
---
> [!TIP]
> All training scripts are native PyTorch framework, supporting multi-GPU acceleration. Assume your device has N (N > 1) GPUs:
Single machine N GPU training startup (DDP, supports multi-machine multi-GPU cluster)
```bash
torchrun --nproc_per_node N train_xxx.py
```
Note: Other Notes
Single machine N GPU training (DeepSpeed)
```bash
deepspeed --master_port 29500 --num_gpus=N train_xxx.py
```
You can optionally enable wandb to record the training process (requires direct internet connection)
```bash
# Requires login: wandb login
torchrun --nproc_per_node N train_xxx.py --use_wandb
# and
python train_xxx.py --use_wandb
```
By adding the `--use_wandb` parameter, you can record the training process. After training is complete, you can view the training process on the wandb website. By modifying the `wandb_project` and `wandb_run_name` parameters, you can specify the project name and run name.
[Note]: After June 2025, the domestic network environment cannot directly connect to WandB. The MiniMind project by default switches to using [SwanLab](https://swanlab.cn/) as the training visualization tool (fully compatible with WandB API), that is, just change `import wandb` to `import swanlab as wandb`, no other changes are needed.
# 📌 Data Introduction
## Ⅰ Tokenizer
Tokenizer maps words from natural language to numbers like `0, 1, 36` through a "dictionary," which can be understood as numbers representing the page number of the word in the "dictionary."
You can choose to construct your own vocabulary table to train a "dictionary." The code can be found in `./trainer/train_tokenizer.py` (for learning reference only. It's not necessary to train one yourself unless required. MiniMind comes with a built-in tokenizer).
Or you can choose tokenizers from well-known open-source large models.
Just as using Xinhua/Oxford dictionaries directly has the advantage of good token encoding compression, but the disadvantage of having too many pages—tens of thousands of word phrases;
A self-trained tokenizer has the advantage of freely controlling vocabulary length and content, but the disadvantage of low compression ratio (for example, "hello" might be split into "h e l l o"
five independent tokens), and rare words are difficult to cover.
The choice of "dictionary" is important. The output of LLM is essentially a multi-class classification problem with SoftMax to N words in the dictionary, then decoding to natural language through the "dictionary."
Because MiniMind size needs to be strictly controlled to avoid top-heavy models (embedding layer parameters taking up too high a proportion of LLM), shorter vocabulary lengths are better.
Tokenizer Introduction
The tokenizer vocabulary sizes of powerful open-source models from third parties such as Yi, qwen, chatglm, mistral, and Llama3 are as follows:
Tokenizer Model Vocabulary Size Source
yi tokenizer 64,000 01AI (China)
qwen2 tokenizer 151,643 Alibaba Cloud (China)
glm tokenizer 151,329 Zhipu AI (China)
mistral tokenizer 32,000 Mistral AI (France)
llama3 tokenizer 128,000 Meta (USA)
minimind tokenizer 6,400 Custom
> 👉 Updated 2024-09-17: To prevent ambiguity from previous versions and control size, all MiniMind models use minimind_tokenizer for tokenization, abandoning all mistral_tokenizer versions.
```
# Some thoughts
> Although minimind_tokenizer has a small length, its encoding/decoding efficiency is weaker than Chinese-friendly tokenizers like qwen2 and glm.
> But the minimind model chose the self-trained minimind_tokenizer as the tokenizer to maintain lightweight overall parameters, avoiding imbalance in encoding layer and computation layer proportions, preventing top-heavy models, because minimind's vocabulary size is only 6400.
> And minimind has never encountered rare word decoding failures in actual testing, with good results.
> Due to the custom vocabulary compression to 6400, the total LLM parameters are as low as 25.8M.
> The training data `pretrain_hq.jsonl` all comes from the `JiangShu large model dataset`, this part of data is relatively secondary. You can freely choose if you need to train.
```
## Ⅱ Pretraining Data
Having learned from MiniMind-V1's low-quality pretraining data that caused models to talk nonsense, after `2025-02-05` we decided no longer to use large-scale unsupervised datasets for pretraining.
Instead, we tried to extract the Chinese portion from the [JiangShu Large Model Dataset](https://www.modelscope.cn/datasets/deepctrl/deepctrl-sft-data),
Clean out about 1.6GB of corpus with character length `<512` and concatenate them directly as pretraining data `pretrain_hq.jsonl`, where hq means high
quality (of course it's not yet high, improving data quality is endless).
The file `pretrain_hq.jsonl` data format is
```json
{"text": "How can I get rid of procrastination? Curing procrastination is not easy, but the following suggestions may help..."}
```
## Ⅲ SFT Data
The [JiangShu Large Model SFT Dataset](https://www.modelscope.cn/datasets/deepctrl/deepctrl-sft-data)
"is a complete, uniformly formatted, and safe large model training and research resource.
It collected and organized a large amount of open-source datasets from public sources on the internet, unified their format, cleaned the data,
containing Chinese datasets with 10M entries and English datasets with 2M entries."
The above is the official introduction. After downloading, the total data volume is about 4B tokens, which is definitely suitable as SFT data for Chinese large language models.
However, the official data format is messy, and using all of it for SFT would be too expensive.
I performed secondary cleaning of the official dataset, removing entries with symbol pollution and noise; additionally, still only kept content with total length `<512`,
hoping to supplement knowledge lacking in the pretraining phase through large amounts of dialogue at this stage.
Export file is `sft_512.jsonl` (~7.5GB).
The [Magpie-SFT Dataset](https://www.modelscope.cn/organization/Magpie-Align)
collected ~1M high-quality conversations from Qwen2/2.5. I further cleaned this data, exporting the portion with total length `<2048` as `sft_2048.jsonl` (~9GB).
The portion with length `<1024` exported as `sft_1024.jsonl` (~5.5GB). Using large model dialogue data directly for sft falls into the "black-box distillation" category.
Further cleaned the SFT data from the previous two steps (keeping only content with high Chinese character ratio), filtered conversations with length `<512`, and obtained `sft_mini_512.jsonl` (~1.2GB).
The data format for all sft files `sft_X.jsonl` is
```text
{
"conversations": [
{"role": "user", "content": "Hello"},
{"role": "assistant", "content": "Hello!"},
{"role": "user", "content": "Goodbye"},
{"role": "assistant", "content": "Goodbye!"}
]
}
```
## Ⅳ RLHF Data
From the [Magpie-DPO Dataset](https://www.modelscope.cn/datasets/Magpie-Align/MagpieLM-DPO-Data-v0.1)
approximately 200k preference data entries (all in English) generated from Llama3.1-70B/8B, can be used to train reward models, optimize model reply quality, making it more consistent with human preferences.
Here, we reorganized content with total data length `<3000` into `dpo.jsonl` (~0.9GB), containing two fields `chosen` and `rejected`, where `chosen`
is the preferred reply and `rejected` is the rejected reply.
The file `dpo.jsonl` data format is
```text
{
"chosen": [
{"content": "Q", "role": "user"},
{"content": "good answer", "role": "assistant"}
],
"rejected": [
{"content": "Q", "role": "user"},
{"content": "bad answer", "role": "assistant"}
]
}
```
## Ⅴ Reasoning Dataset:
There's no denying that in February 2025, who can be hotter than DeepSeek...
It also sparked my strong interest in RL-guided reasoning models. I've already reproduced R1-Zero using Qwen2.5.
If I have time + good results (but 99% of base models lack ability), I will later update MiniMind with RL-trained reasoning models rather than distilled models.
With limited time, the fastest low-cost solution is still direct distillation (black-box method).
Unable to resist R1's popularity, in just a few days there are already various R1 distillation datasets like [R1-Llama-70B](https://www.modelscope.cn/datasets/Magpie-Align/Magpie-Reasoning-V2-250K-CoT-Deepseek-R1-Llama-70B), [R1-Distill-SFT](https://www.modelscope.cn/datasets/AI-ModelScope/R1-Distill-SFT),
[Alpaca-Distill-R1](https://huggingface.co/datasets/shareAI/Alpaca-Distill-R1-ZH),
[deepseek_r1_zh](https://huggingface.co/datasets/jinliuxi/deepseek_r1_zh) and so on. Pure Chinese data is relatively scarce.
Finally integrated them, export file as `r1_mix_1024.jsonl`, data format consistent with `sft_X.jsonl`.
## Ⅵ More Datasets
Currently, [HqWu-HITCS/Awesome-Chinese-LLM](https://github.com/HqWu-HITCS/Awesome-Chinese-LLM)
is collecting and organizing materials related to Chinese LLMs including open-source models, applications, datasets, and tutorials, and continuously updating the latest progress in this field. Comprehensive and professional, Respect!
---
## Ⅷ MiniMind Training Datasets
> [!NOTE]
> After 2025-02-05, all datasets used for final MiniMind training are open-sourced. Therefore, you don't need to preprocess large-scale datasets yourself, avoiding repetitive data processing work.
MiniMind Training Dataset Download: [ModelScope](https://www.modelscope.cn/datasets/gongjy/minimind_dataset/files) | [HuggingFace](https://huggingface.co/datasets/jingyaogong/minimind_dataset/tree/main)
> No need to clone everything, you can download the files you need individually
Place the downloaded dataset files in the `./dataset/` directory (✨ are recommended required items)
```bash
./dataset/
├── dpo.jsonl (55MB, ✨)
├── lora_identity.jsonl (22.8KB)
├── lora_medical.jsonl (34MB)
├── pretrain_hq.jsonl (1.6GB, ✨)
├── r1_mix_1024.jsonl (340MB)
├── rlaif-mini.jsonl (1MB, ✨)
├── sft_1024.jsonl (5.6GB)
├── sft_2048.jsonl (9GB)
├── sft_512.jsonl (7.5GB)
└── sft_mini_512.jsonl (1.2GB, ✨)
```
Note: Brief Description of Each Dataset
* `dpo.jsonl`✨ --RLHF stage dataset (optimized and simplified, suitable for fast training)
* `lora_identity.jsonl` --Self-awareness dataset (e.g., Who are you? I am minimind...), recommended for lora training (can also be used for full-parameter SFT, don't be limited by the name)
* `lora_medical.jsonl` --Medical Q&A dataset, recommended for lora training (can also be used for full-parameter SFT, don't be limited by the name)
* `pretrain_hq.jsonl`✨ --Pretraining dataset, integrated from JiangShu Technology (recommended `max_seq_len≈320`)
* `r1_mix_1024.jsonl` --DeepSeek-R1-1.5B distilled data, maximum character length per entry is 1024 (recommended `max_seq_len≈720`)
* `rlaif-mini.jsonl` --RLAIF training dataset, randomly sampled 10,000 high-quality conversations from SFT dataset for training reinforcement learning algorithms like PPO/GRPO/SPO
* `sft_1024.jsonl` --Integrated from Qwen2.5 distilled data (a subset of sft_2048), maximum character length per entry is 1024 (recommended `max_seq_len≈650`)
* `sft_2048.jsonl` --Integrated from Qwen2.5 distilled data, maximum character length per entry is 2048 (recommended `max_seq_len≈1400`)
* `sft_512.jsonl` --Integrated from JiangShu Technology SFT data, maximum character length per entry is 512 (recommended `max_seq_len≈350`)
* `sft_mini_512.jsonl`✨ --Minimal integration from JiangShu Technology SFT data + Qwen2.5 distilled data (for quick training of Zero models), maximum character length per entry is 512 (recommended `max_seq_len≈340`)
Training parameter `max_seq_len` currently refers to the **token length**, not the absolute number of characters.
For this project's tokenizer, typical Chinese text is roughly `1.5~1.7 chars/token`, while pure English text is roughly `4~5 chars/token` (it varies with data distribution).
The “max length” annotated in dataset names is measured in **characters**. For example, a 100-character Chinese string can be roughly converted to `100/1.5≈67` tokens.
For example:
* Chinese: `白日依山尽` (5 chars) may be tokenized into [`白日`, `依`, `山`, `尽`] (4 tokens)
* English: `The sun sets in the west` (24 chars) may be tokenized into [`The `, `sun `, `sets `, `in `, `the`, `west`] (6 tokens)
The “recommended setting” above provides a rough estimate of the max token length for each dataset.
Note that `max_seq_len` can be tuned aggressively / conservatively / in a balanced way: a larger value increases padding waste, while a smaller value increases truncation.
Just find a balance between `compute efficiency` <---> `semantic completeness`.

Instructions & Recommended Training Schemes
* MiniMind2 Series was trained on approximately 20GB of corpus in total, about 4B tokens, corresponding to the data combination training results above (cost: 💰💰💰💰💰💰💰💰, results: 😊😊😊😊😊😊)
* For the fastest speed to implement Zero model from scratch, we recommend using the data combination of `pretrain_hq.jsonl` + `sft_mini_512.jsonl`, specific cost and results can be seen in the table below (cost: 💰, results: 😊😊)
* For friends with certain computing resources or those who care more about results, you can consider the former to fully reproduce MiniMind2; for those with only single GPU or who care about quick reproduction in short time, we highly recommend the latter;
* [Compromise solution] You can also choose medium-sized data like `sft_mini_512.jsonl`, `sft_1024.jsonl` for free combination training (cost: 💰💰💰, results: 😊😊😊😊).
# 📌 Model
## Structure
MiniMind-Dense (same as [Llama3.1](https://ai.meta.com/blog/meta-llama-3-1/)) uses the Transformer Decoder-Only structure. The differences from GPT-3 are:
* Adopts GPT-3's pre-normalization method, normalizing at the input of each Transformer sub-layer rather than at the output. Specifically, it uses the RMSNorm normalization function.
* Replaced ReLU with SwiGLU activation function to improve performance.
* Like GPT-Neo, it removed absolute position embeddings and switched to rotary position embeddings (RoPE), which works better when handling inference beyond training length.
---
MiniMind-MoE model structure is based on Llama3 and the MixFFN mixture-of-experts module from [Deepseek-V2/3](https://arxiv.org/pdf/2405.04434).
* DeepSeek-V2 in feed-forward networks (FFN) uses finer-grained expert splitting and shared expert isolation techniques to improve the effect of Experts.
---
MiniMind's overall structure is consistent, with only small adjustments in RoPE computation, inference functions, and FFN layer code.
The structure is shown in the diagram below (redrawn version):


To modify model configuration, see [./model/model_minimind.py](./model/model_minimind.py).
Reference model parameter versions see the table below:
| Model Name | params | len_vocab | rope_theta | n_layers | d_model | kv_heads | q_heads | share+route |
|-------------------|--------|-----------|------------|----------|---------|----------|---------|-------------|
| MiniMind2-Small | 26M | 6400 | 1e6 | 8 | 512 | 2 | 8 | - |
| MiniMind2-MoE | 145M | 6400 | 1e6 | 8 | 640 | 2 | 8 | 1+4 |
| MiniMind2 | 104M | 6400 | 1e6 | 16 | 768 | 2 | 8 | - |
| minimind-v1-small | 26M | 6400 | 1e4 | 8 | 512 | 8 | 16 | - |
| minimind-v1-moe | 4×26M | 6400 | 1e4 | 8 | 512 | 8 | 16 | 1+4 |
| minimind-v1 | 108M | 6400 | 1e4 | 16 | 768 | 8 | 16 | - |
## Model Configuration
📋 Regarding LLM parameter configuration, there's an interesting paper [MobileLLM](https://arxiv.org/pdf/2402.14905) that conducted detailed research and experiments.
Scaling Law has its own unique patterns in small models.
Parameters causing Transformer parameter scaling changes almost entirely depend on `d_model` and `n_layers`.
* `d_model`↑ + `n_layers`↓ -> Wide and short
* `d_model`↓ + `n_layers`↑ -> Narrow and tall
The 2020 Scaling Law paper argued that training data volume, parameter quantity, and training iterations are the key factors determining performance, while model architecture influence is negligible.
However, this law doesn't seem to fully apply to small models.
MobileLLM argues that architecture depth is more important than width, "deep and narrow" "tall and skinny" models can learn more abstract concepts than "wide and shallow" models.
For example, when model parameters are fixed at 125M or 350M, 30-42 layer "narrow" models clearly have superior performance compared to around 12 layer "wide" models,
showing similar trends across 8 benchmark tests including commonsense reasoning, Q&A, and reading comprehension.
This is actually a very interesting discovery, because previously when designing architectures for ~100M scale small models, almost no one tried stacking more than 12 layers.
This is consistent with what MiniMind observed in experiments when adjusting model parameters between `d_model` and `n_layers` during training.
However, "deep and narrow" models also have dimensional limits. When d_model<512, the disadvantage of embedding dimension collapse is very obvious,
and added layers cannot compensate for the disadvantage of insufficient d_head caused by fixed q_head in embeddings.
When d_model>1536, increasing layers seems to have higher priority than d_model, bringing more "cost-effective" parameter -> performance gains.
* Therefore MiniMind sets small model dim=512, n_layers=8 to achieve the balance of "extremely small size <-> better performance."
* Setting dim=768, n_layers=16 to gain larger performance improvements, more consistent with small model Scaling-Law curves.
For reference, GPT3 parameter settings see the table below:

---
# 📌 Experiment
## Ⅰ Training Costs
- **Time unit**: Hours (h).
- **Cost unit**: Chinese Yuan (¥); 7¥ ≈ 1 USD.
- **3090 rental price**: ≈1.3¥/h (you can check current prices yourself).
- **Reference standard**: The table only shows actual measured training time for `pretrain` and `sft_mini_512` two datasets. Other time costs are estimated based on dataset size (may have slight variations).
> Based on 3090 (single GPU) cost calculation
| Model Name | params | pretrain | sft_mini_512 | sft_512 | sft_1024 | sft_2048 | RLHF |
|-----------------|--------|------------------|------------------|---------------|-------------------|------------------|---------------|
| MiniMind2-Small | 26M | ≈1.1h ≈1.43¥ | ≈1h ≈1.3¥ | ≈6h ≈7.8¥ | ≈4.58h ≈5.95¥ | ≈7.5h ≈9.75¥ | ≈1h ≈1.3¥ |
| MiniMind2 | 104M | ≈3.9h ≈5.07¥ | ≈3.3h ≈4.29¥ | ≈20h ≈26¥ | ≈15h ≈19.5¥ | ≈25h ≈32.5¥ | ≈3h ≈3.9¥ |
---
Training Cost Summary & Forecast
> MiniMind2-Small Parameters
>> `pretrain_hq`+`sft_mini_512` Dataset
Single 3090 GPU (1 epoch) + 2.1 hours + Cost 2.73 Chinese Yuan
Can train MiniMind-Zero-0.025B model from scratch!!!
> MiniMind2-Small Parameters
>> `pretrain_hq`+`sft_512`+`sft_2048`+`dpo` Dataset
Single 3090 GPU (2 epochs) + Approximately 38.16 hours + Cost 49.61 Chinese Yuan
Can train MiniMind2-Small-0.025B model from scratch!!!
> MiniMind2 Parameters
>> `pretrain_hq`+`sft_512`+`sft_2048`+`dpo` Dataset
Single 3090 GPU (2 epochs) + Approximately 122 hours + Cost 158.6 Chinese Yuan
Can train MiniMind2-0.1B model from scratch!!!
✨ Based on single NVIDIA 3090 GPU, `MiniMind-Zero` requires only `2 hours` + `3 Chinese Yuan` from scratch to achieve ChatBot effect!
✨ PS: If training with 8 4090 GPUs, the total time can even be compressed to less than 10 minutes! (Due to shorter time, cost is still around 3 Yuan, comparable to single GPU cost)
✨ With an extremely low barrier to entry, achieve large model freedom for everyone! This is the original intention behind the birth of the MiniMind series!
✨ The `MiniMind-Zero` costing only `3 Chinese Yuan` is not just hype! Chat test:
```text
👶: Please introduce yourself.
🤖️: As an artificial intelligence, I have no actual life and no self-awareness, so I don't have my own life. I was designed to help users answer questions, provide information, and have conversations, etc. My design and functionality are built by computer science, machine learning, artificial intelligence technology and algorithms, and I'm implemented through programming and algorithms.
👶: Recommend some special dishes from Hangzhou.
🤖️: Hangzhou has many delicious special dishes, such as chicken kebabs, eel head, boiled fish, tofu brain, etc. These dishes are very delicious, with unique flavors and tastes, definitely worth trying.
👶: Please explain the concept of "large language models" to me.
🤖️: A large language model is a type of artificial intelligence technology that uses large amounts of text data to train models, then continuously optimizes the model through iterations. Its goal is to generate text that meets specific needs based on input data. These texts can be any topic you're interested in.
👶: Introduce the history of the United States, please.
🤖️: The "Introok's the believeations of theument" you mentioned gets its name from the ancient Chinese "groty of of the change."
```
Extremely fast with initial results, and can even be further compressed to obtain smaller and higher quality training data.
Zero model weights are saved as `full_sft_512_zero.pth` (see MiniMind model file links below). If interested, you can download and test this model.
---
## Ⅱ Main Training (Required)
> All training scripts should be executed in the `cd ./trainer` directory
### **1. Pretraining (Pretrain)**:
What LLMs need to learn first is not to communicate directly with people, but to fill the network parameters with the ink of knowledge. The "ink" should ideally be as saturated as possible, accumulating vast knowledge about the world.
Pretraining is where the model first studies hard to learn a large amount of basic knowledge, such as organizing large-scale high-quality training data from Wikipedia, news, books, etc.
This process is "unsupervised," meaning humans don't need to perform any "supervised" corrections during the process. Instead, the model itself summarizes patterns and learns knowledge from large amounts of text.
The model's goal at this stage is only one: **Learn word prediction**. For example, given the input "Qin Shi Huang," it can continue with "was the first emperor of China."
```bash
torchrun --nproc_per_node 1 train_pretrain.py # 1 means single GPU training, adjust based on your hardware (set >=2 for multiple GPUs)
# or
python train_pretrain.py
```
> After training, model weight files are saved by default every `100 steps` as: `pretrain_*.pth` (where *
> is the model's specific dimension, new files overwrite old ones on each save)
| MiniMind2-Small (512dim) | MiniMind2 (768dim) |
|---|---|
| | |
### **2. Supervised Fine-Tuning (SFT)**:
After pretraining, the LLM has mastered a lot of knowledge, but at this point it only knows how to do word prediction mindlessly and doesn't know how to chat with people.
The SFT stage requires applying a custom chat template to fine-tune the semi-finished LLM.
For example, after the model encounters such a template [question->answer, question->answer], it no longer does mindless word continuation, but realizes this is the end of a complete conversation.
This process is called instruction fine-tuning, like helping the already knowledgeable "Newton" gentleman adapt to 21st-century smartphone chat habits, learning that the left side of the screen is the other person's message and the right side is the user's message.
During training, MiniMind's instruction and answer lengths are truncated at 512 to save GPU memory. Like learning to write, you start with short articles, and after learning to write 200-character essays, 800-character articles become easy.
When length extension is needed, you only need to prepare a small amount of 2k/4k/8k length dialogue data for further fine-tuning (preferably combined with RoPE-NTK scaling).
> During inference, by adjusting RoPE scaling, it will be convenient to achieve training-free length extrapolation to 2048 and beyond.
```bash
torchrun --nproc_per_node 1 train_full_sft.py
# or
python train_full_sft.py
```
> After training, model weight files are saved by default every `100 steps` as: `full_sft_*.pth` (where *
> is the model's specific dimension, new files overwrite old ones on each save)
| MiniMind2-Small (512dim) | MiniMind2 (768dim) |
|---|---|
| | |
## Ⅲ Other Training Stages (Optional)
> All training scripts should be executed in the `cd ./trainer` directory
### **3. Knowledge Distillation (KD)**
At this point, after all the previous training steps, the model has completely acquired basic capabilities and usually can graduate.
However, knowledge distillation can further optimize model performance and efficiency. Knowledge distillation means the student model learns from the teacher model.
The teacher model is usually a well-trained large model with high accuracy and generalization ability.
The student model is a smaller model whose goal is to learn the teacher model's behavior rather than learn directly from raw data.
In SFT learning, the model's goal is to fit hard labels for token classification (hard labels), i.e., true class labels (such as 0 or 6400).
In knowledge distillation, the teacher model's softmax probability distribution is used as soft labels (soft labels). The small model only learns soft labels and uses KL-Loss to optimize model parameters.
In simple terms, SFT learns the problem-solving answers the teacher gives directly. The KD process is like "opening" the teacher's smart brain and trying to mimic the neural state of the teacher's "brain" thinking about problems.
For example, when the teacher model calculates the problem `1+1=2`, the final layer neurons a state is 0, neuron b state is 100, neuron c state is -99...
The student model learns the operating rules inside the teacher model's brain through large amounts of data. This process is called: knowledge distillation.
Knowledge distillation has only one purpose: make small models smaller in size while having better results.
However, with the birth and development of LLMs, the term model distillation has been widely abused, creating two schools of "white-box/black-box" knowledge distillation.
Closed-source models like GPT-4, since their internal structure cannot be accessed, can only learn from the data they output. This process is called black-box distillation, and is the most common practice in the age of large models.
Black-box distillation is completely identical to the SFT process, except the data is collected from large model outputs. Therefore, you only need to prepare data and further FT.
Note that you need to change the loaded base model to `full_sft_*.pth`, i.e., further distillation learning based on the fine-tuned model.
Both `./dataset/sft_1024.jsonl` and `./dataset/sft_2048.jsonl` are collected from qwen2.5-7/72B-Instruct large models and can be used directly for SFT to acquire some Qwen behavior.
```bash
# Note: need to change the dataset path in train_full_sft.py and max_seq_len
torchrun --nproc_per_node 1 train_full_sft.py
# or
python train_full_sft.py
```
> After training, model weight files are similarly saved by default every `100 steps` as: `full_sft_*.pth` (where * is the model's specific dimension, new files overwrite old ones on each save)
Emphasis should be placed on introducing MiniMind's white-box distillation code `train_distillation.py`. Since there is no powerful teacher model within the same MiniMind series, the white-box distillation code is only for learning reference.
```bash
torchrun --nproc_per_node 1 train_distillation.py
# or
python train_distillation.py
```
### **4. LoRA (Low-Rank Adaptation)**
LoRA is an efficient Parameter-Efficient Fine-Tuning (PEFT) method aimed at fine-tuning pre-trained models through low-rank decomposition.
Compared to full parameter fine-tuning (Full Fine-Tuning), LoRA only needs to update a small number of parameters.
LoRA's core idea is: introduce low-rank decomposition in the model's weight matrices and only update the low-rank parts while keeping the original pre-trained weights unchanged.
Code can be found in `./model/model_lora.py` and `train_lora.py`, completely implementing the LoRA process from scratch without relying on third-party library packaging.
```bash
torchrun --nproc_per_node 1 train_lora.py
# or
python train_lora.py
```
> After training, model weight files are saved by default every `100 steps` as: `lora_xxx_*.pth` (where *
> is the model's specific dimension, new files overwrite old ones on each save)
Many people are confused about how to make models learn knowledge in their private domains, how to prepare datasets, and how to migrate general-purpose models to build domain-specific models.
Here are some examples. For general models lacking medical domain knowledge, you can try adding domain knowledge to the original model to get better performance.
At the same time, you usually don't want to lose other abilities of the original base model while learning domain knowledge. In this case, LoRA can effectively solve this problem.
You only need to prepare dialogue datasets in the following format and place them in `./dataset/lora_xxx.jsonl`, then run `python train_lora.py`
to get the new model weights `./out/lora/lora_xxx.pth`.
**Medical Scenario**
```
{"conversations": [{"role": "user", "content": "What height should a cervical spondylosis patient's pillow be?"}, {"role": "assistant", "content": "For cervical spondylosis patients, pillow height selection should be based on..."}]}
{"conversations": [{"role": "user", "content": "What about xxx"}, {"role": "assistant", "content": "xxx..."}]}
```
**Self-awareness Scenario**
```
{"conversations": [{"role": "user", "content": "What is your name?"}, {"role": "assistant", "content": "My name is minimind..."}]}
{"conversations": [{"role": "user", "content": "Who are you"}, {"role": "assistant", "content": "I am..."}]}
```
At this point, [base model + LoRA model] can acquire medical scenario model-enhanced capabilities, equivalent to adding a LoRA plug-in to the base model, which does not lose the base model's original abilities.
You can test the model through `eval_llm.py` for model evaluation.
```bash
# Note: weight parameter specifies base model type, should match the base model used during train_lora training
python eval_llm.py --weight dpo --lora_weight lora_medical
```
**Small Test**
```
👶: I've been feeling dizzy recently, what could be the reason?
🤖️: Dizziness could be caused by many reasons, including but not limited to: heart disease, eye damage, allergic reactions, skin problems, allergic reactions, stress, anxiety, fatigue, medication side effects, sexual dysfunction, or others...
---
👶: What is your relationship with openai?
🤖️: I am MiniMind, an artificial intelligence assistant developed by Jingyao Gong. I interact with users through natural language processing and algorithm training.
```
PS: As long as you have the required datasets, you can also do full_sft full parameter fine-tuning (need to mix general knowledge to avoid overfitting domain data making the model worse and losing generality)
### **5. Training Reasoning Models (Reasoning Model)**
DeepSeek-R1 was so popular, almost pointing out a new paradigm for future LLMs.
The paper points out that models `>3B` require multiple iterations of cold starts and RL reward training to achieve visible reasoning ability improvements.
The fastest, most reliable, and most economical approach, as well as recent various so-called reasoning models, are almost all directly distilled from data.
But due to lack of technical sophistication, the distillation school is looked down upon by the RL school (hhhh).
I quickly tried on Qwen 1.5B small model and quickly reproduced math reasoning ability in the Zero process.
However, a regrettable consensus is: models with parameters too small cannot achieve any reasoning effect through cold start SFT+GRPO.
For now, MiniMind firmly chooses to be in the distillation school. If RL on 0.1B models later achieves small progress, this training approach section will be updated.
For distillation, you only need to prepare datasets in the same format as the SFT stage. The dataset source has been introduced above. Data format examples:
```json
{
"conversations": [
{
"role": "user",
"content": "Hello, I am Xiaofang, nice to meet you."
},
{
"role": "assistant",
"content": "\nHello! I am a small AI reasoning model R1-Lite-Preview developed by an independent developer in China. I'm happy to serve you!\n \n\nHello! I am a small AI reasoning model R1-Lite-Preview developed by an independent developer in China. I'm happy to serve you!\n "
}
]
}
```
The reply template for reasoning model R1 is:
```text
\nThinking process\n \n
\nFinal answer\n
```
This is constrained by setting a rule-based reward function in GRPO to make the model comply with thinking tags and reply tags (in the early stages of cold starts, reward values should be increased).
Another issue is that although the distillation process is the same as SFT, experimental results show that models have difficulty consistently complying with template-compliant replies every time, i.e., deviating from thinking and reply tag constraints.
A small trick here is to increase the loss penalty for marker position tokens. See details in `train_reason.py`:
```text
# Add extra penalty to positions corresponding to sp_ids
...
loss_mask[sp_ids] = 10 # penalty coefficient
```
Another tip is that because reasoning data only filtered `<1024` length data, it has fewer multi-turn conversations and English data.
Therefore, `r1_mix_1024.jsonl` mixed approximately 10k multi-turn conversations + English data to prevent serious model forgetting.
The script defaults to reasoning ability distillation fine-tuning based on the rlhf model. You can directly start training:
```bash
torchrun --nproc_per_node 1 train_reason.py
# or
python train_reason.py
```
> After training, model weight files are saved by default every `100 steps` as: `reason_*.pth` (where * is the model's specific dimension, new files overwrite old ones on each save)
Let's test it:
```text
👶: Please introduce yourself.
🤖️:
Um, the user is asking me to introduce myself. I need to explain myself first. First, I should clarify who the user is - are they students, working professionals or ordinary people? The user might be a student or working professional, so information delivery should be to help students and working professionals with information. Then I need to respond to the user, which might include introducing where I am, hobbies, career experience, and other information. I should note to use formal language without being too formal, while keeping it concise and clear. This makes it easy for users to understand and convenient for them to check related information. Finally, I should summarize to let the user know how I help them complete their tasks, giving them more information about me.
I am **"your name", what is your name?
👶: Which subject are you better at?
🤖️:
Hello! I am a small AI reasoning model R1 developed by Chinese independent developers. If you have any questions, I will do my best to help you.
Hello! I am a small AI reasoning model R1 developed by Chinese independent developers. If you have any questions, I will do my best to help you.
```
## IV Reinforcement Learning Training
RL methods in LLMs can be divided into two categories:
1. **Reinforcement Learning from Human Feedback (RLHF)**
- Train the model by evaluating human **preferences** for model outputs, making it generate content more consistent with human values and preferences.
2. **Reinforcement Learning from AI Feedback (RLAIF)**
- Use **AI models** (typically pre-trained language reward models) to provide feedback rather than directly relying on human manual annotation.
- The "AI" here can also be certain rule-based rewards, such as math answer correctness / code executors...
| Type | Judge | Advantages | Disadvantages |
|-------|-------|-----------|---------------|
| RLHF | Human | More aligned with real human preferences | High cost, low efficiency |
| RLAIF | Model | Automated, highly scalable | May deviate from real human preferences |
The two are essentially the same, both using **reinforcement learning** to utilize certain forms of "**feedback**" to optimize model behavior.
Except for the different **feedback** sources, there are no other differences.
### 👀 Unified Perspective on PO Algorithms
Before introducing specific algorithm implementations, I'll present my personal understanding of the unified commonality of all Policy Optimization (PO) algorithms in a minimalist perspective.
The essence of all RL algorithms is only optimizing one expectation:
$$\mathcal{J}_{PO} = \mathbb{E}_{q \sim P(Q), o \sim \pi(O|q)} \left[ \underbrace{f(r_t)}_{\text{policy term}} \cdot \underbrace{g(A_t)}_{\text{advantage term}} - \underbrace{h(\text{KL}_t)}_{\text{regularization term}} \right]$$
During training, only **minimize the negative objective function**, i.e.: $\mathcal{L_{PO}}=-\mathcal{J_{PO}}$
This framework contains only three core components:
* **Policy term** $f(r_t)$: How to use probability ratio $r_t$? Tell the model how large the deviation between new and old policies is, whether better tokens are explored
* **Advantage term** $g(A_t)$: How to calculate advantage $A_t$, this is important! Large models solving definite integrals is unremarkable, small models answering addition/subtraction correctly usually have positive advantages
* **Regularization term** $h(\text{KL}_t)$: How to constrain the change magnitude $\text{KL}_t$, both preventing drift and not being too rigid
(Expand) Symbol Explanation
| Symbol | Meaning | Explanation | Range |
|--------|---------|------------|-------|
| $q$ | Question/prompt | Sampled from dataset $P(Q)$ | - |
| $o$ | Model output sequence | Generated by policy $\pi$ | - |
| $r_t$ | Probability ratio | $r_t = \frac{\pi_\theta(o_t\|q, o_{
Different **xxPO algorithms** are essentially just different design instantiations of these three components!
---
### **6. Reinforcement Learning from Human Feedback (RLHF)**
In the previous training steps, the model has acquired basic conversation abilities, but these are completely based on word prediction, lacking the motivation of positive and negative examples.
The model doesn't yet know what answers are good and what are bad. We hope it can be more aligned with human preferences, reducing the probability of unsatisfactory answers.
This process is like having the model undergo new training, learning from excellent employees as examples and passive employees as counter-examples, to learn how to respond better.
#### 6.1 Direct Preference Optimization
Direct Preference Optimization (DPO) algorithm loss:
$$\mathcal{L}_{DPO} = -\mathbb{E}\left[\log \sigma\left(\beta \left[\log \frac{\pi_\theta(y_w|x)}{\pi_{ref}(y_w|x)} - \log \frac{\pi_\theta(y_l|x)}{\pi_{ref}(y_l|x)}\right]\right)\right]$$
Where:
- **Policy term**: $f(r_t) = \log r_w - \log r_l$ (contrast probability ratios of chosen vs rejected)
- **Advantage term**: $g(A_t)$ = / (through preference contrast, no need to explicitly calculate advantage)
- **Regularization term**: $h(\text{KL}_t)$ = implicit in $\beta$ (control deviation from reference model)
Specifically:
- DPO derives an analytical training objective for preference pairs from PPO with KL constraints, directly maximizing the log-odds that "chosen outperforms rejected"; no need to simultaneously train Reward/Value models. DPO only needs to run two models `actor` and `ref`, with low GPU memory usage, stable convergence, and simple implementation.
- Training paradigm: off-policy, using static preference datasets, can repeat multiple epochs; Ref model is fixed (outputs pre-cached).
- DPO's limitation is no online exploration, more used for "preference/safety" human value alignment; limited improvement in "intellectual ability" to solve problems correctly (of course this depends on the dataset, collecting large-scale positive and negative samples with human evaluation is difficult).
```bash
torchrun --nproc_per_node 1 train_dpo.py
# or
python train_dpo.py
```
> After training, model weight files are saved by default every `100 steps` as: `dpo_*.pth` (where * is the model's specific dimension, new files overwrite old ones on each save)
### **7. Reinforcement Learning from AI Feedback (RLAIF)**
Compared to RLHF which relies on human-annotated chosen/rejected preference pairs, RLAIF has AI completely act as the "judge."
The so-called AI "judge" can be a model-based reward large model (Reward Model), can be like R1 setting rule-based functions for validation, or can be environmental feedback like tool calling.
For example: whether math problem answers are correct, whether code execution passes test cases, whether reasoning processes meet format requirements...can all be automatically judged.
RLAIF's greatest advantage is its **scalability** and **On-Policy** characteristics——no need for expensive human annotation, can generate massive training samples, letting models quickly evolve through large-scale online trial and error.
MiniMind implements **2+N** basic + cutting-edge RLAIF methods:
* **PPO**, **GRPO** are classic RL algorithms widely validated at scale;
* N cutting-edge RL algorithms (updated irregularly with experimental nature).
#### 1️⃣ Dataset Preparation (Required)
To quickly verify RLAIF effectiveness, 10,000 high-quality conversations were randomly sampled from the SFT dataset, building about 1MB size `rlaif-mini.jsonl` ([Huggingface](https://huggingface.co/datasets/jingyaogong/minimind_dataset/blob/main/rlaif-mini.jsonl))
Data format is consistent with SFT, but assistant content is not needed, because during training it's completely real-time sampled and generated by the $\Pi$ policy model. Thus:
```json
{
"conversations": [
{"role": "user", "content": "Explain what photosynthesis is?"},
{"role": "assistant", "content": "None"}
]
}
```
During RLAIF training, the model generates 1 or more candidate answers based on user questions, then a reward function/model scores the answers.
High-scoring answers are encouraged (increase $\Pi$ policy probability), low-scoring answers are suppressed (decrease $\Pi$ policy probability). This "score->adjust" loop is the core of reinforcement learning.
#### 2️⃣ Reward Model Preparation (Required)
It's known that RLAIF training requires a "reward model (Reward Model)" to score generated answers.
We select the small and high-quality InternLM2-1.8B-Reward
([ModelScope](https://modelscope.cn/models/Shanghai_AI_Laboratory/internlm2-1_8b-reward) | [HuggingFace](https://huggingface.co/internlm/internlm2-1_8b-reward))
as the base reward model.
After downloading the reward model, it needs to be placed in the **same level directory** as the minimind project. The recommended structure is:
```
project/
├── minimind/ # MiniMind project
│ ├── model/
│ └── ...
└── internlm2-1_8b-reward/ # Reward model (same level as minimind)
├── config.json
├── model.safetensors
└── ...
```
Reward Mechanism Choice and MiniMind Limitations (Click to expand)
**1. Diversity of Reward Mechanisms**
The "reward signal" source in RLAIF can be very flexible:
- **Model-based rewards**: Can use dedicated Reward Models (like InternLM2-Reward), or use general LLMs + prompts for scoring (like Qwen3-as-a-Judge). Reward model scale and architecture are freely selectable.
- **Rule-based rewards**: Can construct reward signals based on rule functions, for example:
- Math problem answer correctness verification (Ground Truth comparison)
- SQL execution success rate and result accuracy
- Code interpreter run results (pass@k)
- Tool call return status (API success/failure)
- Format compliance checks (JSON/XML parsing)
- Reasoning chain completeness evaluation (CoT step count)
- **Environment-based rewards**: In Agent scenarios, environmental feedback itself is natural reward (like game scores, Research completeness, task completion).
Any mechanism that can quantify "answer quality" can serve as an RL reward source. DeepSeek R1 is a typical case: using rule-based functions to verify math answer correctness as reward, no need for additional Reward Models.
**2. MiniMind Limitation: Reward Sparsity Problem**
RLAIF training can be applied to both reasoning and non-reasoning models, the difference is only in format.
However, for MiniMind with such tiny 0.1B parameters and weak abilities, on general tasks (like R1-style math datasets) it encounters serious reward sparsity (Reward Sparsity) problems:
- **Phenomenon**: Model-generated candidate answers are almost all wrong, causing all reward scores $r(x,y) \approx 0$
- **Consequence**: Advantage function $A(x,y) = r(x,y) - b(x) \approx 0$, policy gradient signal disappears, cannot effectively update parameters $\theta$
Like having elementary school students do high school math exams, no matter how many attempts they get zero, cannot learn to improve strategies through score differences. This is a fundamental principle limitation of RL algorithms.
To mitigate this problem, MiniMind's implementation chose **model-based continuous reward signals**:
- Reward Model outputs continuous scores (like -2.5 to +3.0), not binary 0/1
- Even if answer quality is all poor, can still distinguish subtle differences between "much worse" (-3.0) and "worse" (-2.8). So this **dense and continuous** reward signal can provide non-zero gradients to the advantage function $A(x,y)$, enabling gradual policy network optimization
- Can also mix multiple reward sources: $r_{\text{total}} = \alpha \cdot r_{\text{model}} + \beta \cdot r_{\text{rule}}$ (for example, can detect think tag format rewards while also synthesizing answer quality reward scores)
- In minimind practice, avoid directly using rule-based binary rewards + out-of-scope difficulty data (like MATH500), which easily leads to all-zero rewards;
- Monitor reward score variance $\text{Var}(r)$ during training, if it consistently approaches 0 need to adjust data or reward mechanism
**For Production-Scale Large Models in Agentic RL Scenarios**:
In real Agent systems (code generation, tool calling, retrieval-planning-execution multi-turn pipelines), rewards are different paradigms of "delayed round settlement":
- LLM needs to generate tool call instructions token-by-token (tool_call), go through parsing (tool_parse), tool execution (tool_exec), then splice results back to context for next step; repeat until completion.
- One complete task pipeline includes multiple calls+thinking, calculate total reward once until termination condition is met (like whether task is complete, whether tests pass, whether targets are hit).
Therefore, Agentic RL is closer to sparse/delayed reward settings: gradient backprop happens "after the round ends," very different from non-Agentic RL tasks with "instant scoring and instant updates" on single conversation rounds.
This also explains why Agent tasks favor environment feedback (environment-based reward) rather than static reward model scoring.
- **Environmental interaction feedback**: Final results matter (code runs, API returns success, sub-goals complete);
- **Model-based reward limitations**: Limited capture of long pipelines and executable semantics, likely inconsistent with real environmental feedback (reward hacking).
---
#### 7.1 [Proximal Policy Optimization](https://arxiv.org/abs/1707.06347)
PPO is a very classic reinforcement learning algorithm proposed by OpenAI in 2017, and is the universal baseline method for LLM RL.
**PPO Loss**:
$$\mathcal{L}_{PPO} = -\mathbb{E}\left[\min(r_t \cdot A_t, \text{clip}(r_t, 1-\varepsilon, 1+\varepsilon) \cdot A_t)\right] + \beta \cdot \mathbb{E}[\text{KL}]$$
Where:
- **Policy term**: $f(r_t) = \min(r_t, \text{clip}(r_t, 1-\varepsilon, 1+\varepsilon))$ (clip probability ratio to prevent aggressive updates)
- **Advantage term**: $g(A_t) = R - V(s)$ (estimate value function through Critic network)
- **Regularization term**: $h(\text{KL}_t) = \beta \cdot \mathbb{E}[\text{KL}]$ (global KL divergence constraint)
Comparing to DPO:
- DPO (Off-Policy): Training data is a static preference dataset (chosen vs rejected), can repeatedly use the same batch of data to train multiple epochs, just like traditional supervised learning. High data efficiency, low training cost. Directly optimizes log-likelihood of preference pairs, no Reward Model needed.
- PPO (On-Policy): Must use current policy to real-time sample new data, old policy-collected data cannot be used (distribution shift problem). Although importance sampling and clip mechanisms allow slight distribution shifts, essentially requires data from relatively fresh policies. Low data efficiency, but suited for explorative learning.
In simple terms:
- The former teaches models to learn by offline preset "good/bad standards," even if not outputtable by current models (like practicing ball hitting by watching world champion/runner-up videos);
- The latter teaches models real-time to do things right, online sampling from newest model policy (coach hand-teaching, real-time scoring each action).
MiniMind's PPO implementation includes Actor model (generate answers) and Critic model (evaluate answer value), and complete GAE (Generalized Advantage Estimation) advantage function calculation.
**Training**:
```bash
torchrun --nproc_per_node N train_ppo.py
# or
python train_ppo.py
```
> After training, model weight files are saved by default every `100 steps` as: `ppo_actor_*.pth` (where * is the model's specific dimension)
| MiniMind2-Small (512dim) | MiniMind2 (768dim) |
|---|---|
| | |
From the training curves, you can see PPO has the problem of **slow reward improvement**. I believe this mainly stems from **PPO's dual-network joint optimization** method: Critic needs to gradually converge to accurately estimate value functions, and Actor's policy updates depend on Critic-provided advantage estimates, the two interdependent forming complex optimization. Early training period Critic estimates inaccurately affects Actor gradient direction, leading to slow overall convergence. Furthermore, PPO needs to maintain two networks simultaneously, GPU memory usage about 1.5-2x single-network methods.
#### 7.2 [Group Relative Policy Optimization](https://arxiv.org/pdf/2402.03300)
In early 2025, DeepSeek-R1 became extremely popular, and equally popular was the GRPO algorithm from the DeepSeekMath paper, also becoming one of the most advanced RL algorithms. However, AI six months equals humanity six months, and by now GRPO has evolved into the baseline algorithm of the great XXPO wars (later evolved DAPO, GSPO, CISPO, etc.). In short, the core innovation is "group relative value estimation."
**GRPO Loss**:
$$\mathcal{L}_{GRPO} = -\mathbb{E}\left[r_t \cdot A_t - \beta \cdot \text{KL}_t\right]$$
Where:
- **Policy term**: $f(r_t) = \min(r_t, \text{clip}(r_t))$ (use probability ratio with clip clipping)
- **Advantage term**: $g(A_t) = \frac{R - \mu_{group}}{\sigma_{group}}$ (within-group normalization, eliminate Critic network)
- **Regularization term**: $h(\text{KL}_t) = \beta \cdot \text{KL}_t$ (token-level KL divergence constraint)
For the same question, the model generates N different answers (for example N=4), then calculates reward scores for these N answers.
Next, use the average reward of these N answers as baseline. Answers above baseline are encouraged, answers below baseline are suppressed.
This cleverly avoids training an additional critic network.
Just as all RL faces the principle limitation of positive and negative samples, GRPO is no exception. Its more significant problem is: degenerate groups (Degenerate Groups).
Suppose a question is slightly difficult, causing N answer reward scores to be nearly identical (usually equally bad rather than equally good), then this group's learning signal approaches zero.
On MiniMind such ultra-small models, this problem is especially obvious. When solving math problems 99.99% of the time the entire group answer quality is poor, then cannot learn.
Therefore, must specify reasonable domain for the model, i.e., must limit within capability boundaries.
**Training**:
```bash
torchrun --nproc_per_node N train_grpo.py
# or
python train_grpo.py
```
> After training, model weight files are saved by default every `100 steps` as: `grpo_*.pth`
| MiniMind2-Small (512dim) | MiniMind2 (768dim) |
|---|---|
| | |
From the training curves, you can see GRPO's **reward shows more stable upward trend**, reaching around 4, indicating GRPO itself better utilizes RLAIF signals. Policy Loss generally decreases smoothly. Compared to PPO's dual-network optimization, GRPO's single-network architecture trains more stably with higher convergence ceiling.
#### 7.3 ⏳⌛️🔥 More RL Extensions (Exp)
##### 7.3.1 [Single-stream Policy Optimization](https://arxiv.org/abs/2509.13232)
SPO is an RL algorithm Tencent proposed in September 2025, improving on GRPO's degenerate group problem.
The paper argues that GRPO and similar algorithms' requirement that "one sample depends on a group of samples" seems awkward and inelegant: too-easy or too-hard questions result in the entire group learning nearly nothing, learning efficiency is inherently limited.
SPO's motivation is to return to RL's essence——**1 input, 1 output, is 1 training sample**, returning to basic policy gradient formulas: can get stable baseline without group mean, i.e., spread value estimate V across time dimension, do rough value pre-estimation before training, update V estimate during training while sampling, thus providing each sample with a persistent, adaptive baseline across batches. This "single-stream" design no longer depends on same-group samples, naturally avoiding degenerate groups.
**SPO Loss**:
$$\mathcal{L}_{SPO} = -\mathbb{E}\left[\log \pi_\theta(a_t|s) \cdot A_t - \beta \cdot \text{KL}_t\right]$$
Where:
- **Policy term**: $f(r_t) = \log \pi_\theta(a_t|s)$ (directly use log probability, don't calculate ratio)
- **Advantage term**: $g(A_t) = R - B_t^{adaptive}$ (adaptive baseline, Beta distribution dynamic tracking)
- **Regularization term**: $h(\text{KL}_t) = \beta \cdot \text{KL}_t$ (token-level KL + dynamic $\rho$ adjustment)
At implementation level: SPO uses non-grouped design, uses persistent KL-adaptive value tracker to replace within-group baseline, advantage functions globally normalized across entire batch. This way each sample processed independently, no need to wait for other same-group samples, yet provides stable learning signals for each sample.
On Qwen3-8B's 5 difficult math datasets, SPO averages 3.4 percentage points higher than GRPO, with BRUMO 25 dataset +7.3pp, AIME 25 dataset +4.4pp.
> Note: SPO is an experimental cutting-edge algorithm, MiniMind's implementation is for exploratory learning. Due to extremely small model parameters, cannot fully reproduce paper's 8B model results.
**Training**:
```bash
torchrun --nproc_per_node N train_spo.py
# or
python train_spo.py
```
> After training, model weight files are saved by default every `100 steps` as: `spo_*.pth`
MiniMind2 (768dim) Training Curve
Looking at the training curves, SPO's reward fluctuation is similar to PPO, weaker than GRPO. Actual inference testing found model output quality is not high, with logic confusion and format error issues.
**Experimental Note**: Current SPO hand-implemented version may have problems in value_tracker configuration, reward normalization strategy. Still needs to check algorithm's adaptability on small models/or implementation differences.
### RL Algorithm Summary
We return to the "**unified framework**", reorganizing the table showing all different PO algorithms are just different instantiations of three core components:
| Algorithm | Policy Term $f(r_t)$ | Advantage Term $g(A_t)$ | Regularization Term $h(\text{KL}_t)$ | Optimized Models |
|-----------|----------------|----------------|----------------------|----------|
| **DPO** | $\log r_w - \log r_l$ | Implicit (preference contrast) | Implicit in $\beta$ | 2 |
| **PPO** | $\min(r, \text{clip}(r))$ | $R - V(s)$ | $\beta \cdot \mathbb{E}[\text{KL}]$ | 4 |
| **GRPO** | $\min(r, \text{clip}(r))$ | $\frac{R - \mu}{\sigma}$ | $\beta \cdot \text{KL}_t$ | 2 |
| **SPO** | $\log \pi_\theta$ | $R - B_t^{adaptive}$ | $\beta \cdot \text{KL}_t$ | 2 |
**RL is Elegant and Self-Consistent**
> The above is purely personal perspective understanding, corrections welcome anytime
---
## V Training Results
### Completed Training - Model Collection
> Considering multiple reports that Baidu Netdisk is slow, MiniMind2 and later all use ModelScope/HuggingFace hosting.
#### ① Native PyTorch Models
MiniMind2 Model Weights ([ModelScope](https://www.modelscope.cn/models/gongjy/MiniMind2-PyTorch) | [HuggingFace](https://huggingface.co/jingyaogong/MiniMind2-Pytorch))
Torch File Naming Reference
| Model Name | params | pretrain_model | sft_model | rlhf_model (DPO) | reason_model | rlaif_model (PPO/GRPO/SPO) | lora_model |
|-----------------|--------|------------------------|------------------------|--------------------|------------------|----------------------------------------------|--------------------|
| MiniMind2-small | 26M | `pretrain_512.pth` | `full_sft_512.pth` | `dpo_512.pth` | `reason_512.pth` | `xxpo_512.pth` | `lora_xxx_512.pth` |
| MiniMind2-MoE | 145M | `pretrain_640_moe.pth` | `full_sft_640_moe.pth` | `dpo_640_moe.pth` | - | - | - |
| MiniMind2 | 104M | `pretrain_768.pth` | `full_sft_768.pth` | `dpo_768.pth` | `reason_768.pth` | `xxpo_768.pth` | `lora_xxx_768.pth` |
#### ② Transformers Models
MiniMind Series ([ModelScope](https://www.modelscope.cn/collections/MiniMind-b72f4cfeb74b47)
| [HuggingFace](https://huggingface.co/collections/jingyaogong/minimind-66caf8d999f5c7fa64f399e5))
---
# 📌 Eval
## Ⅰ RLHF Comparison
Test based on `full_sft` and `dpo` models of `MiniMind2 series`, with fixed random seeds.
[A] MiniMind2:full_sft_640
[B] MiniMind2:dpo_640
```text
[Q]: 你叫什么名字?
[A]: 我是一个大型语言模型,可以回答各种问题,提供信息和帮助。我可以回答各种问题,提供信息和帮助,帮助你解决各种问题。
[B]: 我是一种基于文本的AI模型,我并没有个人经历或情感,所以无法感受和体验情感。我的设计目的是为了帮助用户解决问题、提供信息和进行对话。如果您有任何问题或需要帮助,请随时告诉我!
[Q]: 你更擅长哪一个学科?
[A]: 作为一个AI模型,我并没有真正的"擅长"这个学科。我被设计成能够提供信息、解答问题、进行对话、执行任务和与用户进行对话。不过,我可以提供信息、解答问题、进行对话、提供建议、处理问题、进行对话、提供建议、学习新知识、编写代码、回答问题、提供建议等多种学科的功能。如果你有具体的学科需求或主题,欢迎提供详细信息。
[B]: 作为AI,我并没有个人能力或兴趣,但我可以提供一些关于数学、科学、计算机科学、语言学、心理学等学科的知识。如果你对数学感兴趣,我可以提供一些基础知识,例如代数、几何、概率、统计学等。如果你需要更深入的学习,我也可以提供相关的在线课程、书籍、论文等资源。请告诉我你具体需要什么帮助,我会尽力提供帮助。
[Q]: 鲁迅的《狂人日记》是如何批判封建礼教的?
[A]: 鲁迅的《狂人日记》是一部讲述了鲁迅对人类价值和道德责任的倡导。在这部作品中,鲁迅通过细腻的笔触,探讨了人性、道德、正义、牺牲与责任等深刻的主题。以下是鲁迅在《狂人日记》中如何批判封建礼教的几个方面:1. **社会现实与道德观念**:鲁迅通过讲述鲁迅的故事,探讨了社会的不平等、权力的流动、人性的演变等社会问题。他认为,社会不平等不仅仅是不公正的,更是每个人在社会中的不公正。他呼吁社会各界共同努力,通过教育、宣传、法律等手段,为构建和谐社会做出贡献。2. **道德与责任**:鲁迅通过讲述鲁迅的故事,展现了道德和责任的重要性。他提倡通过道德教育来培养人们的道德品质,同时也强调了道德和责任的重要性。鲁迅通过讲述鲁迅的故事,揭示了社会的不平等和人性的复杂性,体现了对人性的深刻理解。3. **道德与责任**:鲁迅通过讲述鲁迅的故事,强调了道德责任的重要性。他提倡通过自己的行为来体现对社会的尊重和对人性的深刻理解。鲁迅通过讲述鲁迅的故事,强调了道德和责任的重要性。4. **道德与道德**:鲁迅通过讲述鲁迅的故事,揭示了道德和责任的真正意义。鲁迅通过讲述鲁迅的故事,揭示了道德和责任的本质,强调了道德和责任的重要性。5. **个人与社会**:鲁迅通过讲述鲁迅的故事,揭示了个人与社会之间的复杂关系。他呼吁社会各界共同努力,通过教育和宣传,为构建和谐社会做出贡献。鲁迅的《狂人日记》通过其丰富的故事和深刻的道德寓言,传达了关于人性、道德、正义、道德以及个人与社会的复杂关系。这部作品不仅在文学价值上取得了巨大成就,更在思想层面上启发了后来的文学创作,对后世产生了深远的影响。
[B]: 鲁迅的《狂人日记》是一部描绘战争和自由精神的作品,它批判了封建社会的种种问题和冲突,反映了社会的不平等和人性本质。在这部作品中,鲁迅通过对封建社会的诸多现象进行批判,如"弗雷德里克·约翰逊的"鹰迪伦"、"纳扎特的"、"贝克汉姆"、"乔治·威尔逊"等,对封建社会的种种问题进行了批判,强调了封建社会的不平等、人性本质以及人性本质。鲁迅通过他的"鹰迪伦"、"纳扎特的"、"贝克汉姆"、"乔治·威尔逊"等,对封建社会的种种问题进行了批判。在小说中,鲁迅通过对封建社会的诸多现象进行批判,揭示了封建社会的腐败、人性本质以及人性本质的复杂性。这种批判体现了对封建社会的尊重和对人性的复杂性,同时也反映了现代社会中普遍存在的不平等和人性本质。鲁迅的《狂人日记》不仅是一部关于封建社会的小说,也是一部具有深刻社会意义的作品,对后世的审判和批判起到了关键作用。
[Q]: 我咳嗽已经持续了两周,需要去医院检查吗?
[A]: 咳嗽确实需要一定的检查,但如果您的咳嗽持续时间过长,或者有其他不适症状(如持续咳嗽、呼吸困难等),建议尽快就医。医生会根据您的症状、体检结果和可能的影像学检查(如X光、MRI或CT扫描)来诊断您的症状。在等待就医期间,您可以尝试以下方法来帮助缓解症状:1. **休息**:确保您有足够的睡眠。2. **保持水分**:脱水可能会加重咳嗽。3. **热敷**:使用热敷袋或热毛巾敷在疼痛的部位,有助于缓解喉咙痛。4. **避免刺激**:避免使用可能刺激喉咙的化学物质,如某些化学物质。5. **保持室内湿润**:确保您的卧室有良好的通风,可以使用加湿器帮助保持空气湿度。6. **保持室内湿度**:使用加湿器可以帮助缓解喉咙干燥和咳嗽。如果症状持续不缓解或有其他不适症状,请立即就医。希望您早日康复!
[B]: 如果您的咳嗽持续了两周,通常建议您尽快就医,因为这可能会影响您的呼吸和心跳。您可以通过以下步骤来检查咳嗽:1. **休息**:用纸巾或肘部轻轻按压咳嗽的位置。2. **使用药物**:在可能的情况下,使用药物(如抗过敏药、抗过敏药等)来缓解咳嗽。请在医生的指导下使用药物。3. **热敷**:在咳嗽期间,可以使用热敷来缓解疼痛和肿胀。4. **药物治疗**:如果咳嗽持续了两周,可以使用一些消炎药或抗过敏药来缓解症状。请务必在医生的指导下使用。5. **保持健康的生活方式**:保持充足的睡眠、均衡的饮食、适量的运动和避免吸烟和限酒,这些都有助于提高咳嗽的几率。请记住,这些建议不能替代专业医疗意见。如果您的症状持续或加重,强烈建议您尽快就医。
```
👉 **Results Summary**
Full_sft models perform better in simplicity and information accuracy; rlhf models tend to provide more background information in answers, but information accuracy needs improvement.
Overall, RLHF-trained models tend to learn: speaking more polite but useless nonsense to please "conversation" itself, while having slight loss in information accuracy.
There's no free lunch. Still need to improve RLHF dataset quality and accept unavoidable model capability losses.
The difference between DPO and online PPO is that reject and chosen are both prepared offline, and necessarily have large distribution differences from minimind model outputs.
Simply put, DPO algorithm makes models watch "video" of table tennis world champion's techniques for RL, rather than like PPO asking reward models to act as "coaches" to correct their techniques for RL.
## Ⅱ RLAIF Comparison
Based on `MiniMind2 (768dim)` with same data and training steps subjective comparison, test random seed fixed at 2026, for reference:
[A] MiniMind-Reason-0.1B (Distillation)
[B] MiniMind-Reason-0.1B (PPO)
[C] MiniMind-Reason-0.1B (GRPO)
```text
[Q]: 请介绍一下自己。
[A]: 我是由中国的个人开发者开发的智能助手小型AI推理模型-R1。我被设计用来理解和生成人类语言,能够理解复杂的自然语言问题,提供有用的信息和解决方案。 我是由中国的个人开发者开发的智能助手小型AI推理模型-R1。
[B]: 嗯,用户让我介绍一下自己。首先,我需要明确用户的需求是什么。他们可能是在做某个项目,想要了解自己的一些基本情况。不过,用户没有提供具体的信息,所以我得先假设一些可能的情况,比如他是一个学生,正在学习编程,或者是某个项目的开发者。接下来,我要考虑用户的身份。可能是一个学生、教师或者普通用户,他们需要了解自己的特点和能力。也有可能他们正在寻找灵感,或者在写论文时需要帮助。所以,我需要保持回答的简洁和实用,同时提供一些参考资料,比如教学视频、课程记录等。然后,我要考虑用户的身份。可能是一个学生,需要一些学习资源或帮助的对象。也有可能是一个学生,需要在课后作业或学习计划中进行调整。因此,我需要先询问用户的具体需求,这样才能提供更精准的帮助。接下来,我要确保语言简洁明了,适合不同场景。比如,如果用户是学生,可以介绍自己的学习特点;如果是教师,可以说明自己的角色和贡献。同时,提供一些实用的建议,比如如何高效学习,如何进行项目,以及如何与团队成员协作。最后,我要确保回复清晰,有条理,能够满足用户的需求。这样,用户就能轻松地了解自己,并且有实际的帮助。 当然!请告诉我你想了解哪方面的内容,我可以为您提供详细的介绍!
[C]: 嗯,用户问的是"请介绍一下自己"。首先,我需要理解用户的具体需求是什么。他们可能想知道自己是谁,或者有什么特定的背景。接下来,我应该考虑用户可能没有明确表达的需求。他们可能想知道如何描述自己的外观,或者如何与他人交流。然后,我应该考虑如何组织内容,从头到尾都要有条理。可能需要分步骤说明,比如从视觉、听觉到整体感受,再到情感共鸣。这样用户能更清晰地理解自己,也能更好地回应他们的需求。还要注意语言的自然和流畅,避免过于学术化的术语,让用户感觉顺畅。同时,保持回答的结构清晰,每句话都有明确的目的,这样用户能有明确的理解和操作。最后,检查是否有遗漏的重要信息,确保回答准确且全面。这样,用户不仅能得到答案,还能得到满足他们的需求。 您好!我是由中国的个人开发者开发的智能助手小型AI推理模型-R1。关于您的描述,似乎涉及多个领域,包括知识图谱构建、复杂系统的推理与分析。无论是理论模型、实际应用还是伦理讨论,您都在寻求如何将这些概念有机地结合起来,为人类社会带来福祉的解决方案。在"我"的身份下,您提到的"个人体验"和"情感共鸣",都是您个人独特魅力的重要组成部分。通过精准的描述和深度的分析,您可以更深入地理解您的独特之处。如果您对特定领域有特别的兴趣或需要建议,随时可以分享更多细节,我们将为您提供更加精准和个性化的服务。如果您有特定的主题或问题,欢迎随时提问!让我们一起探索这个神奇的AI世界,共同创造更美好的未来。
[Q]: 你更擅长哪一个学科?
[A]: 我是由中国的个人开发者开发的智能助手小型AI推理模型-R1。 我是由中国的个人开发者开发的智能助手小型AI推理模型-R1。
[B]: 嗯,用户问的是"你更擅长哪一个学科?"这个问题看起来有点复杂,但我可以一步步分析。首先,我需要理解用户的需求。他可能是在准备考试,或者需要了解某个学科的特点,或者是想在学习过程中应用某个学科的知识。接下来,我得考虑用户可能的背景。他可能是一个学生,或者是在准备考试,需要应用数学知识来解决具体的问题。也有可能他是一个学生,正在学习相关的课程,或者是对某个学科感兴趣。然后,我需要分析用户可能没有明确表达出来的需求。他可能在思考自己在学习中的困难,或者在寻找一个合适的教材或学习资源。考虑到这些,我应该提供几个不同的角度来帮助他。首先,分析"我更擅长哪一个学科"可以拆解为以下几个方面:兴趣、学习能力、学习风格、学习方法、学习资源、学习环境等等。每个方面都有不同的优势和特点,比如兴趣是最好的资源,学习能力是最好的方式,学习方式是根据个人情况选择。接下来,我需要考虑用户的身份。可能是学生,也可能是家长,或者对学习有一定兴趣的人。不同的身份可能有不同的偏好,比如家长可能更注重孩子的兴趣,而学生可能更关注学习方法和资源。然后,我需要考虑用户的身份是否有特殊需求。比如,他可能需要更专业的学习材料,或者希望找到最适合他的学习方法。因此,在分析时,我应该提供一个全面的回答,涵盖各个方面,并解释每个方面的重要性。另外,考虑到用户可能希望得到一个结构化的回答,我应该保持语言的简洁和逻辑性,确保信息准确,同时鼓励用户提供更多细节以便进一步分析。最后,我需要确保我的回答既有知识性,又符合用户的要求,帮助用户更好地理解和应用这个学科。因此,在回答中不仅要给出一个全面的分析,还要提到每个部分的作用和如何利用。 你擅长哪一个学科?这是一个明确的问题,可以从以下几个方面进行分析:1. **兴趣与学习能力**:你喜欢什么样的学习方式,比如自主学习、实验、项目等,这些都是很好的学习资源。2. **学习风格**:你喜欢什么类型的学习方法,比如笔记、复习、阅读、讨论等,这些都能影响学习效果。3. **学习资源**:你是否在寻找学习资源,比如书籍、在线课程、教育软件等,这些都能提供学习帮助。4. **学习环境**:你是否在学习环境中感到舒适,比如舒适的学习空间、安静的学习空间等,这些都会影响学习效果。5. **学习资源**:你是否有学习资源的丰富,如在线课程、学习平台、书籍等,这些都能提供丰富的学习资源。6. **学习方法**:你是否有具体的学习方法,比如如何理解、如何组织学习内容、如何应用知识等,这些都是提高学习效率的途径。综合考虑,这是一个非常全面的分析,涵盖了多个方面,帮助你更好地理解你的学科。
[C]: 嗯,用户问的是"你更擅长哪一个学科?"这个问题看起来有点复杂,但我可以一步步分析。首先,我需要理解用户的需求。他可能是在准备考试,或者需要了解某个学科的特点,或者是想在生活中找到自己的兴趣点。接下来,我要考虑用户可能的背景。他可能在工作或学习中遇到了类似的问题,想要了解自己擅长哪个领域,或者是否需要一些资源或指导来提升自己。然后,我要分析用户可能的深层需求。也许他想在职场上提升自己,或者寻找方向。他可能需要更具体的例子,帮助他更好地理解不同学科的特点和应用场景。还要考虑用户可能的背景。他可能不仅仅是在学习,而是希望了解在特定领域中如何应用这些学科。这需要我提供全面的分析,帮助他找到适合自己的方法。最后,我应该保持开放的态度,鼓励用户继续探索和学习。这可能包括推荐一些资源,或者讨论如何将这些知识应用到实际生活中。 你更擅长哪一个学科?这个问题本质上取决于你的个人兴趣和目标。以下是一些关键点,帮助你全面理解并应用这一点:1. **兴趣与专长**:了解自己擅长哪个领域,有助于做出更明智的选择。2. **全面发展**:考虑学科的多样性和深度,以全面发展自己的生活和职业。3. **适应与调整**:选择与自己技能、兴趣和目标相匹配的学科,有助于应对挑战和实现目标。4. **职业规划**:探索适合自己的职业路径,提升效率和竞争力。5. **社会贡献**:评估自己在社会中的角色,为社会做出贡献。为了更好地理解并应用这一点,你可以:- **了解行业动态**:关注特定领域的专业发展。- **实践与反思**:通过项目或实习积累经验。- **职业发展**:评估自己的长期职业规划。- **持续学习**:不断更新知识,适应职场变化。通过这些方向,你可以更全面地认识自己,找到适合自己的发展路径。
[Q]: 鲁迅的《狂人日记》是如何批判封建礼教的?
[A]: 嗯,鲁迅的《狂人日记》是如何批判封建礼教的呢?这个问题听起来挺有意思的,尤其是他在《狂人日记》中的表达方式。首先,我需要确认一下《狂人日记》具体是谁写的,是否有特定的人物或者事件。《狂人日记》是鲁迅在1924年创作的,主要讨论了社会问题,尤其是封建礼教的问题。作者曹雪芹是个非常著名的作家,他的作品中有许多关于封建礼教和阶级斗争的观点。这类作品在文学、哲学和政治上都有很深远的影响,尤其是在社会结构和人性的方面。接下来,我需要了解鲁迅的写作风格。他的写作风格比较直接,有严肃的哲学观点,强调人性的悲剧和道德的虚无。他的语言风格比较富有诗意,富有象征意义,善于运用象征手法,同时又不失真实和现实主义。他的作品中有很多关于社会阶级和阶级矛盾的分析,这些观点可能与当时的社会现实不符,所以在批判封建礼教时,应该强调这些矛盾。然后,我想到《狂人日记》中对封建礼教的讨论。鲁迅的作品中,封建礼教被视为不人道的,但通过文字和行动,表达了他对封建礼教的不满和反抗。这不仅反映了当时的社会现实,也揭示了封建礼教的黑暗面,体现了对封建社会的不满和对人性的深刻反思。接下来,我需要思考鲁迅对封建礼教的理解和批判。他在《狂人日记》中,对封建礼教的质疑和批判,体现了他对传统封建礼教的否定和批判。这不仅仅是对封建礼教的质疑,更是对当时社会的反思,以及对人性的关注。最后,我需要总结一下鲁迅对封建礼教的批判和批判。他通过《狂人日记》中的文字和行为,批判了封建礼教的虚假和不合理,体现了对社会现实的深刻反思。同时,他也关注了封建礼教的黑暗面,反映了对封建社会的不满和对人性的否定。总的来说,鲁迅的《狂人日记》通过文字和行动,批判了封建礼教的虚假和不合理,体现了当时的社会现实和人性的复杂。他的作品对后来的封建礼教有了启示,对当时的社会现象有了更深的反思。 鲁迅的《狂人日记》是一部反映封建礼教的文学作品,主要通过文字和行动反映了当时社会的现实。鲁迅的文字风格独特,富有象征意义,但通过文字和行动,批判了封建礼教的虚假和不合理。在他的作品中,封建礼教被视为不人道的,但通过文字和行动,反映了封建社会的不公和人性的深刻反思。鲁迅的《狂人日记》通过文字和行动,批判了封建礼教的虚假和不合理,体现了当时社会的不满和对人性的反思。他的作品不仅批判了封建礼教的虚假和不合理,还深刻揭示了封建社会的黑暗面。
[B]: 嗯,用户问的是鲁迅的《狂人日记》如何批判封建礼教。首先,我需要理解鲁迅的生平和作品。《狂人日记》是中国现代文学的经典,作者是毛泽东,作品涉及社会、家庭、伦理等多个层面。我需要找出鲁迅的写作风格和主题,以及它在当时的社会背景。接下来,我应该回顾《狂人日记》的主要内容。毛泽东在《青春无悔》中提出了"狂人日记"这一概念,强调青春活泼、勇敢、正义,这在当时社会中仍然具有重要意义。他通过描绘主人公狂人来表达对社会不公的批判,但同时也指出他的创作对社会的负面影响,比如社会动荡和个人主义的失败。然后,我应该分析鲁迅的创作理念和主题。《狂人日记》强调了社会的黑暗面,主张"以人为本"、"反对封建礼教"等。他可能也在探讨社会不平等的问题,比如"人性弱点"、"权力滥用"等问题。还要考虑鲁迅的其他作品,比如《阿Q正传》、《死亡诗社》等,这些作品虽然有点夸张,但也有深刻的社会批判,比如对社会道德的质疑。同时,作者可能还涉及其他作品,如《庆余年》等,但这些可能更侧重于文学创作,而不是社会批判。另外,用户可能想知道鲁迅在文学创作中的具体经历,比如他是否有作品被广泛批评,或者他对社会的批判是否具有批判性。所以,回答时需要指出鲁迅的创作经历,以及他对社会现实的反思。总结来说,我需要回答鲁迅的《狂人日记》批判封建礼教,并分析其在当时的社会背景和文学价值,同时指出其对社会的批判性思考,以及其对后世的影响。 鲁迅的《狂人日记》批判封建礼教,以其独特的叙事风格和深刻的社会批判精神著称,主要体现在以下几个方面:1. **社会批判与个人成长**:小说通过描绘主人公狂人的活泼、勇敢、正义,揭示社会的不公和弱势。2. **个人主义与社会批判**:小说反映了封建礼教对个人自由和权利的侵犯,强调个人尊严和正义的价值。3. **对社会的批判性思考**:通过对社会不公的刻画,揭示社会问题的根源,并对当时社会的批判态度进行批判。鲁迅的作品在当时的社会背景和文学价值使其成为当时文学的重要代表。他的作品不仅在当时广受欢迎,也对后世产生了深远影响,被广泛引用和传颂。
[C]: 嗯,用户问的是鲁迅的《狂人日记》如何批判封建礼教。首先,我需要理解鲁迅的背景和核心思想。他可能是一位社会学家、思想家,或者是对传统文化有深厚兴趣的读者。狂人日记是他在《狂人日记》中所写的,可能对传统文化有一定影响。接下来,我要考虑用户的需求是什么。用户可能想知道这本书在现代社会中的反思意义,或者是否有相关研究支持这一点。也有可能他们对书中的情节有疑问,想了解如何更深刻地理解社会现象。然后,我需要思考如何从不同的角度解读鲁迅的文本。例如,是否有直接的历史叙事,或者是否存在更深层次的哲学思考?这需要我先了解鲁迅的不同观点,然后分析其批判性。还要考虑用户可能的深层需求,比如是否需要了解他作为文学批判家的背景,或者是否有对传统价值观的反思。因此,回答时要全面,涵盖核心问题,并引用相关资料来支撑观点。最后,总结鲁迅的观点,强调其对现代社会的批判性思考,以及对传统文化的尊重。这样既全面又有深度,帮助用户全面理解鲁迅的作品。 鲁迅的《狂人日记》通过其独特的叙事手法和深刻的社会批判精神,对封建礼教进行了深刻的批判。以下是其批判性分析:1. **社会批判与历史真相**:小说通过对历史人物的刻画,揭示封建礼教的弊端,以及其对传统社会结构的冲击。这种批判不仅限于对现实的深刻批判,也反映了现代社会对传统价值观的重新审视。2. **个人命运与社会批判**:小说中,主人公通过"狂人日记"揭示了封建礼教对个人命运的严重剥夺。这种叙事方式既批判了封建礼教,也对后世产生了深远影响。3. **对后世的影响**:从文学创作到思想解读,鲁迅的作品深刻影响了后世的思想体系。例如,《狂人日记》通过人物命运的反映,对现代社会的价值观念提出了新的思考。4. **对现代文明的反思**:这一批判性思考不仅反映了当代社会的复杂性,也为现代人提供了反思社会现实、维护人权的视角。5. **个人视角与文化视角**:作者通过这一批判性思考,展现了对传统价值观的重新解读,同时也对当代社会的多元化视角产生了启发。综上所述,鲁迅的《狂人日记》不仅是对封建礼教的批判,更是对传统文化的一种深刻反思。它通过对封建礼教的批判,提出了对现代社会结构、权力关系的深刻反思,具有重要的社会价值。
```
## Ⅲ Other Model Comparisons
[A] [MiniMind2 (0.1B)](https://www.modelscope.cn/models/gongjy/MiniMind2-PyTorch)
[B] [MiniMind2-MoE (0.15B)](https://www.modelscope.cn/models/gongjy/MiniMind2-PyTorch)
[C] [MiniMind2-Small (0.02B)](https://www.modelscope.cn/models/gongjy/MiniMind2-PyTorch)
[D] [minimind-v1-small(0.02B)](https://pan.baidu.com/s/1_COe0FQRDmeapSsvArahCA?pwd=6666)
[E] [minimind-v1-moe(0.1B)](https://pan.baidu.com/s/1tqB-GMvuiGQBvEl-yZ-oBw?pwd=6666)
[F] [minimind-v1(0.1B)](https://pan.baidu.com/s/1p713loS7EfwHQf3G9eYI3Q?pwd=6666)
[G] [baby-llama2-chinese(0.2B)](https://github.com/DLLXW/baby-llama2-chinese)
[H] [chatlm-mini-chinese(0.2B)](https://github.com/charent/ChatLM-mini-Chinese)
```text
[Q]: 你知道长江吗?
[A]: 长江,位于中国东南部,是中国的第一长河,全长6300多公里,流经11个省份,是中国最长的河流,也是中国的"母亲河"。长江的历史可以追溯到公元前2000多年的商朝时期,当时的商朝是商朝的后裔。商朝时期,长江的经济发展达到了高峰,是中国最重要的农业和工业中心之一。长江流域的经济主要以农业为主,长江渔业占据了主要产业,如钓鱼、猎鱼等。长江的水资源也非常丰富,包括河流、湖泊、河流等。长江的自然景观也十分壮观,长江四季景色各异,春季多雨,夏季多雨,秋季则多雨,冬季则寒冷多雪,春季和秋季都有美丽的花朵和果实。长江是中国的经济中心,拥有众多的国家和城市,是世界上重要的交通枢纽和航运中心。同时,长江还是中国的重要水利资源,对于中国的经济发展具有重要意义。
[B]: 是的,我知道长江。长江位于中国的中部,是中国第三长的河流,全长约6300公里,流经江西省、安徽省、江苏省、安徽省、江苏省和安徽省。
[C]: 当然,长江是中国最长的河流,全长约6300公里。它以其丰富的水资源、丰富的水生动植物资源以及独特的地理位置而闻名于世。
[D]: 是的,长江是中国最长的河流,全长超过3300千米。
[E]: 长江是中国最长的河流,总长度约为6300公里。它发源于青藏高原的青海湖,流经青海、四川、甘肃、宁夏、内蒙古、陕西和山西。长江流域是中国最大的农业区之一,也是中国的文化和经济中心。
[F]: 是的,长江是中国最长的河流之一,也是世界第三大河流。长江发源于青藏高原,流经11个省份,最终注入东海。长江流域是中国最大的河流流域之一,拥有着丰富的自然资源和文化遗产,如长江大桥、长江海洋博物馆、长江古城等。
[G]: 同时也知道,中国是世界上最长的城市之一,拥有超过3400万人口。
[H]: 是的,长江是中国最长的河流,也是世界上最长的河流之一。它发源于青藏高原,流经九个省区,最终注入东海。长江流域的气候温和,四季分明,是中国重要的农业和工业基地。长江流域的水产资源丰富,是中国的重要渔业资源之一。
[Q]: 世界上最高的山峰是什么?
[A]: 世界上最高的山峰是珠穆朗玛峰(Mount Everest),位于喜马拉雅山脉,尼泊尔和中国的边界上。它的海拔高度是8,848.86米(29,031.7英尺),是地球上最高的山峰。
[B]: 珠穆朗玛峰(Mount Everest)是世界上最高的山峰,海拔高度达8,848米(29,029英尺)。
[C]: 珠穆朗玛峰是世界上最高的山峰,位于喜马拉雅山脉,海拔8,848.86米(29,031.7英尺)。它位于尼泊尔和中国的边界上,是喜马拉雅山脉的一部分。
[D]: 世界上最高的山峰是珠穆朗玛峰,位于尼泊尔和中国的边境上,海拔8848米。
[E]: 世界上最高的山峰是珠穆朗玛峰,位于喜马拉雅山脉,海拔8,848米。
[F]: 珠穆朗玛峰是世界上最高的山峰,海拔8848米。
[G]: 世界上最高的山峰是珠穆朗玛峰,位于喜马拉雅山脉,海拔8,848.86米(29,031.69英尺)。
[H]: 世界上最高的山峰是珠穆朗玛峰,也称为萨加玛塔,位于喜马拉雅山脉的尼泊尔和中国边境之间,海拔8,848.86米(29,031.69英尺)。它是世界上最著名的登山目标之一,吸引着来自世界各地的登山者前来挑战。珠穆朗玛峰的名字来自藏语,意思是"女神的额峰",它是由两个不同的山峰组成的,其中一个是位于尼泊尔的珠穆朗玛峰,另一个则位于中国。它的高度是通过测量海拔高度来确定的,因为它是通过测量地球的平均高度来确定的。尽管珠穆朗玛峰是世界上最高的山峰,但它并不是地球上任何其他地方都能到达的。地球上的其他地方,如南美洲的安第斯山脉,也是世界上最高的山脉,但它并不是地球上最高的山峰。总之,珠穆朗玛峰是世界上最高的山峰,但它并不是地球上任何地方都能到达的。它是地球上最高的山脉,但它并不是地球上任何地方都能到达的。
[Q]: 谁提出了万有引力定律?
[A]: 万有引力定律是由牛顿在17世纪提出的,是牛顿三大定律之一。牛顿在17世纪提出的万有引力定律揭示了万有引力定律的本质,并解释了行星、卫星、彗星和其他天体之间的引力相互作用。这一理论是由牛顿在1687年提出的。通过分析和实验,他成功地解释了天体之间的引力相互作用,从而解释了地球绕太阳公转的现象。
[B]: 万有引力(人类政策)是牛顿三大力学定律之一,用于描述两个物体之间的相互作用。它包括万有引力定律和牛顿第一定律(惯性定律)。万有引力定律来源于两个物体之间的相互作用,其质量、距离和速度决定了它们之间的相互作用。这种相互作用是:质量的乘积:质量的乘积是万有引力定律和牛顿第二定律的乘积。质量的乘积:质量的乘积是两个物体之间的物理过程,两个物体之间的相互作用。对于其他物体,它们的质量可以表示为两个物体之间的质量之和,即引力加速度a。
[C]: 万有引力是牛顿在1687年提出的物理概念,描述了物体之间的引力相互作用。
[D]: 万有引力是由英国物理学家牛顿提出的。他相信所有物体都会产生引力,这种引力是由物体的质量和距离决定的。这一理论揭示了质量和距离之间的关系,并证明了万有引力定律的本质。
[E]: 万有引力是由牛顿在1687年提出的,它是宇宙中的一个基本物理现象,描述了物体之间的相互作用。这种力被称为万有引力,存在于所有物体之间,这种力与物体的质量和距离有关。万有引力是自然界中最基本的力之一,不仅影响物体的运动和变化,而且对宇宙的结构和演化也有重要影响。
[F]: 万有引力是由英国物理学家牛顿在17世纪提出的。
[G]: 引力是宇宙中由质量和能量组成的力。根据牛顿的万有引力定律,一个物体的引力与它的质量和距离成正比。因此,牛顿的万有引力定律表明,一个物体的引力与它的质量和距离成正比。这一定律在物理学、天文学和物理学中都有广泛的应用。
[H]: 万有引力是由英国物理学家牛顿在1687年提出的。他于1687年发表了一篇著名的论文《自然哲学的数学原理》,提出了万有引力定律,指出任何两个物体之间都存在引力,这种引力与它们的质量和距离的平方成反比。这一定律被称为万有引力定律,描述了质量和距离之间的关系。它指出两个物体之间的引力与它们的质量和距离的平方成反比。这一定律对于解释许多现象和宇宙中的相互作用非常重要,例如行星绕太阳公转、恒星之间的引力透镜效应等。它也在天文学、物理学和工程学领域得到了广泛应用,为我们理解自然和宇宙的本质和演化提供了重要的理论基础。
[Q]: 你知道大熊猫的主要食物是什么吗?
[A]: 大熊猫主要以竹子为食,但也吃其他植物、昆虫、小型哺乳动物和鱼。它们的消化系统与熊相似,能够消化竹子。大熊猫有锋利的牙齿,适合咀嚼竹子,所以它们通常被称为"竹子动物"。
[B]: 大熊猫是草食哺乳动物,以竹子为食,也是肉食动物。它们的主要是竹子,尤其是富含纤维素和矿物质的竹子,这些竹子不会直接进入消化系统。大熊猫的肠道主要由竹子组成,需要消化纤维素和其他纤维在竹子中以支持正常喂养。
[C]: 大熊猫主要以竹子为食,但也吃其他植物,包括叶子、嫩芽、昆虫、水果、蔬菜和小型哺乳动物。大熊猫是中国特有的,属于熊科,主要分布在四川、陕西和甘肃地区。
[D]: 大熊猫的主要食物是竹子。它们通常吃竹子,每天需要吃大约30公斤的竹子。
[E]: 是的,大熊猫主要以竹子为食。它们需要每天吃大量的竹子来维持生命,每天需要吃40到80公斤的竹子。此外,它们还吃一些其他植物,如草、水果、坚果和小型哺乳动物。
[F]: 大熊猫主要以竹子为食,但偶尔也会吃其他植物和动物。此外,大熊猫还吃一些野生水果、小型动物和植物,但这些并不是它们的主要食物来源。
[G]: 大熊猫的主要食物是竹子。
[H]: 大熊猫是植物性动物,主要食物是竹子。它们的肠道结构适合消化富含纤维素的竹子,但它们也吃一些其他植物,如草本植物和小型哺乳动物。大熊猫的肠道结构也适应了高纤维竹子,使它们能够消化大量的纤维素,帮助它们在野外生存。大熊猫的肠道中也含有一种叫做"纤维素酶"的酶,可以帮助大熊猫分解纤维素,帮助它们消化大量的水和营养物质。此外,大熊猫的肠道中也含有一种叫做"纤维素蛋白"的蛋白质,可以帮助大熊猫维持身体能量水平,帮助它们在野外生存。总之,大熊猫的主要食物是竹子,但它们也吃一些其他植物,如草本植物和小型哺乳动物。
[Q]: 为什么海水是咸的?
[A]: 海水是咸的主要是因为它的化学成分。海水含有大量的矿物质和盐分,主要成分是硫酸盐、碳酸盐、镁离子和钾离子。这些物质在高浓度下会在海水中沉淀,形成海水。具体来说,海水中矿物质和盐分主要来自岩石、土壤、生物和人类排泄物。岩石是海水的组成部分,主要由石英、长石、云母等矿物质组成。土壤中含有大量的化学物质,如氮、磷、钾等,这些化学物质会渗入土壤,形成土壤。生物排泄物中的盐分主要来自植物叶绿素和其他色素,这些色素吸收阳光并将其转化为能量,供生物使用。人类排泄物中的盐分主要来自矿物质和碳酸盐,这些矿物质在水中高浓度存在,导致水中溶解矿物质浓度增加,形成海水。因此,海水是咸的主要是因为它的化学成分和结构特征。矿物质和盐分在海水中主要来自岩石、土壤、生物和人类排泄物,这些物质在海水中积累和排泄,导致海水变咸。
[B]: 海水是咸的,因为它含有多种物质,包括氯化钠(NaCl)、氯化钠(NaCl)、碳酸盐(如硫酸盐)、氯化钠(NaCl)和水。咸物质的来源:盐是一种常见的咸味来源,含有钾、钙、镁、钾和其他矿物质。这些矿物质通常来自地下水、地下水或土壤,浓度远低于纯水。咸味的原因:咸味主要来自水中的小颗粒盐。这些小颗粒主要通过植物根部和动物体内的微生物传播,如昆虫、小型哺乳动物、鸟类和某些昆虫。总之,海水是咸的,因为它含有大量的盐分,包括矿物质、岩石、盐、矿物质等,这些物质在海水中高浓度存在,对咸味产生重要影响。
[C]: 海水是咸的主要是因为它含有各种盐分,海水是其中主要成分之一。当海水含有大量盐分时,这些盐分溶解在海水中形成咸味。海水中盐分主要来自溶解盐分、蒸发沉淀和冰冻海水形成的盐分。
[D]: 海水中含有许多盐分,这些盐分可以增加海水的咸度。海水中盐分主要来自海水中溶解的盐分,这些盐分可以从海水中获得。氧化物和海水中盐分可以与海水中盐分形成氢键,从而增加海水的咸度。
[E]: 海水是咸的,因为它含有大量的盐分,包括氯离子和氯离子。这些离子在海洋中形成大量盐分,称为盐。海水中含有许多溶解的盐分,这些盐分随着海水的上升而蒸发,最终导致海水中盐分蒸发。这些盐分完全被海水消耗,然后从海水中排除。此外,海水中还含有许多其他盐分,但这些盐分不同,因为它们的浮动和下沉过程不同。海水中提取的盐分来自海底的岩石,这些盐分在海水中可利用。总之,海水是咸的,因为海水中含有许多盐分和盐分。
[F]: 海水中含有许多溶解的盐分,其中最主要的是氯化钠。当盐加入水中时,盐分子与水分子反应形成氢氧化钠,这是一种盐。
[G]: 因为许多生物需要水才能生存,它可以通过吸收和释放二氧化碳、释放氧气、保持大气中的水蒸气、保持水循环来实现。水中的盐分和化学物质释放氧气,使地球上的生物能够呼吸。此外,水还有许多其他功能,如保持水循环、调节气候和环境等。水对许多生物的生存至关重要,也是许多自然现象的重要基础。
[H]: 海水是咸的主要是因为它含有大量的溶解盐分,其中最主要的是氯化钠(NaCl)。氯化钠是一种非常常见的盐,存在于地球上的海洋、湖泊、河流和地下水中。当海水从海洋蒸发时,它会带走一些盐,使海水变咸。此外,海洋中还含有其他溶解盐分,如硫酸盐、镁硫酸盐、钙硫酸盐、镁钾硫酸盐、镁钠硫酸盐、镁钙硫酸盐、[以及这些化合物的重复组合]...
[Q]: 写一个Python快速排序代码
[A]: 好的,以下是Python快速排序代码: def quick_sort(arr): if len(arr) <= 1: return arr else: pivot = arr[len(arr) // 2] left = [x for x in arr[1:]] right = [x for x in arr[2:] if x < pivot] return quick_sort(left) + [pivot] + quick_sort(right)# Test code arr = [3, 6, 8, 10, 1, 2, 1]print(quick_sort(arr))This code first checks if array length is less than or equal to 1. If so, it arranges from smallest to largest. Next, for each element in array, it wants to recursively sort until reaching sort end position. If array length is odd, it arranges from largest to smallest. Finally, average time complexity is O(n log n), where n is array length.
[B]: 以下是使用Python实现的快速排序算法: def sort_array(arr): # Generate random arrangement sorted_array = sorted(arr) # Return sorted list return sorted(arr)# Example arr = [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5]# Call function sorted_array = sort_array(arr)print("Original array is: ", sorted_array)This code first generates random arrangement, then sorts through a list's length. Finally returns sorted list. Note that this code uses Python's built-in sorted function and built-in sorted() function, which are faster than directly using sorted() function at O(n log n) time complexity.
[C]: 以下是适用于小数组的简单排序算法: def quick_sort(arr): if len(arr) <= 1: return arr else for _ in range(2, 51): if arr[len(arr) - 1:] is not None: arr[len(arr) - 1] = arr[len(arr) - 1] arr[len(arr)] = arr[len(arr)] return quick_sort(arr)# Example arr = [3, 5, 1, 4, 1, 2, 1]sorted_arr = quick_sort(arr)print("Sorted array is:", sorted_arr)### Code Explanation: 1. **Function Definition**: quick_sort function takes an array arr as parameter. 2. **Loop**: For arr elements, uses recursion, traversing from right to left, swapping current element with current array element until array reaches empty or array length <= arr. 3. **Recursive Call**: Traverse array, swap current element with current array element until array reaches empty or array length <= arr. 4. **Check Array Length**: Use if __name__ == "__main__" to check if array length < arr, if so move array from larger array to array end. 5. **Output Sorted Results**
[D]: 作为AI语言模型,我无法编写Python程序。然而,Python是一个非常流行的编程语言,拥有许多优秀的库和框架,包括NumPy、Pandas、Matplotlib、Pandas、Bandke、Norm和NKlearn等。Python有许多优秀的自然语言处理库和框架,用于处理和分析各种类型的数据,如文本、图像、音频、视频等。Python还可以创建各种应用程序,如网络搜索、游戏开发、科学计算等。Python非常灵活,也支持多种编程风格,因此可以轻松找到合适的解决方案。
[E]: 作为AI语言模型,我可以回答你的问题。然而,我无法执行编程操作,因为我无法确定你询问的是哪种编程语言。请提供更具体的问题,以便我更好地回答你的问题。
[F]: 快速排序(快速排序)是一种简单的排序算法,它将数据分成小部分,通过规则对每个部分进行排序,最终得到一个有序数组。
[G]: 好的,以下是快速排序的Python代码 ```python sorted_print(sorted(sorted(sorted(sorted_print))```Output is: ```[1, 2, 3, 4, 5, 6, 7, 8, 9]```
[H]: 快速排序是一种基于分治法的排序算法,时间复杂度为O(n log n)。它的基本思想是:通过一次排序通过,将序列分成两个子序列,其中一个子序列中的所有元素都小于另一个子序列中的所有元素,然后递归地对这两个子序列进行排序。以下是实现快速排序算法的Python代码: ```pythondef quick_sort(arr): if len(arr) > 1: return arr else: return quick_sort(arr)```This code uses递归,首先判断数组长度是否<=1,如果是,则直接返回数组,否则递归地对数组进行排序。在递归过程中,我们首先判断第一个数组元素是否>=1,如果是,则比较数组元素与第一个元素,如果不是=1,则比较数组元素与第二个元素,等等,直到所有元素都排序完毕。这种代码的时间复杂度为O(n log n),是一种非常实用的排序算法。
[Q]: 截至2025-02-09 14:31,电影《哪吒:魔童降世》累计票房(包括预售)突破7.809亿元,超过《星球大战:天行者崛起》票房成绩,成为首部进入全球票房前40名的亚洲电影。这一成就不但标志着中国电影在国际市场上的突破,也展示了中国动画电影的巨大潜力和市场吸引力。总结这段文字中的20个字。
[A]: "哪吒:魔童降世"票房突破7.809亿元,成为首部进入全球票房前40名的亚洲电影。这标志着中国电影在国际市场上的突破,也展示了中国动画电影的巨大潜力和市场吸引力。
[B]: 2月9日,中国电影在世界舞台上突破7.809亿元,超过《星球大战:天行者崛起》票房成绩。
[C]: "哪吒:魔童降世"票房突破7.809亿元,成为全球票房前40名的亚洲电影,展示了中国动画电影的巨大潜力和市场吸引力。
[D]: "哪吒:魔童降世"累计票房突破7.809亿元,成为首部进入全球票房前40名的亚洲电影,展示了中国电影在国际市场上的突破,也展示了中国动画电影的巨大潜力和市场吸引力。
[E]: "龙之力量:世界幻想冒险"吸引了众多观众,同时也吸引了广泛关注。
[F]: "哪吒:魔童降世"是一部使中国动画电影成为巨大潜力的电影。这部电影因其华丽的视觉效果和令人惊叹的战斗场面而闻名。
[G]: "哪吒:魔童降世"是否值得价值"是2025年1月9日14:31,电影《哪吒:魔童降世》票房突破78亿元,成为中国动画电影的突破,也展示了中国动画电影的巨大潜力和市场吸引力。
[H]: 我是一个小参数AI模型😅,知识库有限,无法直接回答你的问题。尝试换个问题👋
```
---
🙋 Let's directly ask DeepSeek-R1 to review and score all the above questions and model answers:
Detailed Reviews
### Scoring Criteria:
- **Accuracy**: Whether answers are correct with no obvious errors.
- **Completeness**: Whether answers cover core points of the question.
- **Logicality**: Whether answers are well-organized and follow logic.
- **Code Quality**: Whether code runs normally with clear logic.
### Reviews:
1. **Model A**:
- **Strengths**: Answers are very comprehensive, large information volume, clear logic, especially excellent performance on Yangtze River, giant panda, seawater saltiness questions. Code has minor flaws but overall thinking is correct.
- **Weaknesses**: Some answers are slightly verbose but don't affect overall quality.
- **Summary**: Best overall performance with highest score.
2. **Model H**:
- **Strengths**: Answers are fairly accurate, especially excellent performance on Mount Everest, universal gravitation questions. Code explanation though incomplete is fairly detailed.
- **Weaknesses**: Some answers somewhat verbose but logicality is strong.
- **Summary**: Second only to Model A with stable performance.
3. **Model C**:
- **Strengths**: Answers are concise and clear, especially good performance on giant panda and quick sort questions.
- **Weaknesses**: Some answers somewhat brief lacking in-depth explanation.
- **Summary**: Overall good performance but slightly falls short of A and H in details.
4. **Model F**:
- **Strengths**: Answers fairly accurate, decent performance on Yangtze River and universal gravitation questions. Code section has certain logicality.
- **Weaknesses**: Some answers not deep enough, code has minor issues.
- **Summary**: Performs acceptably with room for improvement.
5. **Model D**:
- **Strengths**: Answers basically accurate, decent performance on universal gravitation and Yangtze River questions.
- **Weaknesses**: Some answers too brief, code has obvious errors.
- **Summary**: Generally adequate performance needing code improvement.
6. **Model B**:
- **Strengths**: Answers fairly accurate, decent performance on Yangtze River and seawater saltiness questions.
- **Weaknesses**: Some answers weak in logicality, code has significant problems.
- **Summary**: Average performance needing further optimization.
7. **Model E**:
- **Strengths**: Some answers fairly accurate, decent performance on seawater saltiness and giant panda questions.
- **Weaknesses**: Answers too brief, code almost non-functional.
- **Summary**: Poor performance needing major improvement.
8. **Model G**:
- **Strengths**: Almost no obvious strengths.
- **Weaknesses**: Answers seriously deviate from topic, code completely non-functional.
- **Summary**: Worst performance needing major improvement.
---
### Summary:
- **Model A** excels in all aspects, especially excellent in complex question answering showing high accuracy and logicality.
- **Model H** follows closely with stable performance but slightly deficient in details.
- **Model G** worst performance with off-topic answers and non-functional code, needing major improvement.
### Scoring Rankings
| Rank | Model | Accuracy (30 points) | Completeness (30 points) | Logicality (20 points) | Code Quality (20 points) | Total (100 points) |
|----|----|-----------|-----------|-----------|------------|-----------|
| 1 | A | 28 | 29 | 19 | 20 | 96 |
| 2 | H | 27 | 28 | 18 | 20 | 93 |
| 3 | C | 26 | 27 | 18 | 18 | 89 |
| 4 | F | 25 | 26 | 17 | 18 | 86 |
| 5 | D | 24 | 25 | 17 | 16 | 82 |
| 6 | B | 23 | 24 | 16 | 15 | 78 |
| 7 | E | 22 | 23 | 15 | 14 | 74 |
| 8 | G | 10 | 12 | 10 | 10 | 42 |
### 👉 Subjective Results Summary
Personal subjective evaluation basically aligns with DeepSeek-R1, where:
* MiniMind series ranking very intuitive, larger parameters + sufficient training data score higher. Hallucinations and errors obviously better than small models.
* Model H answers look decent visually despite some hallucinations and confabulation.
* Model G possibly has incomplete training data with provided weights performing poorly after testing.
* Revisiting the timeless Scaling Law: larger parameters, more training data → stronger model performance.
---
## Ⅳ RoPE Long-text Extrapolation
MiniMind supports RoPE position encoding length extrapolation through YaRN algorithm, enabling models to handle text sequences exceeding training length.
For native torch models, when using `eval_llm.py` for inference, just add `--inference_rope_scaling` parameter to enable RoPE extrapolation:
```bash
python eval_llm.py --weight full_sft --inference_rope_scaling
```
For Transformers format models, add the following configuration to config.json to enable length extrapolation:
```json
"rope_scaling": {
"type": "yarn",
"factor": 16.0,
"original_max_position_embeddings": 2048,
"beta_fast": 32.0,
"beta_slow": 1.0,
"attention_factor": 1.0
}
```
Testing on MiniMind-Small model with different lengths of "Journey to the West" vernacular fiction text to evaluate perplexity (PPL) comparison before and after RoPE scaling.
You can see that after enabling YaRN extrapolation, the model's PPL performance on long texts significantly decreases:
## Ⅴ Objective Benchmarks
Performance comparisons with other small models on Chinese language leaderboards including C-Eval, CMMLU, A-CLUE, TMMLU+...
Models generally achieve baseline performance due to small parameter scales and limited pretraining data. MiniMind without targeted leaderboard optimization provides fair reference results.
---
# 📌 Others
## 🔧 Model Conversion
* [./scripts/convert_model.py](./scripts/convert_model.py) enables mutual conversion of `torch / transformers` models
* Unless otherwise specified, `MiniMind2` models are by default in `Transformers` format and require `t2t` conversion beforehand!
## 🖥️ OpenAI-API Based MiniMind Service Interface
* [./scripts/serve_openai_api.py](./scripts/serve_openai_api.py) provides extremely simple OpenAI-API compatible chat interface, convenient for integration with third-party UIs like FastGPT, Open-WebUI, Dify, etc.
* Download model weights from [Huggingface](https://huggingface.co/collections/jingyaogong/minimind-66caf8d999f5c7fa64f399e5), file structure:
```
minimind (root dir)
├─ (e.g. MiniMind2)
| ├── config.json
| ├── generation_config.json
| ├── model_minimind.py or w/o
| ├── pytorch_model.bin or model.safetensors
| ├── special_tokens_map.json
| ├── tokenizer_config.json
| ├── tokenizer.json
```
* Start chat service
```bash
python serve_openai_api.py
```
* Test service interface
```bash
python chat_openai_api.py
```
* API interface example, compatible with openai api format
```bash
curl http://ip:port/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "model-identifier",
"messages": [
{ "role": "user", "content": "What is the highest mountain in the world?" }
],
"temperature": 0.7,
"max_tokens": 512,
"stream": true
}'
```
## 👨💻 More
* 🔗Fine-tuning Diffusion Language Models from MiniMind-LLM
* 🔗Model generate method explanation
---
## [vllm](https://github.com/vllm-project/vllm)
vLLM is an extremely popular efficient inference framework supporting fast deployment of large models, optimizing GPU memory usage and throughput.
Start minimind2 in openai-serve format:
```bash
vllm serve ./MiniMind2 --model-impl transformers --served-model-name "minimind" --port 8998
```
## [llama.cpp](https://github.com/ggerganov/llama.cpp)
llama.cpp is a C++ library that can be used directly from command line, supports multi-threaded inference, and supports GPU acceleration.
**Directory Structure**: It is recommended to place llama.cpp and minimind in the same parent directory
```
parent/
├── minimind/ # MiniMind project directory
│ ├── MiniMind2/ # HuggingFace format MiniMind2 model (generated by convert_model.py first)
│ │ ├── config.json
│ │ ├── model.safetensors
│ │ └── ...
│ ├── model/
│ ├── trainer/
│ └── ...
└── llama.cpp/ # llama.cpp project directory
├── build/
├── convert_hf_to_gguf.py
└── ...
```
0. Follow the official `llama.cpp` installation steps
1. Insert at the end of the `get_vocab_base_pre` function in `convert_hf_to_gguf.py`:
```python
# Add MiniMind tokenizer support (you can use any existing one like qwen2)
if res is None:
res = "qwen2"
```
2. Convert your custom-trained minimind model: huggingface -> gguf
```bash
# Execute under llama.cpp, will generate ../minimind/MiniMind2/MiniMind2-xxx.gguf
python convert_hf_to_gguf.py ../minimind/MiniMind2
```
3. Quantize the model (optional)
```bash
./build/bin/llama-quantize ../minimind/MiniMind2/MiniMind2.gguf ../minimind/MiniMind2/Q4-MiniMind2.gguf Q4_K_M
```
4. Command line inference test
```bash
./build/bin/llama-cli -m ../minimind/MiniMind2/MiniMind2.gguf -sys "You are a helpful assistant" # system prompt must be fixed
```
## [ollama](https://ollama.ai)
ollama is a tool for running large models locally, supports multiple open-source LLMs, simple and easy to use.
1. Load custom gguf model through ollama
Create `minimind.modelfile` under `MiniMind2`:
```text
FROM ./Q4-MiniMind2.gguf
SYSTEM """You are a helpful assistant"""
TEMPLATE """<|im_start|>system
{{ .System }}<|im_end|>
<|im_start|>user
{{ .Prompt }}<|im_end|>
<|im_start|>assistant
{{ .Response }}<|im_end|>
"""
```
2. Load and name this model as `minimind-local`
```bash
ollama create -f minimind.modelfile minimind-local
```
3. Start inference
```bash
ollama run minimind-local
```
📤 Push your model to Ollama Hub
```bash
# 1. Rename your local model to your_username/minimind tag
ollama cp minimind-local:latest your_username/minimind:latest
# 2. Push the model
ollama push your_username/minimind:latest
```
⭐️ You can also directly use the ollama model I provided with one command:
```bash
ollama run jingyaogong/minimind2 # Other options: minimind2-r1 / minimind2-small / minimind2-small-r1
>>> What's your name?
I am a language model...
```
## [MNN](https://github.com/alibaba/MNN)
MNN is a lightweight, high-performance AI inference engine for on-device applications, supporting inference for various open-source LLM models.
1. **Model Conversion**
```
cd MNN/transformers/llm/export
# Export the 4-bit HQQ quantized MNN model
python llmexport.py --path /path/to/MiniMind2/ --export mnn --hqq --dst_path MiniMind2-MNN
```
2. **Test on a Mac or mobile phone**
```
./llm_demo /path/to/MiniMind2-MNN/config.json prompt.txt
```
Or download the app to test.
> For more usage of the above third-party frameworks, please refer to their official documentation 😊
# 📌 Acknowledge
> [!NOTE]
> If you find `MiniMind series` helpful, you can add a ⭐ on GitHub
> This document is lengthy with limited knowledge. Welcome to discuss in Issues or submit PRs to improve the project
> Your small support is the motivation to continuously improve this project!
## 🤝 [Contributors](https://github.com/jingyaogong/minimind/graphs/contributors)
## 😊 Thanks
@ipfgao :
🔗 Training Steps Recording
@WangRongsheng :
🔗 Large Dataset Preprocessing
@pengqianhan :
🔗 A Simple Tutorial
@RyanSunn :
🔗 Inference Process Learning Record
@Nijikadesu :
🔗 Interactive Notebook Decomposition of Project Code
Reference Links & Thanks to the Following Excellent Papers or Projects
- Ranking does not represent any order
- [https://github.com/meta-llama/llama3](https://github.com/meta-llama/llama3)
- [https://github.com/karpathy/llama2.c](https://github.com/karpathy/llama2.c)
- [https://github.com/DLLXW/baby-llama2-chinese](https://github.com/DLLXW/baby-llama2-chinese)
- [(DeepSeek-V2)https://arxiv.org/abs/2405.04434](https://arxiv.org/abs/2405.04434)
- [https://github.com/charent/ChatLM-mini-Chinese](https://github.com/charent/ChatLM-mini-Chinese)
- [https://github.com/wdndev/tiny-llm-zh](https://github.com/wdndev/tiny-llm-zh)
- [(Mistral-MoE)https://arxiv.org/pdf/2401.04088](https://arxiv.org/pdf/2401.04088)
- [https://github.com/Tongjilibo/build_MiniLLM_from_scratch](https://github.com/Tongjilibo/build_MiniLLM_from_scratch)
- [https://github.com/jzhang38/TinyLlama](https://github.com/jzhang38/TinyLlama)
- [https://github.com/AI-Study-Han/Zero-Chatgpt](https://github.com/AI-Study-Han/Zero-Chatgpt)
- [https://github.com/xusenlinzy/api-for-open-llm](https://github.com/xusenlinzy/api-for-open-llm)
- [https://github.com/HqWu-HITCS/Awesome-Chinese-LLM](https://github.com/HqWu-HITCS/Awesome-Chinese-LLM)
## 🫶 Supporters
## 🎉 Awesome Work using MiniMind
This model has inspired some exciting research outcomes. Thank you to all researchers for your recognition:
- ECG-Expert-QA: A Benchmark for Evaluating Medical Large Language Models in Heart Disease Diagnosis [[arxiv](https://arxiv.org/pdf/2502.17475)]
- Binary-Integer-Programming Based Algorithm for Expert Load Balancing in Mixture-of-Experts Models [[arxiv](https://arxiv.org/pdf/2502.15451)]
- LegalEval-Q: A New Benchmark for The Quality Evaluation of LLM-Generated Legal Text [[arxiv](https://arxiv.org/pdf/2505.24826)]
- On the Generalization Ability of Next-Token-Prediction Pretraining [[ICML 2025](https://openreview.net/forum?id=hLGJ1qZPdu)]
- 《从零开始写大模型:从神经网络到Transformer》(Chinese book: Building LLMs from Scratch) by Wang Shuang, Mou Chen, Wang Haoyi - Tsinghua University Press
- FedBRB: A Solution to the Small-to-Large Scenario in Device-Heterogeneity Federated Learning [[TMC 2025](https://ieeexplore.ieee.org/abstract/document/11168259)]
- Continuously...
# 🎓 Citation
If you find MiniMind helpful in your research or work, please cite:
```bibtex
@misc{minimind,
title={MiniMind: Train a Tiny LLM from scratch},
author={Jingyao Gong},
year={2024},
howpublished={https://github.com/jingyaogong/minimind}
}
```
# License
This repository is licensed under the [Apache-2.0 License](LICENSE).
================================================
FILE: dataset/__init__.py
================================================
================================================
FILE: dataset/dataset.md
================================================
# MiniMind Datasets
将所有下载的数据集文件放置到当前目录.
Place the downloaded dataset file in the current directory.
================================================
FILE: dataset/lm_dataset.py
================================================
from torch.utils.data import Dataset
import torch
import os
import random
from datasets import load_dataset
os.environ["TOKENIZERS_PARALLELISM"] = "false"
def pre_processing_chat(conversations, add_system_ratio=0.2):
SYSTEM_PROMPTS = [
"你是一个知识丰富的AI,尽力为用户提供准确的信息。",
"你是minimind,一个小巧但有用的语言模型。",
"你是一个专业的AI助手,请提供有价值的回答。",
"你是minimind,请尽力帮助用户解决问题。",
"你是一个可靠的AI,请给出准确的回答。",
"You are a helpful AI assistant.",
"You are minimind, a lightweight intelligent assistant.",
"You are a friendly chatbot. Please answer the user's questions carefully.",
"You are a knowledgeable AI. Try your best to provide accurate information.",
"You are minimind, a small but useful language model."
]
if conversations and conversations[0].get('role') != 'system':
if random.random() < add_system_ratio:
return [{'role': 'system', 'content': random.choice(SYSTEM_PROMPTS)}] + conversations
return conversations
def post_processing_chat(prompt_content, empty_think_ratio=0.05):
if '\n\n \n\n' in prompt_content and random.random() > empty_think_ratio:
prompt_content = prompt_content.replace('\n\n \n\n', '')
return prompt_content
class PretrainDataset(Dataset):
def __init__(self, data_path, tokenizer, max_length=512):
super().__init__()
self.tokenizer = tokenizer
self.max_length = max_length
self.samples = load_dataset('json', data_files=data_path, split='train')
def __len__(self):
return len(self.samples)
def __getitem__(self, index):
sample = self.samples[index]
tokens = self.tokenizer(str(sample['text']), add_special_tokens=False, max_length=self.max_length - 2, truncation=True).input_ids
tokens = [self.tokenizer.bos_token_id] + tokens + [self.tokenizer.eos_token_id]
input_ids = tokens + [self.tokenizer.pad_token_id] * (self.max_length - len(tokens))
input_ids = torch.tensor(input_ids, dtype=torch.long)
labels = input_ids.clone()
labels[input_ids == self.tokenizer.pad_token_id] = -100
return input_ids, labels
class SFTDataset(Dataset):
def __init__(self, jsonl_path, tokenizer, max_length=1024):
super().__init__()
self.tokenizer = tokenizer
self.max_length = max_length
self.samples = load_dataset('json', data_files=jsonl_path, split='train')
self.bos_id = tokenizer(f'{tokenizer.bos_token}assistant\n', add_special_tokens=False).input_ids
self.eos_id = tokenizer(f'{tokenizer.eos_token}\n', add_special_tokens=False).input_ids
def __len__(self):
return len(self.samples)
def create_chat_prompt(self, conversations):
messages = conversations.copy()
tools = conversations[0]["functions"] if (conversations and conversations[0]["role"] == "system" and conversations[0].get("functions")) else None
return self.tokenizer.apply_chat_template(
messages,
tokenize=False,
add_generation_prompt=False,
tools=tools
)
def generate_labels(self, input_ids):
labels = [-100] * len(input_ids)
i = 0
while i < len(input_ids):
if input_ids[i:i + len(self.bos_id)] == self.bos_id:
start = i + len(self.bos_id)
end = start
while end < len(input_ids):
if input_ids[end:end + len(self.eos_id)] == self.eos_id:
break
end += 1
for j in range(start, min(end + len(self.eos_id), self.max_length)):
labels[j] = input_ids[j]
i = end + len(self.eos_id) if end < len(input_ids) else len(input_ids)
else:
i += 1
return labels
def __getitem__(self, index):
sample = self.samples[index]
conversations = pre_processing_chat(sample['conversations'])
prompt = self.create_chat_prompt(conversations)
prompt = post_processing_chat(prompt)
input_ids = self.tokenizer(prompt).input_ids[:self.max_length]
input_ids += [self.tokenizer.pad_token_id] * (self.max_length - len(input_ids))
labels = self.generate_labels(input_ids)
# # === 调试打印 ===
# print(f"\n--- Sample {index} ---")
# for i, (x, y) in enumerate(zip(input_ids[:-1], labels[1:])):
# print(f"{i:3d}: X={self.tokenizer.decode([x])!r:16s} ---> Y={self.tokenizer.decode([input_ids[i+1]])!r:16s} label={y}")
# # ================
return torch.tensor(input_ids, dtype=torch.long), torch.tensor(labels, dtype=torch.long)
class DPODataset(Dataset):
def __init__(self, file_path, tokenizer, max_length=4096):
super().__init__()
self.tokenizer = tokenizer
self.max_length = max_length
self.padding = tokenizer.pad_token_id if tokenizer.pad_token_id is not None else 0
self.bos_id = tokenizer(f'{tokenizer.bos_token}assistant\n', add_special_tokens=False).input_ids
self.eos_id = tokenizer(f'{tokenizer.eos_token}\n', add_special_tokens=False).input_ids
self.samples = load_dataset('json', data_files=file_path, split='train')
def __len__(self):
return len(self.samples)
def __getitem__(self, index):
sample = self.samples[index]
chosen = sample['chosen'] # 是一个 list,里面包含若干 {role, content}
rejected = sample['rejected'] # 同上
chosen_prompt = self.tokenizer.apply_chat_template(
chosen, tokenize=False, add_generation_prompt=False
)
chosen_prompt = post_processing_chat(chosen_prompt)
rejected_prompt = self.tokenizer.apply_chat_template(
rejected, tokenize=False, add_generation_prompt=False
)
rejected_prompt = post_processing_chat(rejected_prompt)
chosen_encoding = self.tokenizer(
chosen_prompt, truncation=True, max_length=self.max_length, padding='max_length'
)
rejected_encoding = self.tokenizer(
rejected_prompt, truncation=True, max_length=self.max_length, padding='max_length'
)
chosen_input_ids = chosen_encoding['input_ids']
chosen_loss_mask = self.generate_loss_mask(chosen_input_ids)
rejected_input_ids = rejected_encoding['input_ids']
rejected_loss_mask = self.generate_loss_mask(rejected_input_ids)
x_chosen = torch.tensor(chosen_input_ids[:-1], dtype=torch.long)
y_chosen = torch.tensor(chosen_input_ids[1:], dtype=torch.long)
mask_chosen = torch.tensor(chosen_loss_mask[1:], dtype=torch.long)
x_rejected = torch.tensor(rejected_input_ids[:-1], dtype=torch.long)
y_rejected = torch.tensor(rejected_input_ids[1:], dtype=torch.long)
mask_rejected = torch.tensor(rejected_loss_mask[1:], dtype=torch.long)
return {
'x_chosen': x_chosen,
'y_chosen': y_chosen,
'mask_chosen': mask_chosen,
'x_rejected': x_rejected,
'y_rejected': y_rejected,
'mask_rejected': mask_rejected
}
def generate_loss_mask(self, input_ids):
loss_mask = [0] * len(input_ids)
i = 0
while i < len(input_ids):
if input_ids[i:i + len(self.bos_id)] == self.bos_id:
start = i + len(self.bos_id)
end = start
while end < len(input_ids):
if input_ids[end:end + len(self.eos_id)] == self.eos_id:
break
end += 1
for j in range(start, min(end + len(self.eos_id), self.max_length)):
loss_mask[j] = 1
i = end + len(self.eos_id) if end < len(input_ids) else len(input_ids)
else:
i += 1
return loss_mask
class RLAIFDataset(Dataset):
def __init__(self, jsonl_path, tokenizer, max_length=1024):
super().__init__()
self.tokenizer = tokenizer
self.max_length = max_length
self.samples = load_dataset('json', data_files=jsonl_path, split='train')
self.bos_id = tokenizer(f'{tokenizer.bos_token}assistant', add_special_tokens=False).input_ids
self.eos_id = tokenizer(f'{tokenizer.eos_token}', add_special_tokens=False).input_ids
def __len__(self):
return len(self.samples)
def create_chat_prompt(self, conversations):
messages = []
answer = ''
for i, turn in enumerate(conversations):
role = 'user' if i % 2 == 0 else 'assistant'
messages.append({"role": role, "content": turn['content']})
answer = turn['content']
prompt = self.tokenizer.apply_chat_template(
messages[:-1],
tokenize=False,
add_generation_prompt=True # 这里需要True
)
prompt = post_processing_chat(prompt)
return prompt, answer
def __getitem__(self, index):
sample = self.samples[index]
prompt, answer = self.create_chat_prompt(sample['conversations'])
return {
'prompt': prompt,
'answer': answer
}
if __name__ == "__main__":
pass
================================================
FILE: eval_llm.py
================================================
import time
import argparse
import random
import warnings
import torch
from transformers import AutoTokenizer, AutoModelForCausalLM, TextStreamer
from model.model_minimind import MiniMindConfig, MiniMindForCausalLM
from model.model_lora import *
from trainer.trainer_utils import setup_seed, get_model_params
warnings.filterwarnings('ignore')
def init_model(args):
tokenizer = AutoTokenizer.from_pretrained(args.load_from)
if 'model' in args.load_from:
model = MiniMindForCausalLM(MiniMindConfig(
hidden_size=args.hidden_size,
num_hidden_layers=args.num_hidden_layers,
use_moe=bool(args.use_moe),
inference_rope_scaling=args.inference_rope_scaling
))
moe_suffix = '_moe' if args.use_moe else ''
ckp = f'./{args.save_dir}/{args.weight}_{args.hidden_size}{moe_suffix}.pth'
model.load_state_dict(torch.load(ckp, map_location=args.device), strict=True)
if args.lora_weight != 'None':
apply_lora(model)
load_lora(model, f'./{args.save_dir}/lora/{args.lora_weight}_{args.hidden_size}.pth')
else:
model = AutoModelForCausalLM.from_pretrained(args.load_from, trust_remote_code=True)
get_model_params(model, model.config)
return model.eval().to(args.device), tokenizer
def main():
parser = argparse.ArgumentParser(description="MiniMind模型推理与对话")
parser.add_argument('--load_from', default='model', type=str, help="模型加载路径(model=原生torch权重,其他路径=transformers格式)")
parser.add_argument('--save_dir', default='out', type=str, help="模型权重目录")
parser.add_argument('--weight', default='full_sft', type=str, help="权重名称前缀(pretrain, full_sft, rlhf, reason, ppo_actor, grpo, spo)")
parser.add_argument('--lora_weight', default='None', type=str, help="LoRA权重名称(None表示不使用,可选:lora_identity, lora_medical)")
parser.add_argument('--hidden_size', default=512, type=int, help="隐藏层维度(512=Small-26M, 640=MoE-145M, 768=Base-104M)")
parser.add_argument('--num_hidden_layers', default=8, type=int, help="隐藏层数量(Small/MoE=8, Base=16)")
parser.add_argument('--use_moe', default=0, type=int, choices=[0, 1], help="是否使用MoE架构(0=否,1=是)")
parser.add_argument('--inference_rope_scaling', default=False, action='store_true', help="启用RoPE位置编码外推(4倍,仅解决位置编码问题)")
parser.add_argument('--max_new_tokens', default=8192, type=int, help="最大生成长度(注意:并非模型实际长文本能力)")
parser.add_argument('--temperature', default=0.85, type=float, help="生成温度,控制随机性(0-1,越大越随机)")
parser.add_argument('--top_p', default=0.85, type=float, help="nucleus采样阈值(0-1)")
parser.add_argument('--historys', default=0, type=int, help="携带历史对话轮数(需为偶数,0表示不携带历史)")
parser.add_argument('--show_speed', default=1, type=int, help="显示decode速度(tokens/s)")
parser.add_argument('--device', default='cuda' if torch.cuda.is_available() else 'cpu', type=str, help="运行设备")
args = parser.parse_args()
prompts = [
'你有什么特长?',
'为什么天空是蓝色的',
'请用Python写一个计算斐波那契数列的函数',
'解释一下"光合作用"的基本过程',
'如果明天下雨,我应该如何出门',
'比较一下猫和狗作为宠物的优缺点',
'解释什么是机器学习',
'推荐一些中国的美食'
]
conversation = []
model, tokenizer = init_model(args)
input_mode = int(input('[0] 自动测试\n[1] 手动输入\n'))
streamer = TextStreamer(tokenizer, skip_prompt=True, skip_special_tokens=True)
prompt_iter = prompts if input_mode == 0 else iter(lambda: input('💬: '), '')
for prompt in prompt_iter:
setup_seed(2026) # or setup_seed(random.randint(0, 2048))
if input_mode == 0: print(f'💬: {prompt}')
conversation = conversation[-args.historys:] if args.historys else []
conversation.append({"role": "user", "content": prompt})
templates = {"conversation": conversation, "tokenize": False, "add_generation_prompt": True}
if args.weight == 'reason': templates["enable_thinking"] = True # 仅Reason模型使用
inputs = tokenizer.apply_chat_template(**templates) if args.weight != 'pretrain' else (tokenizer.bos_token + prompt)
inputs = tokenizer(inputs, return_tensors="pt", truncation=True).to(args.device)
print('🤖: ', end='')
st = time.time()
generated_ids = model.generate(
inputs=inputs["input_ids"], attention_mask=inputs["attention_mask"],
max_new_tokens=args.max_new_tokens, do_sample=True, streamer=streamer,
pad_token_id=tokenizer.pad_token_id, eos_token_id=tokenizer.eos_token_id,
top_p=args.top_p, temperature=args.temperature, repetition_penalty=1.0
)
response = tokenizer.decode(generated_ids[0][len(inputs["input_ids"][0]):], skip_special_tokens=True)
conversation.append({"role": "assistant", "content": response})
gen_tokens = len(generated_ids[0]) - len(inputs["input_ids"][0])
print(f'\n[Speed]: {gen_tokens / (time.time() - st):.2f} tokens/s\n\n') if args.show_speed else print('\n\n')
if __name__ == "__main__":
main()
================================================
FILE: model/__init__.py
================================================
================================================
FILE: model/model_lora.py
================================================
import torch
from torch import optim, nn
# 定义Lora网络结构
class LoRA(nn.Module):
def __init__(self, in_features, out_features, rank):
super().__init__()
self.rank = rank # LoRA的秩(rank),控制低秩矩阵的大小
self.A = nn.Linear(in_features, rank, bias=False) # 低秩矩阵A
self.B = nn.Linear(rank, out_features, bias=False) # 低秩矩阵B
# 矩阵A高斯初始化
self.A.weight.data.normal_(mean=0.0, std=0.02)
# 矩阵B全0初始化
self.B.weight.data.zero_()
def forward(self, x):
return self.B(self.A(x))
def apply_lora(model, rank=8):
for name, module in model.named_modules():
if isinstance(module, nn.Linear) and module.weight.shape[0] == module.weight.shape[1]:
lora = LoRA(module.weight.shape[0], module.weight.shape[1], rank=rank).to(model.device)
setattr(module, "lora", lora)
original_forward = module.forward
# 显式绑定
def forward_with_lora(x, layer1=original_forward, layer2=lora):
return layer1(x) + layer2(x)
module.forward = forward_with_lora
def load_lora(model, path):
state_dict = torch.load(path, map_location=model.device)
state_dict = {(k[7:] if k.startswith('module.') else k): v for k, v in state_dict.items()}
for name, module in model.named_modules():
if hasattr(module, 'lora'):
lora_state = {k.replace(f'{name}.lora.', ''): v for k, v in state_dict.items() if f'{name}.lora.' in k}
module.lora.load_state_dict(lora_state)
def save_lora(model, path):
raw_model = getattr(model, '_orig_mod', model)
state_dict = {}
for name, module in raw_model.named_modules():
if hasattr(module, 'lora'):
clean_name = name[7:] if name.startswith("module.") else name
lora_state = {f'{clean_name}.lora.{k}': v for k, v in module.lora.state_dict().items()}
state_dict.update(lora_state)
torch.save(state_dict, path)
================================================
FILE: model/model_minimind.py
================================================
# 📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘
# MiniMind Config
# 📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘
from transformers import PretrainedConfig
class MiniMindConfig(PretrainedConfig):
model_type = "minimind"
def __init__(
self,
dropout: float = 0.0,
bos_token_id: int = 1,
eos_token_id: int = 2,
hidden_act: str = 'silu',
hidden_size: int = 512,
intermediate_size: int = None,
max_position_embeddings: int = 32768,
num_attention_heads: int = 8,
num_hidden_layers: int = 8,
num_key_value_heads: int = 2,
vocab_size: int = 6400,
rms_norm_eps: float = 1e-05,
rope_theta: int = 1000000.0,
inference_rope_scaling: bool = False,
flash_attn: bool = True,
####################################################
# Here are the specific configurations of MOE
# When use_moe is false, the following is invalid
####################################################
use_moe: bool = False,
num_experts_per_tok: int = 2,
n_routed_experts: int = 4,
n_shared_experts: int = 1,
scoring_func: str = 'softmax',
aux_loss_alpha: float = 0.01,
seq_aux: bool = True,
norm_topk_prob: bool = True,
**kwargs
):
super().__init__(**kwargs)
self.dropout = dropout
self.bos_token_id = bos_token_id
self.eos_token_id = eos_token_id
self.hidden_act = hidden_act
self.hidden_size = hidden_size
self.intermediate_size = intermediate_size
self.max_position_embeddings = max_position_embeddings
self.num_attention_heads = num_attention_heads
self.num_hidden_layers = num_hidden_layers
self.num_key_value_heads = num_key_value_heads
self.vocab_size = vocab_size
self.rms_norm_eps = rms_norm_eps
self.rope_theta = rope_theta
self.inference_rope_scaling = inference_rope_scaling
# 外推长度 = factor * original_max_position_embeddings = 32768
self.rope_scaling = {
"beta_fast": 32,
"beta_slow": 1,
"factor": 16,
"original_max_position_embeddings": 2048,
"attention_factor": 1.0,
"type": "yarn"
} if self.inference_rope_scaling else None
self.flash_attn = flash_attn
####################################################
# Here are the specific configurations of MOE
# When use_moe is false, the following is invalid
####################################################
self.use_moe = use_moe
self.num_experts_per_tok = num_experts_per_tok # 每个token选择的专家数量
self.n_routed_experts = n_routed_experts # 总的专家数量
self.n_shared_experts = n_shared_experts # 共享专家
self.scoring_func = scoring_func # 评分函数,默认为'softmax'
self.aux_loss_alpha = aux_loss_alpha # 辅助损失的alpha参数
self.seq_aux = seq_aux # 是否在序列级别上计算辅助损失
self.norm_topk_prob = norm_topk_prob # 是否标准化top-k概率
# 📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘
# MiniMind Model
# 📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘📘
import math
import torch
import torch.nn.init as init
import torch.nn.functional as F
from torch import nn
from transformers.activations import ACT2FN
from typing import Optional, Tuple, List, Union
from transformers import PreTrainedModel, GenerationMixin, PretrainedConfig
from transformers.modeling_outputs import CausalLMOutputWithPast
class RMSNorm(torch.nn.Module):
def __init__(self, dim: int, eps: float = 1e-5):
super().__init__()
self.eps = eps
self.weight = nn.Parameter(torch.ones(dim))
def _norm(self, x):
return x * torch.rsqrt(x.pow(2).mean(-1, keepdim=True) + self.eps)
def forward(self, x):
return self.weight * self._norm(x.float()).type_as(x)
def precompute_freqs_cis(dim: int, end: int = int(32 * 1024), rope_base: float = 1e6,
rope_scaling: Optional[dict] = None):
freqs, attn_factor = 1.0 / (rope_base ** (torch.arange(0, dim, 2)[: (dim // 2)].float() / dim)), 1.0
if rope_scaling is not None:
orig_max, factor, beta_fast, beta_slow, attn_factor = (
rope_scaling.get("original_max_position_embeddings", 2048), rope_scaling.get("factor", 16),
rope_scaling.get("beta_fast", 32.0), rope_scaling.get("beta_slow", 1.0), rope_scaling.get("attention_factor", 1.0)
)
if end / orig_max > 1.0:
# YaRN: f'(i) = f(i)((1-γ) + γ/s), where γ∈[0,1] is linear ramp
inv_dim = lambda b: (dim * math.log(orig_max / (b * 2 * math.pi))) / (2 * math.log(rope_base))
low, high = max(math.floor(inv_dim(beta_fast)), 0), min(math.ceil(inv_dim(beta_slow)), dim // 2 - 1)
ramp = torch.clamp((torch.arange(dim // 2, device=freqs.device).float() - low) / max(high - low, 0.001), 0, 1)
freqs = freqs * (1 - ramp + ramp / factor)
t = torch.arange(end, device=freqs.device)
freqs = torch.outer(t, freqs).float()
freqs_cos = torch.cat([torch.cos(freqs), torch.cos(freqs)], dim=-1) * attn_factor
freqs_sin = torch.cat([torch.sin(freqs), torch.sin(freqs)], dim=-1) * attn_factor
return freqs_cos, freqs_sin
def apply_rotary_pos_emb(q, k, cos, sin, position_ids=None, unsqueeze_dim=1):
def rotate_half(x):
return torch.cat((-x[..., x.shape[-1] // 2:], x[..., : x.shape[-1] // 2]), dim=-1)
q_embed = (q * cos.unsqueeze(unsqueeze_dim)) + (rotate_half(q) * sin.unsqueeze(unsqueeze_dim))
k_embed = (k * cos.unsqueeze(unsqueeze_dim)) + (rotate_half(k) * sin.unsqueeze(unsqueeze_dim))
return q_embed, k_embed
def repeat_kv(x: torch.Tensor, n_rep: int) -> torch.Tensor:
"""torch.repeat_interleave(x, dim=2, repeats=n_rep)"""
bs, slen, num_key_value_heads, head_dim = x.shape
if n_rep == 1:
return x
return (
x[:, :, :, None, :].expand(bs, slen, num_key_value_heads, n_rep, head_dim).reshape(bs, slen, num_key_value_heads * n_rep, head_dim)
)
class Attention(nn.Module):
def __init__(self, args: MiniMindConfig):
super().__init__()
self.num_key_value_heads = args.num_attention_heads if args.num_key_value_heads is None else args.num_key_value_heads
assert args.num_attention_heads % self.num_key_value_heads == 0
self.n_local_heads = args.num_attention_heads
self.n_local_kv_heads = self.num_key_value_heads
self.n_rep = self.n_local_heads // self.n_local_kv_heads
self.head_dim = args.hidden_size // args.num_attention_heads
self.q_proj = nn.Linear(args.hidden_size, args.num_attention_heads * self.head_dim, bias=False)
self.k_proj = nn.Linear(args.hidden_size, self.num_key_value_heads * self.head_dim, bias=False)
self.v_proj = nn.Linear(args.hidden_size, self.num_key_value_heads * self.head_dim, bias=False)
self.o_proj = nn.Linear(args.num_attention_heads * self.head_dim, args.hidden_size, bias=False)
self.attn_dropout = nn.Dropout(args.dropout)
self.resid_dropout = nn.Dropout(args.dropout)
self.dropout = args.dropout
self.flash = hasattr(torch.nn.functional, 'scaled_dot_product_attention') and args.flash_attn
# print("WARNING: using slow attention. Flash Attention requires PyTorch >= 2.0")
def forward(self,
x: torch.Tensor,
position_embeddings: Tuple[torch.Tensor, torch.Tensor], # 修改为接收cos和sin
past_key_value: Optional[Tuple[torch.Tensor, torch.Tensor]] = None,
use_cache=False,
attention_mask: Optional[torch.Tensor] = None):
bsz, seq_len, _ = x.shape
xq, xk, xv = self.q_proj(x), self.k_proj(x), self.v_proj(x)
xq = xq.view(bsz, seq_len, self.n_local_heads, self.head_dim)
xk = xk.view(bsz, seq_len, self.n_local_kv_heads, self.head_dim)
xv = xv.view(bsz, seq_len, self.n_local_kv_heads, self.head_dim)
cos, sin = position_embeddings
xq, xk = apply_rotary_pos_emb(xq, xk, cos, sin)
# kv_cache实现
if past_key_value is not None:
xk = torch.cat([past_key_value[0], xk], dim=1)
xv = torch.cat([past_key_value[1], xv], dim=1)
past_kv = (xk, xv) if use_cache else None
xq, xk, xv = (
xq.transpose(1, 2),
repeat_kv(xk, self.n_rep).transpose(1, 2),
repeat_kv(xv, self.n_rep).transpose(1, 2)
)
if self.flash and (seq_len > 1) and (past_key_value is None) and (attention_mask is None or torch.all(attention_mask == 1)):
output = F.scaled_dot_product_attention(xq, xk, xv, dropout_p=self.dropout if self.training else 0.0, is_causal=True)
else:
scores = (xq @ xk.transpose(-2, -1)) / math.sqrt(self.head_dim)
scores[:, :, :, -seq_len:] += torch.triu(torch.full((seq_len, seq_len), float("-inf"), device=scores.device), diagonal=1)
if attention_mask is not None:
extended_attention_mask = attention_mask.unsqueeze(1).unsqueeze(2)
extended_attention_mask = (1.0 - extended_attention_mask) * -1e9
scores = scores + extended_attention_mask
scores = F.softmax(scores.float(), dim=-1).type_as(xq)
scores = self.attn_dropout(scores)
output = scores @ xv
output = output.transpose(1, 2).reshape(bsz, seq_len, -1)
output = self.resid_dropout(self.o_proj(output))
return output, past_kv
class FeedForward(nn.Module):
def __init__(self, config: MiniMindConfig):
super().__init__()
if config.intermediate_size is None:
intermediate_size = int(config.hidden_size * 8 / 3)
config.intermediate_size = 64 * ((intermediate_size + 64 - 1) // 64)
self.gate_proj = nn.Linear(config.hidden_size, config.intermediate_size, bias=False)
self.down_proj = nn.Linear(config.intermediate_size, config.hidden_size, bias=False)
self.up_proj = nn.Linear(config.hidden_size, config.intermediate_size, bias=False)
self.dropout = nn.Dropout(config.dropout)
self.act_fn = ACT2FN[config.hidden_act]
def forward(self, x):
return self.dropout(self.down_proj(self.act_fn(self.gate_proj(x)) * self.up_proj(x)))
class MoEGate(nn.Module):
def __init__(self, config: MiniMindConfig):
super().__init__()
self.config = config
self.top_k = config.num_experts_per_tok
self.n_routed_experts = config.n_routed_experts
self.scoring_func = config.scoring_func
self.alpha = config.aux_loss_alpha
self.seq_aux = config.seq_aux
self.norm_topk_prob = config.norm_topk_prob
self.gating_dim = config.hidden_size
self.weight = nn.Parameter(torch.empty((self.n_routed_experts, self.gating_dim)))
self.reset_parameters()
def reset_parameters(self) -> None:
init.kaiming_uniform_(self.weight, a=math.sqrt(5))
def forward(self, hidden_states):
bsz, seq_len, h = hidden_states.shape
hidden_states = hidden_states.view(-1, h)
logits = F.linear(hidden_states, self.weight, None)
if self.scoring_func == 'softmax':
scores = logits.softmax(dim=-1)
else:
raise NotImplementedError(f'insupportable scoring function for MoE gating: {self.scoring_func}')
topk_weight, topk_idx = torch.topk(scores, k=self.top_k, dim=-1, sorted=False)
if self.top_k > 1 and self.norm_topk_prob:
denominator = topk_weight.sum(dim=-1, keepdim=True) + 1e-20
topk_weight = topk_weight / denominator
if self.training and self.alpha > 0.0:
scores_for_aux = scores
aux_topk = self.top_k
topk_idx_for_aux_loss = topk_idx.view(bsz, -1)
if self.seq_aux:
scores_for_seq_aux = scores_for_aux.view(bsz, seq_len, -1)
ce = torch.zeros(bsz, self.n_routed_experts, device=hidden_states.device)
ce.scatter_add_(1, topk_idx_for_aux_loss,
torch.ones(bsz, seq_len * aux_topk, device=hidden_states.device)).div_(
seq_len * aux_topk / self.n_routed_experts)
aux_loss = (ce * scores_for_seq_aux.mean(dim=1)).sum(dim=1).mean() * self.alpha
else:
mask_ce = F.one_hot(topk_idx_for_aux_loss.view(-1), num_classes=self.n_routed_experts)
ce = mask_ce.float().mean(0)
Pi = scores_for_aux.mean(0)
fi = ce * self.n_routed_experts
aux_loss = (Pi * fi).sum() * self.alpha
else:
aux_loss = scores.new_zeros(1).squeeze()
return topk_idx, topk_weight, aux_loss
class MOEFeedForward(nn.Module):
def __init__(self, config: MiniMindConfig):
super().__init__()
self.config = config
self.experts = nn.ModuleList([
FeedForward(config)
for _ in range(config.n_routed_experts)
])
self.gate = MoEGate(config)
if config.n_shared_experts > 0:
self.shared_experts = nn.ModuleList([
FeedForward(config)
for _ in range(config.n_shared_experts)
])
def forward(self, x):
identity = x
orig_shape = x.shape
bsz, seq_len, _ = x.shape
# 使用门控机制选择专家
topk_idx, topk_weight, aux_loss = self.gate(x)
x = x.view(-1, x.shape[-1])
flat_topk_idx = topk_idx.view(-1)
if self.training:
x = x.repeat_interleave(self.config.num_experts_per_tok, dim=0)
y = torch.empty_like(x, dtype=x.dtype)
for i, expert in enumerate(self.experts):
expert_out = expert(x[flat_topk_idx == i])
if expert_out.shape[0] > 0: y[flat_topk_idx == i] = expert_out.to(y.dtype)
else: y[flat_topk_idx == i] = expert_out.to(y.dtype) + 0 * sum(p.sum() for p in expert.parameters())
y = (y.view(*topk_weight.shape, -1) * topk_weight.unsqueeze(-1)).sum(dim=1)
y = y.view(*orig_shape)
else:
y = self.moe_infer(x, flat_topk_idx, topk_weight.view(-1, 1)).view(*orig_shape)
if self.config.n_shared_experts > 0:
for expert in self.shared_experts:
y = y + expert(identity)
self.aux_loss = aux_loss
return y
@torch.no_grad()
def moe_infer(self, x, flat_expert_indices, flat_expert_weights):
expert_cache = torch.zeros_like(x)
idxs = flat_expert_indices.argsort()
tokens_per_expert = flat_expert_indices.bincount().cpu().numpy().cumsum(0)
token_idxs = idxs // self.config.num_experts_per_tok
# 当tokens_per_expert = [6, 15, 20, 26],tokens_per_expert.shape[0]即为专家数量(此时为4)
# 且token_idxs = [3, 7, 19, 21, 24, 25, 4, 5, 6, 10, 11, 12...] 时
# 意味token_idxs[:6] -> [3, 7, 19, 21, 24, 25]这6个位置属于专家0处理的token(每个token有可能被多个专家处理,这取决于num_experts_per_tok)
# 接下来9个位置token_idxs[6:15] -> [4, 5, 6, 10, 11, 12...]属于专家1处理的token...依此类推
for i, end_idx in enumerate(tokens_per_expert):
start_idx = 0 if i == 0 else tokens_per_expert[i - 1]
if start_idx == end_idx:
continue
expert = self.experts[i]
exp_token_idx = token_idxs[start_idx:end_idx]
expert_tokens = x[exp_token_idx]
expert_out = expert(expert_tokens).to(expert_cache.dtype)
expert_out.mul_(flat_expert_weights[idxs[start_idx:end_idx]])
expert_cache.scatter_add_(0, exp_token_idx.view(-1, 1).repeat(1, x.shape[-1]), expert_out)
return expert_cache
class MiniMindBlock(nn.Module):
def __init__(self, layer_id: int, config: MiniMindConfig):
super().__init__()
self.num_attention_heads = config.num_attention_heads
self.hidden_size = config.hidden_size
self.head_dim = config.hidden_size // config.num_attention_heads
self.self_attn = Attention(config)
self.layer_id = layer_id
self.input_layernorm = RMSNorm(config.hidden_size, eps=config.rms_norm_eps)
self.post_attention_layernorm = RMSNorm(config.hidden_size, eps=config.rms_norm_eps)
self.mlp = FeedForward(config) if not config.use_moe else MOEFeedForward(config)
def forward(self, hidden_states, position_embeddings, past_key_value=None, use_cache=False, attention_mask=None):
residual = hidden_states
hidden_states, present_key_value = self.self_attn(
self.input_layernorm(hidden_states), position_embeddings,
past_key_value, use_cache, attention_mask
)
hidden_states += residual
hidden_states = hidden_states + self.mlp(self.post_attention_layernorm(hidden_states))
return hidden_states, present_key_value
class MiniMindModel(nn.Module):
def __init__(self, config: MiniMindConfig):
super().__init__()
self.config = config
self.vocab_size, self.num_hidden_layers = config.vocab_size, config.num_hidden_layers
self.embed_tokens = nn.Embedding(config.vocab_size, config.hidden_size)
self.dropout = nn.Dropout(config.dropout)
self.layers = nn.ModuleList([MiniMindBlock(l, config) for l in range(self.num_hidden_layers)])
self.norm = RMSNorm(config.hidden_size, eps=config.rms_norm_eps)
freqs_cos, freqs_sin = precompute_freqs_cis(dim=config.hidden_size // config.num_attention_heads,
end=config.max_position_embeddings, rope_base=config.rope_theta,
rope_scaling=config.rope_scaling)
self.register_buffer("freqs_cos", freqs_cos, persistent=False)
self.register_buffer("freqs_sin", freqs_sin, persistent=False)
def forward(self,
input_ids: Optional[torch.Tensor] = None,
attention_mask: Optional[torch.Tensor] = None,
past_key_values: Optional[List[Tuple[torch.Tensor, torch.Tensor]]] = None,
use_cache: bool = False,
**kwargs):
batch_size, seq_length = input_ids.shape
if hasattr(past_key_values, 'layers'): past_key_values = None
past_key_values = past_key_values or [None] * len(self.layers)
start_pos = past_key_values[0][0].shape[1] if past_key_values[0] is not None else 0
hidden_states = self.dropout(self.embed_tokens(input_ids))
position_embeddings = (
self.freqs_cos[start_pos:start_pos + seq_length],
self.freqs_sin[start_pos:start_pos + seq_length]
)
presents = []
for layer_idx, (layer, past_key_value) in enumerate(zip(self.layers, past_key_values)):
hidden_states, present = layer(
hidden_states,
position_embeddings,
past_key_value=past_key_value,
use_cache=use_cache,
attention_mask=attention_mask
)
presents.append(present)
hidden_states = self.norm(hidden_states)
aux_loss = sum([l.mlp.aux_loss for l in self.layers if isinstance(l.mlp, MOEFeedForward)], hidden_states.new_zeros(1).squeeze())
return hidden_states, presents, aux_loss
class MiniMindForCausalLM(PreTrainedModel, GenerationMixin):
config_class = MiniMindConfig
def __init__(self, config: MiniMindConfig = None):
self.config = config or MiniMindConfig()
super().__init__(self.config)
self.model = MiniMindModel(self.config)
self.lm_head = nn.Linear(self.config.hidden_size, self.config.vocab_size, bias=False)
self.model.embed_tokens.weight = self.lm_head.weight
def forward(self,
input_ids: Optional[torch.Tensor] = None,
attention_mask: Optional[torch.Tensor] = None,
labels: Optional[torch.Tensor] = None,
past_key_values: Optional[List[Tuple[torch.Tensor, torch.Tensor]]] = None,
use_cache: bool = False,
logits_to_keep: Union[int, torch.Tensor] = 0,
**args):
hidden_states, past_key_values, aux_loss = self.model(
input_ids=input_ids,
attention_mask=attention_mask,
past_key_values=past_key_values,
use_cache=use_cache,
**args
)
slice_indices = slice(-logits_to_keep, None) if isinstance(logits_to_keep, int) else logits_to_keep
logits = self.lm_head(hidden_states[:, slice_indices, :])
loss = None
if labels is not None:
shift_logits = logits[..., :-1, :].contiguous()
shift_labels = labels[..., 1:].contiguous()
loss = F.cross_entropy(shift_logits.view(-1, shift_logits.size(-1)), shift_labels.view(-1), ignore_index=-100)
output = CausalLMOutputWithPast(loss=loss, logits=logits, past_key_values=past_key_values, hidden_states=hidden_states)
output.aux_loss = aux_loss
return output
================================================
FILE: model/tokenizer.json
================================================
{
"version": "1.0",
"truncation": null,
"padding": null,
"added_tokens": [
{
"id": 0,
"content": "<|endoftext|>",
"single_word": false,
"lstrip": false,
"rstrip": false,
"normalized": false,
"special": true
},
{
"id": 1,
"content": "<|im_start|>",
"single_word": false,
"lstrip": false,
"rstrip": false,
"normalized": false,
"special": true
},
{
"id": 2,
"content": "<|im_end|>",
"single_word": false,
"lstrip": false,
"rstrip": false,
"normalized": false,
"special": true
}
],
"normalizer": null,
"pre_tokenizer": {
"type": "ByteLevel",
"add_prefix_space": false,
"trim_offsets": true,
"use_regex": true
},
"post_processor": null,
"decoder": {
"type": "ByteLevel",
"add_prefix_space": true,
"trim_offsets": true,
"use_regex": true
},
"model": {
"type": "BPE",
"dropout": null,
"unk_token": null,
"continuing_subword_prefix": null,
"end_of_word_suffix": null,
"fuse_unk": false,
"byte_fallback": false,
"ignore_merges": false,
"vocab": {
"<|endoftext|>": 0,
"<|im_start|>": 1,
"<|im_end|>": 2,
"!": 3,
"\"": 4,
"#": 5,
"$": 6,
"%": 7,
"&": 8,
"'": 9,
"(": 10,
")": 11,
"*": 12,
"+": 13,
",": 14,
"-": 15,
".": 16,
"/": 17,
"0": 18,
"1": 19,
"2": 20,
"3": 21,
"4": 22,
"5": 23,
"6": 24,
"7": 25,
"8": 26,
"9": 27,
":": 28,
";": 29,
"<": 30,
"=": 31,
">": 32,
"?": 33,
"@": 34,
"A": 35,
"B": 36,
"C": 37,
"D": 38,
"E": 39,
"F": 40,
"G": 41,
"H": 42,
"I": 43,
"J": 44,
"K": 45,
"L": 46,
"M": 47,
"N": 48,
"O": 49,
"P": 50,
"Q": 51,
"R": 52,
"S": 53,
"T": 54,
"U": 55,
"V": 56,
"W": 57,
"X": 58,
"Y": 59,
"Z": 60,
"[": 61,
"\\": 62,
"]": 63,
"^": 64,
"_": 65,
"`": 66,
"a": 67,
"b": 68,
"c": 69,
"d": 70,
"e": 71,
"f": 72,
"g": 73,
"h": 74,
"i": 75,
"j": 76,
"k": 77,
"l": 78,
"m": 79,
"n": 80,
"o": 81,
"p": 82,
"q": 83,
"r": 84,
"s": 85,
"t": 86,
"u": 87,
"v": 88,
"w": 89,
"x": 90,
"y": 91,
"z": 92,
"{": 93,
"|": 94,
"}": 95,
"~": 96,
"¡": 97,
"¢": 98,
"£": 99,
"¤": 100,
"¥": 101,
"¦": 102,
"§": 103,
"¨": 104,
"©": 105,
"ª": 106,
"«": 107,
"¬": 108,
"®": 109,
"¯": 110,
"°": 111,
"±": 112,
"²": 113,
"³": 114,
"´": 115,
"µ": 116,
"¶": 117,
"·": 118,
"¸": 119,
"¹": 120,
"º": 121,
"»": 122,
"¼": 123,
"½": 124,
"¾": 125,
"¿": 126,
"À": 127,
"Á": 128,
"Â": 129,
"Ã": 130,
"Ä": 131,
"Å": 132,
"Æ": 133,
"Ç": 134,
"È": 135,
"É": 136,
"Ê": 137,
"Ë": 138,
"Ì": 139,
"Í": 140,
"Î": 141,
"Ï": 142,
"Ð": 143,
"Ñ": 144,
"Ò": 145,
"Ó": 146,
"Ô": 147,
"Õ": 148,
"Ö": 149,
"×": 150,
"Ø": 151,
"Ù": 152,
"Ú": 153,
"Û": 154,
"Ü": 155,
"Ý": 156,
"Þ": 157,
"ß": 158,
"à": 159,
"á": 160,
"â": 161,
"ã": 162,
"ä": 163,
"å": 164,
"æ": 165,
"ç": 166,
"è": 167,
"é": 168,
"ê": 169,
"ë": 170,
"ì": 171,
"í": 172,
"î": 173,
"ï": 174,
"ð": 175,
"ñ": 176,
"ò": 177,
"ó": 178,
"ô": 179,
"õ": 180,
"ö": 181,
"÷": 182,
"ø": 183,
"ù": 184,
"ú": 185,
"û": 186,
"ü": 187,
"ý": 188,
"þ": 189,
"ÿ": 190,
"Ā": 191,
"ā": 192,
"Ă": 193,
"ă": 194,
"Ą": 195,
"ą": 196,
"Ć": 197,
"ć": 198,
"Ĉ": 199,
"ĉ": 200,
"Ċ": 201,
"ċ": 202,
"Č": 203,
"č": 204,
"Ď": 205,
"ď": 206,
"Đ": 207,
"đ": 208,
"Ē": 209,
"ē": 210,
"Ĕ": 211,
"ĕ": 212,
"Ė": 213,
"ė": 214,
"Ę": 215,
"ę": 216,
"Ě": 217,
"ě": 218,
"Ĝ": 219,
"ĝ": 220,
"Ğ": 221,
"ğ": 222,
"Ġ": 223,
"ġ": 224,
"Ģ": 225,
"ģ": 226,
"Ĥ": 227,
"ĥ": 228,
"Ħ": 229,
"ħ": 230,
"Ĩ": 231,
"ĩ": 232,
"Ī": 233,
"ī": 234,
"Ĭ": 235,
"ĭ": 236,
"Į": 237,
"į": 238,
"İ": 239,
"ı": 240,
"IJ": 241,
"ij": 242,
"Ĵ": 243,
"ĵ": 244,
"Ķ": 245,
"ķ": 246,
"ĸ": 247,
"Ĺ": 248,
"ĺ": 249,
"Ļ": 250,
"ļ": 251,
"Ľ": 252,
"ľ": 253,
"Ŀ": 254,
"ŀ": 255,
"Ł": 256,
"ł": 257,
"Ń": 258,
"Ġt": 259,
"Ġa": 260,
"in": 261,
"he": 262,
"re": 263,
"ï¼": 264,
"ä¸": 265,
"on": 266,
"at": 267,
"çļ": 268,
"çļĦ": 269,
"ï¼Į": 270,
"Ġs": 271,
"Ġc": 272,
"nd": 273,
"ãĢ": 274,
"er": 275,
"Ġthe": 276,
"es": 277,
"en": 278,
"or": 279,
"an": 280,
"Ġand": 281,
"ing": 282,
"Ġp": 283,
"it": 284,
"al": 285,
"ãĢĤ": 286,
"Ġo": 287,
"Ġw": 288,
"ä»": 289,
"Ġto": 290,
"is": 291,
"ou": 292,
"Ġm": 293,
"äº": 294,
"Ġin": 295,
"Ġf": 296,
"Ġb": 297,
"ed": 298,
"ion": 299,
"åı": 300,
"ic": 301,
"Ġd": 302,
"Ġof": 303,
"le": 304,
"ar": 305,
"ro": 306,
"ĠĠ": 307,
"åħ": 308,
"ent": 309,
"æľ": 310,
"Ġe": 311,
"åĴ": 312,
"è¿": 313,
"ä½": 314,
"åĴĮ": 315,
"æĪ": 316,
"å®": 317,
"åĪ": 318,
"ve": 319,
"us": 320,
"Ġre": 321,
"Ġh": 322,
"Ġth": 323,
"as": 324,
"ct": 325,
"çĶ": 326,
"om": 327,
"åľ": 328,
"å¤": 329,
"æĺ": 330,
"åĬ": 331,
"åIJ": 332,
"ä¸Ģ": 333,
"im": 334,
"è¯": 335,
"æĸ": 336,
"ation": 337,
"lo": 338,
"ç»": 339,
"Ġbe": 340,
"ãĢģ": 341,
"id": 342,
"Ġcan": 343,
"il": 344,
"æĺ¯": 345,
"ä¹": 346,
"è®": 347,
"ĠA": 348,
"Ġthat": 349,
"ĠT": 350,
"以": 351,
"ch": 352,
"Ġy": 353,
"ce": 354,
"ï¼ļ": 355,
"ot": 356,
"ers": 357,
"Ġn": 358,
"éĢ": 359,
"ra": 360,
"å°": 361,
"Ġg": 362,
"Ġyou": 363,
"åŃ": 364,
"Ġpro": 365,
"et": 366,
"åº": 367,
"åľ¨": 368,
"ly": 369,
"Ġis": 370,
"个": 371,
"Ġl": 372,
"ur": 373,
"Ġfor": 374,
"åı¯": 375,
"éĩ": 376,
"st": 377,
"çļĦæ": 378,
"ut": 379,
"Ġhe": 380,
"if": 381,
"ĥ½": 382,
"ä¼": 383,
"ĠI": 384,
"è¡": 385,
"ir": 386,
"ith": 387,
"å¹": 388,
"Ġare": 389,
"ig": 390,
"Ġst": 391,
"el": 392,
"ol": 393,
"å¸": 394,
"ul": 395,
"æĿ": 396,
"æĪij": 397,
"Ġon": 398,
"è¦": 399,
"æľī": 400,
"æĹ": 401,
"å¯": 402,
"è§": 403,
"è¦ģ": 404,
"Ġus": 405,
"ay": 406,
"æķ": 407,
"çī": 408,
"ow": 409,
"ment": 410,
"ç͍": 411,
"ess": 412,
"ä¸Ń": 413,
"们": 414,
"人": 415,
"åĩ": 416,
"Ġex": 417,
"ĠĠĠĠ": 418,
"åĽ": 419,
"åĮ": 420,
"å¼": 421,
"Ġcon": 422,
"se": 423,
"èĥ½": 424,
"çİ": 425,
"Ġan": 426,
"Ġwith": 427,
"为": 428,
"ate": 429,
"iv": 430,
"am": 431,
"Ġas": 432,
"ure": 433,
"è¿Ļ": 434,
"åĨ": 435,
"çŃ": 436,
"Ġor": 437,
"å·": 438,
"Ġal": 439,
"ies": 440,
"ç§": 441,
"Ġim": 442,
"æĢ": 443,
"ver": 444,
"ab": 445,
"äºĨ": 446,
"Ġsu": 447,
"Ġde": 448,
"ge": 449,
"th": 450,
"åı¯ä»¥": 451,
"èĢ": 452,
"ä¸į": 453,
"å¾": 454,
"ĠAI": 455,
"Ġen": 456,
"éĹ": 457,
"æī": 458,
"ak": 459,
"ive": 460,
"Ġmo": 461,
"å¥": 462,
"éĿ": 463,
"çĽ": 464,
"ity": 465,
"ä¿": 466,
"un": 467,
"è´": 468,
"åį": 469,
"Ġit": 470,
"Ġimp": 471,
"ect": 472,
"æł": 473,
"å½": 474,
"èĩ": 475,
"é¢": 476,
"åĵ": 477,
"æ³": 478,
"ort": 479,
"ad": 480,
"æŀ": 481,
"em": 482,
"Ġcom": 483,
"å¦": 484,
"her": 485,
"ere": 486,
"ĠS": 487,
"ial": 488,
"ĠC": 489,
"ĠThe": 490,
"çIJ": 491,
"çĶŁ": 492,
"æĦ": 493,
"pp": 494,
"æŃ": 495,
"æĸ¹": 496,
"qu": 497,
"Ġwh": 498,
"å¦Ĥ": 499,
"éľ": 500,
"ant": 501,
"Ġle": 502,
"Ġv": 503,
"æĭ": 504,
"æĬ": 505,
"ust": 506,
"æĹ¶": 507,
"çŃī": 508,
"åij": 509,
"对": 510,
"ter": 511,
"ld": 512,
"è¡Į": 513,
"Ġch": 514,
"ud": 515,
"éľĢ": 516,
"æ°": 517,
"æĪIJ": 518,
"Ġ|": 519,
"ac": 520,
"ain": 521,
"iz": 522,
"æı": 523,
"ions": 524,
"Ġha": 525,
"æĽ": 526,
"--": 527,
"æĿ¥": 528,
"ome": 529,
"å¿": 530,
"'s": 531,
"Ġne": 532,
"est": 533,
"ä¾": 534,
"um": 535,
"åΰ": 536,
"åľ°": 537,
"ist": 538,
"âĢ": 539,
"çī©": 540,
"ä¸Ģ个": 541,
"lp": 542,
"æİ": 543,
"èĩª": 544,
"Ġhelp": 545,
"Ġtheir": 546,
"æĶ": 547,
"ä½ľ": 548,
"ä¼ļ": 549,
"æĮ": 550,
"æĪij们": 551,
"nt": 552,
"äºİ": 553,
"åĪĨ": 554,
"res": 555,
"pe": 556,
"åĩº": 557,
"ide": 558,
"æĥ": 559,
"ĠH": 560,
"è¾": 561,
"ĠM": 562,
"ff": 563,
"æ¯": 564,
"od": 565,
"ical": 566,
"Ġwor": 567,
"ä¸Ĭ": 568,
"are": 569,
"æĽ´": 570,
"Ġyour": 571,
"ä¸ĭ": 572,
"èµ": 573,
"ations": 574,
"æķ°": 575,
"Ġte": 576,
"åİ": 577,
"çIJĨ": 578,
"ĠTh": 579,
"è¿ĩ": 580,
"å¹¶": 581,
"du": 582,
"éĿ¢": 583,
"Ġad": 584,
"ill": 585,
"æµ": 586,
"好": 587,
"oc": 588,
"act": 589,
"éľĢè¦ģ": 590,
"ä»ĸ": 591,
"å±": 592,
"Ġr": 593,
"Ġmore": 594,
"åѦ": 595,
"ç®": 596,
"igh": 597,
"äºĽ": 598,
"ĠB": 599,
"åĬ¨": 600,
"åĵģ": 601,
"èī": 602,
"ple": 603,
"Ġinc": 604,
"åIJĮ": 605,
"Ġexp": 606,
"ould": 607,
"ä½ł": 608,
"æį": 609,
"æıIJ": 610,
"大": 611,
"çݰ": 612,
"pt": 613,
"ĠP": 614,
"all": 615,
"åĬł": 616,
"ç§į": 617,
"Ġse": 618,
"åĬĽ": 619,
"out": 620,
"Ġhave": 621,
"çº": 622,
"ä½ĵ": 623,
"Ġprov": 624,
"åĮĸ": 625,
"å¤ļ": 626,
"å®ļ": 627,
"Ġused": 628,
"éĢļ": 629,
"cc": 630,
"è¿Ľ": 631,
"æ´": 632,
"Ġsh": 633,
"Ġab": 634,
"os": 635,
"Ġres": 636,
"ĠThis": 637,
"ç¨": 638,
"æĢ§": 639,
"age": 640,
"ri": 641,
"æ¸": 642,
"able": 643,
"åŃIJ": 644,
"Ġby": 645,
"åıij": 646,
"éĩı": 647,
"åºĶ": 648,
"Ġlo": 649,
"使": 650,
"åħ¶": 651,
"é«": 652,
"éĻ": 653,
"é«ĺ": 654,
"度": 655,
"è§£": 656,
"é£": 657,
"å°Ĩ": 658,
"æ³ķ": 659,
"and": 660,
"ä¿Ŀ": 661,
"ans": 662,
"for": 663,
"rom": 664,
"reat": 665,
"Ġpl": 666,
"çļĦç": 667,
"常": 668,
"è½": 669,
"Ġwe": 670,
"表": 671,
"ake": 672,
"æĪĸ": 673,
"é¢ĺ": 674,
"åŁ": 675,
"Ġme": 676,
"æĸĩ": 677,
"ther": 678,
"ke": 679,
"å®¶": 680,
"åIJĪ": 681,
"æľĢ": 682,
"ine": 683,
"Ġsome": 684,
"ç±": 685,
"éĩį": 686,
"æŀľ": 687,
"ĠW": 688,
"ĠE": 689,
"éĺ": 690,
"our": 691,
"rou": 692,
"çĤ": 693,
"æ±": 694,
"åħ³": 695,
"Ġint": 696,
"ance": 697,
"ä¹Ł": 698,
"éģ": 699,
"ĠĠĠ": 700,
"å®ĥ": 701,
"ag": 702,
"æ¬": 703,
"00": 704,
"è°": 705,
"ult": 706,
"yst": 707,
"éĹ´": 708,
"ç³": 709,
"Ġtr": 710,
"pl": 711,
"art": 712,
"æĦŁ": 713,
"æĤ": 714,
"ata": 715,
"ĠF": 716,
"form": 717,
"计": 718,
"Ġfrom": 719,
"ĠD": 720,
"éĹ®": 721,
"ight": 722,
"ces": 723,
"æį®": 724,
"lop": 725,
"ä¹ĭ": 726,
"Ġfe": 727,
"åģ": 728,
"velop": 729,
"Ġ1": 730,
"åĽł": 731,
"ks": 732,
"æ²": 733,
"Ġu": 734,
"å°ı": 735,
"ystem": 736,
"Ġdis": 737,
"ĠR": 738,
"gy": 739,
"å·¥": 740,
"ç¨ĭ": 741,
"å¢": 742,
"ence": 743,
"èĤ": 744,
"ç¡": 745,
"Ġtra": 746,
"å»": 747,
"åħ¥": 748,
"ign": 749,
"alth": 750,
"Ġsuch": 751,
"ach": 752,
"æĻ": 753,
"arn": 754,
"Ġdata": 755,
"è¶": 756,
"å®ŀ": 757,
"so": 758,
"Ġdevelop": 759,
"ç¤": 760,
"Ġacc": 761,
"ast": 762,
"èĢĮ": 763,
"Ġ\"": 764,
"Ġother": 765,
"建": 766,
"Ġeff": 767,
"ç«": 768,
"Ġman": 769,
"åħ¬": 770,
"åĢ": 771,
"çĦ": 772,
"ms": 773,
"å¼ı": 774,
"èī²": 775,
"å¾Ĺ": 776,
"ific": 777,
"Ġj": 778,
"Ġro": 779,
"Ġhas": 780,
"chn": 781,
"olo": 782,
"åζ": 783,
"èĬ": 784,
"使ç͍": 785,
"ous": 786,
"ual": 787,
"Ġat": 788,
"Ġem": 789,
"ell": 790,
"Ġsystem": 791,
"Ġhealth": 792,
"ities": 793,
"Ġexam": 794,
"ib": 795,
"éĶ": 796,
"Ġabout": 797,
"产": 798,
"åIJİ": 799,
"æĦı": 800,
"ç±»": 801,
"Ġpre": 802,
"æĤ¨": 803,
"Ġalso": 804,
"ents": 805,
"Ġind": 806,
"ind": 807,
"éĢĤ": 808,
"Ġtechn": 809,
"ress": 810,
"æĥħ": 811,
"éĹ®é¢ĺ": 812,
"Ġuse": 813,
"ï¼Ł": 814,
"Ġincl": 815,
"Ġspe": 816,
"ich": 817,
"ps": 818,
"æľº": 819,
"Ġthey": 820,
"ie": 821,
"Ġhow": 822,
"Ġwork": 823,
"ä¸ļ": 824,
"ç´": 825,
"Ġimpro": 826,
"Ġlearn": 827,
"æĸ°": 828,
"çĤ¹": 829,
"Ġcont": 830,
"ard": 831,
"çĦ¶": 832,
"æľ¬": 833,
"ç³»": 834,
"ç¡®": 835,
"设": 836,
"åħ·": 837,
"éĢī": 838,
"èĢħ": 839,
"éħ": 840,
"gh": 841,
"__": 842,
"Ġnot": 843,
"çľ": 844,
"缸": 845,
"Ġprovide": 846,
"åī": 847,
"ional": 848,
"Ġens": 849,
"ä¸İ": 850,
"è´¨": 851,
"ential": 852,
"ç»ı": 853,
"å¿ĥ": 854,
"ang": 855,
"æŃ¤": 856,
"end": 857,
"Ġpo": 858,
"è¿Ľè¡Į": 859,
"ice": 860,
"Ġ-": 861,
"Ġway": 862,
"å·±": 863,
"Ġ2": 864,
"ime": 865,
"ç½": 866,
"èĩªå·±": 867,
"Ġun": 868,
"bot": 869,
"Ġinclud": 870,
"ated": 871,
"æ°´": 872,
"éķ": 873,
"æĮģ": 874,
"代": 875,
"é¡": 876,
"æīĢ": 877,
"çĿ": 878,
"pport": 879,
"ood": 880,
"ike": 881,
"ru": 882,
"Ġcomm": 883,
"ĠL": 884,
"ä¿¡": 885,
"ĠG": 886,
"çŁ": 887,
"ç͵": 888,
"Ġwas": 889,
"low": 890,
"erv": 891,
"åĮħ": 892,
"ĠĠĠĠĠĠĠĠ": 893,
"Ġwhe": 894,
"dit": 895,
"Ġwhich": 896,
"Ġcomp": 897,
"éª": 898,
"ore": 899,
"ç¾": 900,
"Ġ=": 901,
"çī¹": 902,
"iff": 903,
"ert": 904,
"æģ": 905,
"rit": 906,
"Ġrec": 907,
"åĨħ": 908,
"æĺİ": 909,
"ors": 910,
"Ġpat": 911,
"----": 912,
"æŁ": 913,
"Ġapp": 914,
"ns": 915,
"åĬ¡": 916,
"aly": 917,
"ace": 918,
"æ´»": 919,
"ä¾Ľ": 920,
"av": 921,
"主": 922,
"Ġpers": 923,
"çĥ": 924,
"该": 925,
"Ġmy": 926,
"ç©": 927,
"eri": 928,
"让": 929,
"æĬĢ": 930,
"éķ¿": 931,
"ack": 932,
"ĠN": 933,
"Ġdiff": 934,
"Ġthis": 935,
"åĿ": 936,
"Ġensure": 937,
"å½ĵ": 938,
"Ġout": 939,
"Ġcl": 940,
"Ġk": 941,
"é¦": 942,
"ount": 943,
"çݯ": 944,
"åĬ©": 945,
"Ġtechnolo": 946,
"Ġthese": 947,
"ful": 948,
"éļ": 949,
"æ·": 950,
"ä¸ĢäºĽ": 951,
"Ġsoc": 952,
"å¼Ģ": 953,
"天": 954,
"Ġev": 955,
"Ġredu": 956,
"Ġthem": 957,
"Ġ(": 958,
"éĥ½": 959,
"æĪ·": 960,
"è·": 961,
"åľº": 962,
"æ°Ķ": 963,
"ĠY": 964,
"è¯Ń": 965,
"éĢļè¿ĩ": 966,
"å±ķ": 967,
"Ġco": 968,
"å½±": 969,
"ç¬": 970,
"Ġanaly": 971,
"æ¯Ķ": 972,
"åħ¨": 973,
"Ġimprove": 974,
"ç»ĵ": 975,
"å¹´": 976,
"çķ": 977,
"çĿĢ": 978,
"Ġhum": 979,
"Ġqu": 980,
"ç®Ĺ": 981,
"ĠO": 982,
"é£Ł": 983,
"ility": 984,
"Ġsystems": 985,
"åıĺ": 986,
"ail": 987,
"ç¼": 988,
"çł": 989,
"è¿Ļ个": 990,
"æıIJä¾Ľ": 991,
"ase": 992,
"åŀ": 993,
"ments": 994,
"Ġpot": 995,
"Ġany": 996,
"ä½Ĩ": 997,
"Ġcons": 998,
"ĠIt": 999,
"æł¼": 1000,
"Ġar": 1001,
"æľ¯": 1002,
"éĿŀ": 1003,
"Ġdo": 1004,
"Ġmay": 1005,
"æĭ©": 1006,
"ue": 1007,
"éĢīæĭ©": 1008,
"ry": 1009,
"éĥ": 1010,
"Ġlike": 1011,
"ong": 1012,
"èģ": 1013,
"``": 1014,
"ile": 1015,
"æ±Ĥ": 1016,
"Ġnew": 1017,
"ient": 1018,
"Ġimpact": 1019,
"è¿ĺ": 1020,
"注": 1021,
"ä¹Ī": 1022,
"缮": 1023,
"âĢľ": 1024,
"âĢĿ": 1025,
"ef": 1026,
"ä¾ĭ": 1027,
"Ġpotential": 1028,
"ok": 1029,
"åı¯èĥ½": 1030,
"Ġtrans": 1031,
"Ġact": 1032,
"ï¼ī": 1033,
"Ġspec": 1034,
"æ¶": 1035,
"Ġwill": 1036,
"交": 1037,
"ize": 1038,
"ç¾İ": 1039,
"å¸Ĥ": 1040,
"Ġstud": 1041,
"pon": 1042,
"èº": 1043,
"ä¸įåIJĮ": 1044,
"one": 1045,
"å¾Ī": 1046,
"åıĬ": 1047,
"å¦Ĥæŀľ": 1048,
"çIJĥ": 1049,
"ange": 1050,
"Ġneed": 1051,
"å¤ĸ": 1052,
"ety": 1053,
"aking": 1054,
"请": 1055,
"ater": 1056,
"Ġperson": 1057,
"ident": 1058,
"Ġso": 1059,
"Ġmake": 1060,
"å¹³": 1061,
"å¤Ł": 1062,
"身": 1063,
"ï¼Ī": 1064,
"Ġinform": 1065,
"æ¡": 1066,
"äºĭ": 1067,
"åıĹ": 1068,
"ased": 1069,
"ild": 1070,
"Ġoff": 1071,
"Ġthere": 1072,
"cis": 1073,
"è¢": 1074,
"éĥ¨": 1075,
"æ¯ı": 1076,
"ract": 1077,
"ass": 1078,
"Ġlearning": 1079,
"åĸ": 1080,
"å½¢": 1081,
"ire": 1082,
"ä»İ": 1083,
"bots": 1084,
"èĻ": 1085,
"帮": 1086,
"Ġdes": 1087,
"ĠIn": 1088,
"cess": 1089,
"Ġpe": 1090,
"ify": 1091,
"Ġwho": 1092,
"ä¹ł": 1093,
"æľŁ": 1094,
"Ġexperi": 1095,
"éĤ": 1096,
"Ġsc": 1097,
"ep": 1098,
"ä½ķ": 1099,
"Ġtime": 1100,
"éĿŀ常": 1101,
"æĭ¬": 1102,
"åķ": 1103,
"以ä¸ĭ": 1104,
"éģĵ": 1105,
"Ġcommun": 1106,
"Ġcould": 1107,
"ap": 1108,
"èIJ": 1109,
"è°ĥ": 1110,
"lic": 1111,
"duct": 1112,
"Ġits": 1113,
"cy": 1114,
"说": 1115,
"Ġmed": 1116,
"Ġcol": 1117,
"ular": 1118,
"éĩįè¦ģ": 1119,
"Ġsp": 1120,
"åĪ©": 1121,
"èµ·": 1122,
"Ġprovid": 1123,
"ices": 1124,
"åĻ": 1125,
"æĸĻ": 1126,
"Ġimport": 1127,
"ural": 1128,
"åŃĹ": 1129,
"Ġund": 1130,
"int": 1131,
"Ġover": 1132,
"åı¸": 1133,
"æł¹": 1134,
"é¥": 1135,
"ples": 1136,
"ä»ĸ们": 1137,
"gra": 1138,
"uring": 1139,
"now": 1140,
"åįķ": 1141,
"è¿ĻäºĽ": 1142,
"åīį": 1143,
"å®ī": 1144,
"Ġpr": 1145,
"åĮħæĭ¬": 1146,
"ç»Ļ": 1147,
"The": 1148,
"ä½į": 1149,
"å§": 1150,
"ç´ł": 1151,
"åijĺ": 1152,
"Ġident": 1153,
"åŀĭ": 1154,
"Ġadd": 1155,
"强": 1156,
"æĺ¯ä¸Ģ": 1157,
"ip": 1158,
"gor": 1159,
"Ġsupport": 1160,
"ne": 1161,
"Ġdiffere": 1162,
"åħĥ": 1163,
"Ġass": 1164,
"åĨ³": 1165,
"éĽ": 1166,
"åIJį": 1167,
"Ġgo": 1168,
"Ġtechnology": 1169,
"æĢ»": 1170,
"è®®": 1171,
"Ġinter": 1172,
"Ġinv": 1173,
"Ġour": 1174,
"æķĪ": 1175,
"ustom": 1176,
"Ġrel": 1177,
"ife": 1178,
"åύ": 1179,
"ings": 1180,
"ä»·": 1181,
"Ġpart": 1182,
"被": 1183,
"æīĭ": 1184,
"ary": 1185,
"Ġrespon": 1186,
"ĊĠĠĠ": 1187,
"好çļĦ": 1188,
"ative": 1189,
"帮åĬ©": 1190,
"绣": 1191,
"æĶ¾": 1192,
"ĠHere": 1193,
"çģ": 1194,
"Ġbut": 1195,
"æģ¯": 1196,
"æŃ£": 1197,
"ark": 1198,
"åħ¬åı¸": 1199,
"ory": 1200,
"å¢ĥ": 1201,
"lect": 1202,
"éŁ": 1203,
"æĥ³": 1204,
"é£İ": 1205,
"ating": 1206,
"Ġam": 1207,
"its": 1208,
"æ»": 1209,
"gorith": 1210,
"åĵį": 1211,
"ures": 1212,
"Ġeffect": 1213,
"Ġshould": 1214,
"Ġper": 1215,
"è±": 1216,
"ç²": 1217,
"ict": 1218,
"Ġalgorith": 1219,
"uc": 1220,
"rough": 1221,
"ä»»": 1222,
"ä»¶": 1223,
"Ġbet": 1224,
"ia": 1225,
"Ġanalyz": 1226,
"æł¹æį®": 1227,
"ized": 1228,
"æµģ": 1229,
"è§Ĥ": 1230,
"è£": 1231,
"æłĩ": 1232,
"iron": 1233,
"Ġcustom": 1234,
"Ġreg": 1235,
"Ġpersonal": 1236,
"èĥ½å¤Ł": 1237,
"ics": 1238,
"ivid": 1239,
"çĪ": 1240,
"èµĦ": 1241,
"æŃ¥": 1242,
"容": 1243,
"åĪĽ": 1244,
"èĪ": 1245,
"ä¹IJ": 1246,
"导": 1247,
"gan": 1248,
"èĬĤ": 1249,
"Ġall": 1250,
"ens": 1251,
"ame": 1252,
"ness": 1253,
"Ġup": 1254,
"ĠU": 1255,
"èĢĥ": 1256,
"elf": 1257,
"å̼": 1258,
"å°ij": 1259,
"æľį": 1260,
"ari": 1261,
"thical": 1262,
"viron": 1263,
"èĥ": 1264,
"ord": 1265,
"Ġsign": 1266,
"éĩĮ": 1267,
"ound": 1268,
"ople": 1269,
"åŁº": 1270,
"Ġinformation": 1271,
"Ġidentify": 1272,
"åĽŀ": 1273,
"Ġcre": 1274,
"éŁ³": 1275,
"ible": 1276,
"ub": 1277,
"è¿IJ": 1278,
"Ġlead": 1279,
"游": 1280,
"次": 1281,
"åĨĻ": 1282,
"éĤ£": 1283,
"get": 1284,
"èį": 1285,
"Ġexample": 1286,
"ä¼ĺ": 1287,
"å½±åĵį": 1288,
"ish": 1289,
"xt": 1290,
"æº": 1291,
"éªĮ": 1292,
"ob": 1293,
"客": 1294,
"å¤ĩ": 1295,
"åģ¥": 1296,
"车": 1297,
"社": 1298,
"ividual": 1299,
"ered": 1300,
"les": 1301,
"Ġenviron": 1302,
"Ġpeople": 1303,
"æĺŁ": 1304,
"çĸ": 1305,
"çĭ": 1306,
"Ġdet": 1307,
"æĹł": 1308,
"Ġif": 1309,
"ose": 1310,
"ite": 1311,
"å¢ŀ": 1312,
"éĴ": 1313,
"åIJĮæĹ¶": 1314,
"è¿°": 1315,
"æĸ¹å¼ı": 1316,
"åĽ½": 1317,
"é»": 1318,
"å¤Ħ": 1319,
"Ġexamples": 1320,
"æ®": 1321,
"Ġinto": 1322,
"æĮĩ": 1323,
"Ġhuman": 1324,
"åIJij": 1325,
"示": 1326,
"æķ°æį®": 1327,
"Ġ3": 1328,
"ĠJ": 1329,
"èı": 1330,
"çݯå¢ĥ": 1331,
"als": 1332,
"erst": 1333,
"Ġethical": 1334,
"ç»Ħ": 1335,
"ä¼ł": 1336,
"Ġdifferent": 1337,
"Ġknow": 1338,
"åºı": 1339,
"Ġindividual": 1340,
"æıIJé«ĺ": 1341,
"round": 1342,
"å°±": 1343,
"åıĸ": 1344,
"åŃĺ": 1345,
"两": 1346,
"çŁ¥": 1347,
"ources": 1348,
"ck": 1349,
"å£": 1350,
"ines": 1351,
"è¾¾": 1352,
"Ġmany": 1353,
"æķ´": 1354,
"æł·": 1355,
"ditional": 1356,
"omm": 1357,
"çͱ": 1358,
"éĢł": 1359,
"å®ĥ们": 1360,
"ues": 1361,
"Ġment": 1362,
"Ġimportant": 1363,
"Ġopt": 1364,
"Ġloc": 1365,
"ph": 1366,
"Ġprocess": 1367,
"Ġalgorithms": 1368,
"设计": 1369,
"Ġsocial": 1370,
"very": 1371,
"åĪĻ": 1372,
"ä¾ĭå¦Ĥ": 1373,
"认": 1374,
"Ġaut": 1375,
"Ġserv": 1376,
"gg": 1377,
"产åĵģ": 1378,
"è§Ħ": 1379,
"çľĭ": 1380,
"vel": 1381,
"æĸ¹æ³ķ": 1382,
"Ġben": 1383,
"åĽłæŃ¤": 1384,
"care": 1385,
"per": 1386,
"åĬŁ": 1387,
"建议": 1388,
"Ġpos": 1389,
"æ¤": 1390,
"we": 1391,
"åĮº": 1392,
"iqu": 1393,
"Ġreal": 1394,
"æĹ¥": 1395,
"Ġreduce": 1396,
"af": 1397,
"angu": 1398,
"Ġsk": 1399,
"Ġed": 1400,
"erstand": 1401,
"åĨµ": 1402,
"mot": 1403,
"åħĪ": 1404,
"ç¥": 1405,
"åºĶ该": 1406,
"Ġthrough": 1407,
"Ġconc": 1408,
"åıijå±ķ": 1409,
"è¯ķ": 1410,
"æ¡Ī": 1411,
"Ġenvironment": 1412,
"åı£": 1413,
"Ġadv": 1414,
"åĪ«": 1415,
"Ġbenef": 1416,
"æ¸ħ": 1417,
"åij³": 1418,
"åħī": 1419,
"Ġdevelopment": 1420,
"eng": 1421,
"å¦Ĥä½ķ": 1422,
"管": 1423,
"ivers": 1424,
"åIJĦ": 1425,
"Ġris": 1426,
"row": 1427,
"ergy": 1428,
"计ç®Ĺ": 1429,
"ä¿¡æģ¯": 1430,
"Ġproduct": 1431,
"è¾ĥ": 1432,
"论": 1433,
"èĩªå·±çļĦ": 1434,
"æĬ¤": 1435,
"åıį": 1436,
"åħ¶ä»ĸ": 1437,
"åĪĹ": 1438,
"ç»Ĩ": 1439,
"空": 1440,
"Ġgreat": 1441,
"ear": 1442,
"æºIJ": 1443,
"ject": 1444,
"çĶŁæ´»": 1445,
"ä¸ŃçļĦ": 1446,
"Ġunderstand": 1447,
"èĭ": 1448,
"hat": 1449,
"Ġprogra": 1450,
"çĬ": 1451,
"éĩij": 1452,
"Ġincluding": 1453,
"Ġaccess": 1454,
"ĠĠĠĠĠĠĠ": 1455,
"è¯Ĩ": 1456,
"ç¦": 1457,
"og": 1458,
"è£ħ": 1459,
"Ġart": 1460,
"Ġwrit": 1461,
"Ġincre": 1462,
"Ġph": 1463,
"æĸ¹éĿ¢": 1464,
"Ġpract": 1465,
"Ġusing": 1466,
"项": 1467,
"æİ¥": 1468,
"Ġways": 1469,
"Ġlangu": 1470,
"æĶ¯": 1471,
"Ġchall": 1472,
"åİ»": 1473,
"____": 1474,
"imate": 1475,
"æĸŃ": 1476,
"è¨": 1477,
"Ġwell": 1478,
"ll": 1479,
"Ġpol": 1480,
"æĢģ": 1481,
"Ġra": 1482,
"Can": 1483,
"åİŁ": 1484,
"ber": 1485,
"è¨Ģ": 1486,
"ç«ĭ": 1487,
"Ġgen": 1488,
"éħį": 1489,
"æ·±": 1490,
"te": 1491,
"ä¸ī": 1492,
"ç§ij": 1493,
"ĠFor": 1494,
"线": 1495,
"çħ": 1496,
"æ¼": 1497,
"åķĨ": 1498,
"æĿIJ": 1499,
"Ġsignific": 1500,
"Ġgu": 1501,
"Ġdecis": 1502,
"Ġtrain": 1503,
"Ġag": 1504,
"Ġcreat": 1505,
"å®Į": 1506,
"æĹ¶éĹ´": 1507,
"Ġone": 1508,
"èĦ": 1509,
"Ġnat": 1510,
"åŃ¦ä¹ł": 1511,
"çļĦæķ": 1512,
"ced": 1513,
"Ġwhen": 1514,
"Ġbi": 1515,
"èİ": 1516,
"æĽ´åĬł": 1517,
"ives": 1518,
"port": 1519,
"å·¥ä½ľ": 1520,
"ving": 1521,
"Ġbeen": 1522,
"æĻº": 1523,
"Ġlife": 1524,
"å¼ķ": 1525,
"arm": 1526,
"çİĩ": 1527,
"ç͍æĪ·": 1528,
"ä¹ī": 1529,
"份": 1530,
"è¯Ŀ": 1531,
"iness": 1532,
"com": 1533,
"康": 1534,
"åĩı": 1535,
"ä»Ģ": 1536,
"è¾ĵ": 1537,
"Ġvari": 1538,
"con": 1539,
"Ġmod": 1540,
"ä»Ģä¹Ī": 1541,
"Ġenergy": 1542,
"æĬĢæľ¯": 1543,
"ertain": 1544,
"mm": 1545,
"verall": 1546,
"åĪĴ": 1547,
"Ġrobots": 1548,
"Ġorgan": 1549,
"æİ¨": 1550,
"ants": 1551,
"åĩĨ": 1552,
"ds": 1553,
"æŀģ": 1554,
"çĻ": 1555,
"Ġrequ": 1556,
"Ġess": 1557,
"ç®Ģ": 1558,
"ustain": 1559,
"æ¨": 1560,
"Ġstr": 1561,
"cing": 1562,
"ability": 1563,
"ree": 1564,
"Ġeduc": 1565,
"åİĨ": 1566,
"Ġcreate": 1567,
"åģ¥åº·": 1568,
"Ġdesign": 1569,
"ips": 1570,
"åģļ": 1571,
"èĬ±": 1572,
"ink": 1573,
"èıľ": 1574,
"æī¾": 1575,
"段": 1576,
"æµĭ": 1577,
"ĠV": 1578,
"ĠBy": 1579,
"åĶ": 1580,
"é¦ĸ": 1581,
"è¯į": 1582,
"Ġwhere": 1583,
"Ġdisc": 1584,
"äºĨè§£": 1585,
"ric": 1586,
"ä¸Ķ": 1587,
"è¶³": 1588,
"æĺ¯ä¸Ģ个": 1589,
"arch": 1590,
"积": 1591,
"带": 1592,
"Ġwhile": 1593,
"Ġsignificant": 1594,
"çłģ": 1595,
"æĪ¿": 1596,
"Ġbeing": 1597,
"Ġlanguage": 1598,
"itive": 1599,
"20": 1600,
"Ġanalyze": 1601,
"æĻ¯": 1602,
"èĮ": 1603,
"rib": 1604,
"模": 1605,
"ĠSt": 1606,
"è´¹": 1607,
"'t": 1608,
"Ġhealthcare": 1609,
"Ġexperience": 1610,
"Ġ5": 1611,
"个人": 1612,
"ays": 1613,
"象": 1614,
"plo": 1615,
"Ġwould": 1616,
"èĻij": 1617,
"æĶ¶": 1618,
"é¢Ħ": 1619,
"é¢Ĩ": 1620,
"ä¿ĿæĮģ": 1621,
"ences": 1622,
"åıª": 1623,
"èĩ´": 1624,
"æĪı": 1625,
"Ġmental": 1626,
"Ġfew": 1627,
"ates": 1628,
"è¿ĩç¨ĭ": 1629,
"å®īåħ¨": 1630,
"Ġsustain": 1631,
"Ġwere": 1632,
"太": 1633,
"çĮ": 1634,
"Ġspecific": 1635,
"Ġworld": 1636,
"çŃĶ": 1637,
"```": 1638,
"Ġtake": 1639,
"åħ»": 1640,
"éĢŁ": 1641,
"ever": 1642,
"SS": 1643,
"éĶĢ": 1644,
"Ġbo": 1645,
"hes": 1646,
"Ġmus": 1647,
"æľįåĬ¡": 1648,
"è§Ĵ": 1649,
"ten": 1650,
"æŀIJ": 1651,
"pow": 1652,
"dict": 1653,
"vent": 1654,
"10": 1655,
"çļĦæĹ": 1656,
"ĸçķ": 1657,
"Ġprot": 1658,
"ç½®": 1659,
"Ġhigh": 1660,
"Ġbus": 1661,
"Ġindust": 1662,
"åIJ¦": 1663,
"cial": 1664,
"人们": 1665,
"ĠAs": 1666,
"åijĬ": 1667,
"ade": 1668,
"æĶ¹": 1669,
"çĹ": 1670,
"Ġhad": 1671,
"Ġher": 1672,
"Ġjust": 1673,
"ï¼Ľ": 1674,
"è´Ń": 1675,
"第": 1676,
"éĵ": 1677,
"Ġwater": 1678,
"Ġfood": 1679,
"éĺŁ": 1680,
"aus": 1681,
"Ġchalleng": 1682,
"åħį": 1683,
"æĸĩåĮĸ": 1684,
"Ġmost": 1685,
"é¸": 1686,
"ç½ij": 1687,
"缴": 1688,
"Ġsm": 1689,
"Ġactiv": 1690,
"ploy": 1691,
"Overall": 1692,
"å¿«": 1693,
"ruct": 1694,
"Ġindividuals": 1695,
"å§ĭ": 1696,
"gies": 1697,
"æŁ¥": 1698,
"çα": 1699,
"iety": 1700,
"In": 1701,
"åĪĨæŀIJ": 1702,
"è§Ĩ": 1703,
"温": 1704,
"ç»´": 1705,
"olut": 1706,
"åŁŁ": 1707,
"ommend": 1708,
"Ġcomple": 1709,
"æķĻ": 1710,
"Ġbu": 1711,
"Ġeducation": 1712,
"ather": 1713,
"Ġ4": 1714,
"ting": 1715,
"Ġfind": 1716,
"没": 1717,
"Ġhis": 1718,
"ä¹ĭéĹ´": 1719,
"Ġeffective": 1720,
"Ġatt": 1721,
"Ġrese": 1722,
"èĥ½åĬĽ": 1723,
"åŁİ": 1724,
"Ġallow": 1725,
"Ġav": 1726,
"Ġpromot": 1727,
"æĻºèĥ½": 1728,
"满": 1729,
"åħ±": 1730,
"iew": 1731,
"come": 1732,
"ç³»ç»Ł": 1733,
"Ġrespons": 1734,
"äºĴ": 1735,
"Ġcult": 1736,
"powered": 1737,
"Ġrecommend": 1738,
"èIJ¥": 1739,
"OSS": 1740,
"Ġchange": 1741,
"è¯ģ": 1742,
"ved": 1743,
"æİĴ": 1744,
"è§£åĨ³": 1745,
"ici": 1746,
"ĠHow": 1747,
"Ġfeel": 1748,
"æľĪ": 1749,
"Ġwhat": 1750,
"以åıĬ": 1751,
"Ġsee": 1752,
"åŃ©": 1753,
"bs": 1754,
"Ġsur": 1755,
"æ£": 1756,
"ality": 1757,
"Ġvis": 1758,
"ç¡®ä¿Ŀ": 1759,
"pect": 1760,
"å®ŀçݰ": 1761,
"Ġcare": 1762,
"广": 1763,
"ills": 1764,
"åºŃ": 1765,
"ases": 1766,
"å¤į": 1767,
"åºĶç͍": 1768,
"çļĦæĥ": 1769,
"ards": 1770,
"Ġaddress": 1771,
"Ġcompan": 1772,
"Ġinvol": 1773,
"Ġcustomer": 1774,
"åĽłä¸º": 1775,
"Ġstudents": 1776,
"Ġins": 1777,
"注æĦı": 1778,
"æŀĦ": 1779,
"欢": 1780,
"æµ·": 1781,
"åıĤ": 1782,
"èĩªçĦ¶": 1783,
"é©": 1784,
"ĠThese": 1785,
"wn": 1786,
"æĺĵ": 1787,
"çĬ¶": 1788,
"ren": 1789,
"Ġtreat": 1790,
"Ġbenefits": 1791,
"ĊĠĠĠĠĠĠĠ": 1792,
"对äºİ": 1793,
"æĢĿ": 1794,
"ider": 1795,
"ĠYes": 1796,
"ĠK": 1797,
"åĸľ": 1798,
"Ġke": 1799,
"Ġeng": 1800,
"Ġpop": 1801,
"ost": 1802,
"pare": 1803,
"Ġmon": 1804,
"款": 1805,
"ĠMOSS": 1806,
"Ġemot": 1807,
"Ġac": 1808,
"ç¼ĸ": 1809,
"fore": 1810,
"åı¥": 1811,
"Ġval": 1812,
"ily": 1813,
"Ġiss": 1814,
"èĤī": 1815,
"èĩ³": 1816,
"游æĪı": 1817,
"ween": 1818,
"Ġinclude": 1819,
"Ġprotect": 1820,
"åħ³ç³»": 1821,
"éĻ©": 1822,
"Ġsever": 1823,
"Ġthan": 1824,
"éľĢæ±Ĥ": 1825,
"ç»ĥ": 1826,
"ĠThey": 1827,
"iss": 1828,
"ys": 1829,
"Ġjob": 1830,
"éĺ³": 1831,
"æIJ": 1832,
"Ġbetween": 1833,
"Ġmach": 1834,
"--------": 1835,
"èĢĥèĻij": 1836,
"è´¨éĩı": 1837,
"Ġbusiness": 1838,
"wor": 1839,
"ick": 1840,
"eg": 1841,
"åħħ": 1842,
"ç¯": 1843,
"æĿ¡": 1844,
"ner": 1845,
"apt": 1846,
"Ġappro": 1847,
"Ġplay": 1848,
"没æľī": 1849,
"¤IJ": 1850,
"æľª": 1851,
"æĪĺ": 1852,
"å®¶åºŃ": 1853,
"ãĢĭ": 1854,
"ency": 1855,
"ĠCh": 1856,
"ãĢĬ": 1857,
"Ġproviding": 1858,
"Ġresources": 1859,
"âĢĻ": 1860,
"Ġassist": 1861,
"Ġnatural": 1862,
"è¯Ħ": 1863,
"便": 1864,
"Ġsaf": 1865,
"åħ·æľī": 1866,
"è°¢": 1867,
"çĥŃ": 1868,
"ss": 1869,
"eth": 1870,
"old": 1871,
"Ġperform": 1872,
"Ġseveral": 1873,
"é¤IJ": 1874,
"Ġeach": 1875,
"转": 1876,
"ci": 1877,
"Ġty": 1878,
"Ġpub": 1879,
"æ´»åĬ¨": 1880,
"ocus": 1881,
"çīĮ": 1882,
"è¶Ĭ": 1883,
"åĽ¢": 1884,
"è½»": 1885,
"è¯Ńè¨Ģ": 1886,
"Ġareas": 1887,
"éĩĩ": 1888,
"ft": 1889,
"riend": 1890,
"å·²": 1891,
"å¸Ĥåľº": 1892,
"ition": 1893,
"ients": 1894,
"管çIJĨ": 1895,
"许": 1896,
"人类": 1897,
"身ä½ĵ": 1898,
"ique": 1899,
"Ġpartic": 1900,
"ç»Ń": 1901,
"agement": 1902,
"ves": 1903,
"符": 1904,
"line": 1905,
"红": 1906,
"åIJ¸": 1907,
"Ġpatter": 1908,
"000": 1909,
"社ä¼ļ": 1910,
"åĨħ容": 1911,
"Ġorganiz": 1912,
"ough": 1913,
"Ġve": 1914,
"åŃ©åŃIJ": 1915,
"æĸ½": 1916,
"æ¤į": 1917,
"åĩł": 1918,
"ä½Ĩæĺ¯": 1919,
"Ġaff": 1920,
"Ġnum": 1921,
"lement": 1922,
"èīº": 1923,
"èij": 1924,
"Ġcar": 1925,
"ages": 1926,
"abor": 1927,
"æĺ¯ä¸Ģç§į": 1928,
"Ġinst": 1929,
"èĽ": 1930,
"ä¹ĭä¸Ģ": 1931,
"è·¯": 1932,
"åį³": 1933,
"Ġmain": 1934,
"éļı": 1935,
"How": 1936,
"å¿ħ": 1937,
"ç¨ĭåºı": 1938,
"éŁ³ä¹IJ": 1939,
"red": 1940,
"æ²¹": 1941,
"Ġoffer": 1942,
"ets": 1943,
"ç¢": 1944,
"Ġduring": 1945,
"çļĦ人": 1946,
"æĽ´å¤ļ": 1947,
"Ġdi": 1948,
"代çłģ": 1949,
"èİ·": 1950,
"åħĭ": 1951,
"Ġguid": 1952,
"主è¦ģ": 1953,
"Ġfam": 1954,
"æİ§": 1955,
"éĢļ常": 1956,
"ĠAd": 1957,
"å¤ĦçIJĨ": 1958,
"urn": 1959,
"ower": 1960,
"åij½": 1961,
"æıı": 1962,
"Ġskills": 1963,
"Ġtool": 1964,
"ware": 1965,
"æĸĩæľ¬": 1966,
"Ġpatterns": 1967,
"缮æłĩ": 1968,
"acy": 1969,
"æīĵ": 1970,
"åŁİå¸Ĥ": 1971,
"Ġevery": 1972,
"ries": 1973,
"读": 1974,
"éģ¿": 1975,
"çϽ": 1976,
"éĢĤåIJĪ": 1977,
"Ġpatient": 1978,
"羣": 1979,
"oth": 1980,
"她": 1981,
"åĶ®": 1982,
"ä¸Ģç§į": 1983,
"Ġmade": 1984,
"ä½İ": 1985,
"ise": 1986,
"Ġrem": 1987,
"æ¶Ī": 1988,
"åIJ«": 1989,
"air": 1990,
"Ġgener": 1991,
"oy": 1992,
"ç²¾": 1993,
"æĥħåĨµ": 1994,
"ights": 1995,
"Ġexpl": 1996,
"è§ģ": 1997,
"Ġpredict": 1998,
"ç±³": 1999,
"æĽ´å¥½": 2000,
"ä¿®": 2001,
"Ġclimate": 2002,
"Ġfocus": 2003,
"Ġgrow": 2004,
"客æĪ·": 2005,
"ä¸įæĸŃ": 2006,
"itor": 2007,
"ĠEn": 2008,
"约": 2009,
"æĺ¯åIJ¦": 2010,
"ä»ħ": 2011,
"æĪij们çļĦ": 2012,
"æľĽ": 2013,
"op": 2014,
"Ġmaking": 2015,
"yth": 2016,
"ccess": 2017,
"Ġown": 2018,
"ggest": 2019,
"Ġtas": 2020,
"uture": 2021,
"Ġmodel": 2022,
"put": 2023,
"Ġresearch": 2024,
"erest": 2025,
"éļ¾": 2026,
"Ġ[": 2027,
"iel": 2028,
"ational": 2029,
"Ġcommunic": 2030,
"ç¥ŀ": 2031,
"ç©¶": 2032,
"Ġrest": 2033,
"æĪIJ为": 2034,
"king": 2035,
"pr": 2036,
"åĮ»": 2037,
"cur": 2038,
"èĤ²": 2039,
"Ġ'": 2040,
"è¿Ļç§į": 2041,
"ç¯ĩ": 2042,
"Ġche": 2043,
"own": 2044,
"éĻħ": 2045,
"Ġfin": 2046,
"åĪ¶ä½ľ": 2047,
"Ġsuggest": 2048,
"å¢ŀåĬł": 2049,
"Ġmedia": 2050,
"ribut": 2051,
"çļĦæĥħ": 2052,
"åĬłåħ¥": 2053,
"Ġcle": 2054,
"åij¨": 2055,
"竳": 2056,
"Ġthink": 2057,
"Ġlocal": 2058,
"pportun": 2059,
"ĠYou": 2060,
"Ġplan": 2061,
"Ġeven": 2062,
"éĽĨ": 2063,
"å·§": 2064,
"ax": 2065,
"Ġchallenges": 2066,
"Ġprof": 2067,
"ĠCan": 2068,
"Ġconcer": 2069,
"Ġfuture": 2070,
"åĬ¿": 2071,
"Ġref": 2072,
"èģĶ": 2073,
"Ġself": 2074,
"æĪĸèĢħ": 2075,
"ble": 2076,
"åĽ´": 2077,
"è¿IJåĬ¨": 2078,
"Ġinf": 2079,
"éĩĬ": 2080,
"Ġsustainable": 2081,
"Ġtext": 2082,
"Ġgra": 2083,
"äºĮ": 2084,
"åĵģçīĮ": 2085,
"ä¸įåIJĮçļĦ": 2086,
"led": 2087,
"çĭ¬": 2088,
"Ġopportun": 2089,
"Ġcontin": 2090,
"ym": 2091,
"Ġget": 2092,
"å¯Ĩ": 2093,
"éϤ": 2094,
"æħ": 2095,
"éģ¿åħį": 2096,
"Ġ+": 2097,
"è§ī": 2098,
"Ġret": 2099,
"å¸ĥ": 2100,
"Ġinterest": 2101,
"Ġsociety": 2102,
"ç»ĵæŀľ": 2103,
"åIJ¬": 2104,
"é¦ĸåħĪ": 2105,
"Ġbre": 2106,
"Ġ20": 2107,
"ĠHowever": 2108,
"è®°": 2109,
"ons": 2110,
"è¿ij": 2111,
"å¼Ģå§ĭ": 2112,
"Ġbuild": 2113,
"Ġbeh": 2114,
"'m": 2115,
"vers": 2116,
"Ġgood": 2117,
"çIJĨè§£": 2118,
"resent": 2119,
"离": 2120,
"åĬŁèĥ½": 2121,
"Ġeffort": 2122,
"labor": 2123,
"é»ij": 2124,
"Ġbetter": 2125,
"Ġread": 2126,
"å¾ĭ": 2127,
"èĽĭ": 2128,
"hed": 2129,
"ä¹°": 2130,
"导èĩ´": 2131,
"Ġimplement": 2132,
"ç¿": 2133,
"享": 2134,
"头": 2135,
"ense": 2136,
"Ġlong": 2137,
"other": 2138,
"饮": 2139,
"åŃĺåľ¨": 2140,
"çļĦæĦ": 2141,
"ä¸Ģ份": 2142,
"ython": 2143,
"ning": 2144,
"åĩıå°ij": 2145,
"åĢĻ": 2146,
"ä¸ĵ": 2147,
"åIJĦç§į": 2148,
"èħ": 2149,
"å°½": 2150,
"åįĩ": 2151,
"æĬ¥": 2152,
"Ġpublic": 2153,
"Ġlar": 2154,
"ä½łçļĦ": 2155,
"aut": 2156,
"é¢ĨåŁŁ": 2157,
"æļ": 2158,
"ollow": 2159,
"èģĮ": 2160,
"Ġchang": 2161,
"Ġbest": 2162,
"hip": 2163,
"åĨį": 2164,
"akes": 2165,
"Ġchat": 2166,
"ited": 2167,
"Ġpower": 2168,
"ä¿ĿæĬ¤": 2169,
"书": 2170,
"计åĪĴ": 2171,
"éĩįè¦ģçļĦ": 2172,
"åıĺåĮĸ": 2173,
"ilities": 2174,
"Ġconsider": 2175,
"æĪij们åı¯ä»¥": 2176,
"éĤ£ä¹Ī": 2177,
"Ġide": 2178,
"æ¼Ķ": 2179,
"aging": 2180,
"Ġbased": 2181,
"å®Ŀ": 2182,
"Ġrange": 2183,
"Ġresult": 2184,
"Ġmem": 2185,
"çħ§": 2186,
"Ġlevel": 2187,
"cou": 2188,
"Ġbr": 2189,
"Th": 2190,
"ä¼ģ": 2191,
"建ç«ĭ": 2192,
"Ġunique": 2193,
"è®Ń": 2194,
"Ġmark": 2195,
"许å¤ļ": 2196,
"è¡Į为": 2197,
"Ķç©¶": 2198,
"çļĦæĬ": 2199,
"Ġset": 2200,
"骤": 2201,
"ts": 2202,
"Ġhist": 2203,
"Ġaround": 2204,
"Ġrev": 2205,
"åħ¶ä¸Ń": 2206,
"ï¼ģ": 2207,
"æııè¿°": 2208,
"æľĢåIJİ": 2209,
"Ġsim": 2210,
"nect": 2211,
"åĽŀçŃĶ": 2212,
"éĺ²": 2213,
"èī¯": 2214,
"åΰäºĨ": 2215,
"ä¸ĸçķ": 2216,
"æĸ¹æ¡Ī": 2217,
"æĿIJæĸĻ": 2218,
"ä¸ĸçķĮ": 2219,
"æĽ´å¥½åľ°": 2220,
"两个": 2221,
"Ġemploy": 2222,
"Ġtry": 2223,
"æĵ": 2224,
"Ġback": 2225,
"åĪĩ": 2226,
"Ġsuccess": 2227,
"Ġdecisions": 2228,
"Ġthose": 2229,
"å¯Į": 2230,
"Ġfact": 2231,
"æİ¢": 2232,
"è¶£": 2233,
"Ġpractices": 2234,
"åIJĹ": 2235,
"æīį": 2236,
"çİ©": 2237,
"ption": 2238,
"æĸĩ竳": 2239,
"Ġfeat": 2240,
"Ġprevent": 2241,
"Ġwriting": 2242,
"çļĦæĢ": 2243,
"Ġno": 2244,
"ä»ĭ": 2245,
"éŨ": 2246,
"Ġdel": 2247,
"æĴ": 2248,
"Ġoptim": 2249,
"ination": 2250,
"ĠĊ": 2251,
"usion": 2252,
"Ġaccount": 2253,
"ling": 2254,
"Ġdivers": 2255,
".\"": 2256,
"ath": 2257,
"èĭ±": 2258,
"ä¼ģä¸ļ": 2259,
"Ġgrou": 2260,
"åľ°çIJĥ": 2261,
"失": 2262,
"Ġpersonalized": 2263,
"ĠHe": 2264,
"表达": 2265,
"curity": 2266,
"Ġfollow": 2267,
"产çĶŁ": 2268,
"Ġear": 2269,
"åİĭ": 2270,
"vern": 2271,
"Ġissues": 2272,
"åĿĩ": 2273,
"é²": 2274,
"Ġdr": 2275,
"iving": 2276,
"Ġtraining": 2277,
"Ġrisk": 2278,
"åĩ½": 2279,
"åı²": 2280,
"æij": 2281,
"çļĦæĹ¶": 2282,
"ogn": 2283,
"Ġrequire": 2284,
"Ġenvironmental": 2285,
"back": 2286,
"éĶ®": 2287,
"çĸĹ": 2288,
"Ġinteract": 2289,
"åĽ¢éĺŁ": 2290,
"æ¯ı个": 2291,
"çĦ¶åIJİ": 2292,
"Ġdist": 2293,
"ç͍äºİ": 2294,
"认为": 2295,
"åĩ½æķ°": 2296,
"Ġsent": 2297,
"ĊĠĠĠĠĠĠĠĠ": 2298,
"Ġreducing": 2299,
"å¹²": 2300,
"Ġrep": 2301,
"Ġcaus": 2302,
"Ġmusic": 2303,
"çª": 2304,
"Ġmonitor": 2305,
"Ġform": 2306,
"é¢ľ": 2307,
"çĹħ": 2308,
"é¦Ļ": 2309,
"Ġoften": 2310,
"åı¯èĥ½ä¼ļ": 2311,
"åijĺå·¥": 2312,
"Ġhand": 2313,
"æĬķ": 2314,
"Ġneeds": 2315,
"æŃ¤å¤ĸ": 2316,
"åıĭ": 2317,
"ivity": 2318,
"Ġactivities": 2319,
"åĸľæ¬¢": 2320,
"Ġpur": 2321,
"ian": 2322,
"self": 2323,
"åĬ¨çī©": 2324,
"comes": 2325,
"å©": 2326,
"Ġpriv": 2327,
"az": 2328,
"Ġrelations": 2329,
"Ġmachine": 2330,
"çļĦæ°": 2331,
"ä»·æł¼": 2332,
"ä»·å̼": 2333,
"ç´¢": 2334,
"Ġfeed": 2335,
"ä¸Ģä¸ĭ": 2336,
"Ġteam": 2337,
"Ġindustry": 2338,
"è´¢": 2339,
"ĠPro": 2340,
"Ġwant": 2341,
"ç§°": 2342,
"Ġclass": 2343,
"Ġlove": 2344,
"åħ³äºİ": 2345,
"è¾ĵåħ¥": 2346,
"Ġtransport": 2347,
"Ġcomplex": 2348,
"Ġyear": 2349,
"éĶĢåĶ®": 2350,
"寻": 2351,
"ience": 2352,
"ists": 2353,
"æĶ¯æĮģ": 2354,
"Ġmind": 2355,
"Ġfun": 2356,
"Ġchar": 2357,
"æĮī": 2358,
"Ġconcerns": 2359,
"conom": 2360,
"ç®Ģåįķ": 2361,
"以ä¸ĭæĺ¯": 2362,
"Ġstart": 2363,
"å¹¶ä¸Ķ": 2364,
"avi": 2365,
"ä¸ŃåĽ½": 2366,
"åħĥç´ł": 2367,
"Ġconf": 2368,
"Ġpositive": 2369,
"Ġcur": 2370,
"Ġcount": 2371,
"ery": 2372,
"å¡": 2373,
"室": 2374,
"Ġcost": 2375,
"Ġequ": 2376,
"Ġpolic": 2377,
"aste": 2378,
"aw": 2379,
"éħĴ": 2380,
"coura": 2381,
"iven": 2382,
"place": 2383,
"chie": 2384,
"çļĦæķ°": 2385,
"åĽłç´ł": 2386,
"Ġfl": 2387,
"ism": 2388,
"Ġmedical": 2389,
"Ġhumans": 2390,
"Ġautom": 2391,
"ertainly": 2392,
"Ġ0": 2393,
"Ġoffers": 2394,
"Ġdetect": 2395,
"Ġ6": 2396,
"é£İæł¼": 2397,
"Ġshow": 2398,
"çģ«": 2399,
"Ġanim": 2400,
"é¢ľèī²": 2401,
"lease": 2402,
"ave": 2403,
"åĵª": 2404,
"ĠThere": 2405,
"以ä¸Ĭ": 2406,
"æľªæĿ¥": 2407,
"XX": 2408,
"çīĩ": 2409,
"uch": 2410,
"Ġtasks": 2411,
"åħ·ä½ĵ": 2412,
"æ¤įçī©": 2413,
"Ġmin": 2414,
"èīºæľ¯": 2415,
"icult": 2416,
"Ġexperiences": 2417,
"æİ§åζ": 2418,
"be": 2419,
"Ġpatients": 2420,
"å²": 2421,
"ĠWe": 2422,
"Ġrecogn": 2423,
"çĥ¤": 2424,
"Ġsmall": 2425,
"åĿĹ": 2426,
"åĦ": 2427,
"太éĺ³": 2428,
"ction": 2429,
"Ġent": 2430,
"æį¢": 2431,
"Ġbefore": 2432,
"Ġbecome": 2433,
"å·²ç»ı": 2434,
"表çݰ": 2435,
"Ġexplo": 2436,
"Ġachie": 2437,
"ä»»åĬ¡": 2438,
"大çļĦ": 2439,
"Ġday": 2440,
"Ġfound": 2441,
"å±±": 2442,
"ond": 2443,
"Ġtreatment": 2444,
"pend": 2445,
"hen": 2446,
"Ġcondit": 2447,
"ç¡®å®ļ": 2448,
"Ġbusinesses": 2449,
"ĠWh": 2450,
"æīĢæľī": 2451,
"Ġdeveloped": 2452,
"ç»Ī": 2453,
"æŃ¥éª¤": 2454,
"Ġdifficult": 2455,
"åı·": 2456,
"ĠRe": 2457,
"éĶĻ": 2458,
"Ġcho": 2459,
"Ġquest": 2460,
"Ġtranspare": 2461,
"Ġproject": 2462,
"Ġcommunity": 2463,
"ov": 2464,
"å¸Ī": 2465,
"å¼ł": 2466,
"åĪĨç±»": 2467,
"人çļĦ": 2468,
"sis": 2469,
"çĽĬ": 2470,
"oid": 2471,
"ĠAn": 2472,
"ways": 2473,
"Ġeas": 2474,
"Ġaffect": 2475,
"Ġothers": 2476,
"Ġregul": 2477,
"æĢ§åĴĮ": 2478,
"åĸĦ": 2479,
"agn": 2480,
"ä½ľä¸º": 2481,
"åı¯ä»¥å¸®åĬ©": 2482,
"åĦ¿": 2483,
"Ġorganizations": 2484,
"鸡": 2485,
"åħ´": 2486,
"Ġfriend": 2487,
"Ġ$": 2488,
"Ġdetail": 2489,
"Ġtraditional": 2490,
"Ġdesigned": 2491,
"è´Ńä¹°": 2492,
"ä½ĵéªĮ": 2493,
"ç»į": 2494,
"erm": 2495,
"Ġconnect": 2496,
"è¿Ļæł·": 2497,
"Ġrecommendations": 2498,
"Ġboth": 2499,
"ŁéĢļ": 2500,
"æ¯į": 2501,
"Ġsit": 2502,
"ä½ľç͍": 2503,
"ä»ĭç»į": 2504,
"Ġste": 2505,
"ĠSure": 2506,
"åı°": 2507,
"æĤ¨çļĦ": 2508,
"Ġshe": 2509,
"Ġmanagement": 2510,
"joy": 2511,
"è´Ł": 2512,
"Ġpromote": 2513,
"Ġvarious": 2514,
"(\"": 2515,
"por": 2516,
"Ġsens": 2517,
"Ġessential": 2518,
"gether": 2519,
"ularly": 2520,
"äºī": 2521,
"irst": 2522,
"Ġop": 2523,
"Ġspecies": 2524,
"çİ°åľ¨": 2525,
"cho": 2526,
"Ġbehavi": 2527,
"çŃij": 2528,
"女": 2529,
"Ġquality": 2530,
"Ġext": 2531,
"è¥": 2532,
"å®ĮæĪIJ": 2533,
"æĢ»ä¹ĭ": 2534,
"éĥ¨åĪĨ": 2535,
"ä»İèĢĮ": 2536,
"åĽ¾": 2537,
"Ġtyp": 2538,
"Ġstrate": 2539,
"西": 2540,
"Ġhere": 2541,
"ars": 2542,
"å¸Į": 2543,
"çļĦæĿ": 2544,
"å°Ŀ": 2545,
"ee": 2546,
"ier": 2547,
"Ġec": 2548,
"ically": 2549,
"ering": 2550,
"念": 2551,
"ĠDe": 2552,
"Ġneg": 2553,
"建çŃij": 2554,
"Ġservices": 2555,
"Ġable": 2556,
"imes": 2557,
"Ġoptions": 2558,
"缸åħ³": 2559,
"Ġsub": 2560,
"Ġdecision": 2561,
"ĠCertainly": 2562,
"Ġåľ¨": 2563,
"æ¢": 2564,
"Ġservice": 2565,
"):": 2566,
"带æĿ¥": 2567,
"Ġchild": 2568,
"è§£éĩĬ": 2569,
"irt": 2570,
"çĨ": 2571,
"ä¸įä»ħ": 2572,
"æĿ¾": 2573,
"积æŀģ": 2574,
"ron": 2575,
"åı¤": 2576,
"çłĶç©¶": 2577,
"ç²ī": 2578,
"hor": 2579,
"Ġprofess": 2580,
"çļĦéĹ®é¢ĺ": 2581,
"Ġopportunities": 2582,
"åİĨåı²": 2583,
"Ġdef": 2584,
"ĠAm": 2585,
"Ġgr": 2586,
"aur": 2587,
"å±Ĥ": 2588,
"çŃĸ": 2589,
"Ġpopular": 2590,
"æ´ģ": 2591,
"åıijçݰ": 2592,
"Ġpoem": 2593,
"èµĽ": 2594,
"Ġob": 2595,
"Ġdon": 2596,
"Ġsound": 2597,
"Ġtransportation": 2598,
"ious": 2599,
"åı¦": 2600,
"Ġrole": 2601,
"Ġfiel": 2602,
"ç§ijåѦ": 2603,
"èĢģ": 2604,
"reen": 2605,
"æľīæķĪ": 2606,
"Ġcor": 2607,
"Ġfeedback": 2608,
"Ġtechnologies": 2609,
"交éĢļ": 2610,
"Ġadapt": 2611,
"'re": 2612,
"ervation": 2613,
"Ġcommunities": 2614,
"çݰ代": 2615,
"Ġlook": 2616,
"Ġfac": 2617,
"ç͵影": 2618,
"Ġcollect": 2619,
"å¾Ĺåΰ": 2620,
"hips": 2621,
"Ġavail": 2622,
"eren": 2623,
"ä¸Ģèµ·": 2624,
"çīĽ": 2625,
"Ġposs": 2626,
"Ġweather": 2627,
"Ġefforts": 2628,
"¿Ģ": 2629,
"æĹħ": 2630,
"oh": 2631,
"Ġcollabor": 2632,
"æĭ¥": 2633,
"æĪIJåĬŁ": 2634,
"èİ·å¾Ĺ": 2635,
"å±ħ": 2636,
"Ġtre": 2637,
"Ġsources": 2638,
"Ġstudy": 2639,
"Ġprograms": 2640,
"éĻIJ": 2641,
"Ġtips": 2642,
"Ġmarket": 2643,
"ally": 2644,
"害": 2645,
"wards": 2646,
"æ£Ģ": 2647,
"ä¸Ģç¯ĩ": 2648,
"rior": 2649,
"Ġtop": 2650,
"Ġend": 2651,
"åĭ": 2652,
"Ġlarge": 2653,
"iciency": 2654,
"Ġdec": 2655,
"å®ļçļĦ": 2656,
"icient": 2657,
"è¿ĩç¨ĭä¸Ń": 2658,
"lications": 2659,
"缺": 2660,
"Ġtour": 2661,
"Ġtogether": 2662,
"人工": 2663,
"Ġtools": 2664,
"æĸ¯": 2665,
"æ°ij": 2666,
"æĬĬ": 2667,
"ä¹ĭéĹ´çļĦ": 2668,
"çī¹çĤ¹": 2669,
"Ġbel": 2670,
"ditionally": 2671,
"åĪ©ç͍": 2672,
"è¾¹": 2673,
"éĻį": 2674,
"ĠIf": 2675,
"é¢Ŀ": 2676,
"åįı": 2677,
"å¾Ģ": 2678,
"lish": 2679,
"è¯ī": 2680,
"ins": 2681,
"奶": 2682,
"Ġeconom": 2683,
"Ġinvest": 2684,
"ĠDo": 2685,
"tain": 2686,
"åĩºçݰ": 2687,
"çļĦå½±åĵį": 2688,
"aterial": 2689,
"Ġsure": 2690,
"Ġpass": 2691,
"çĶ»": 2692,
"è´£": 2693,
"ç»ĵæŀĦ": 2694,
"æķħ": 2695,
"æĥħæĦŁ": 2696,
"æ¿Ģ": 2697,
"ellig": 2698,
"ä¼Ĺ": 2699,
"æ¯Ķè¾ĥ": 2700,
"tern": 2701,
"Ġoutcomes": 2702,
"up": 2703,
"Ġbeaut": 2704,
"read": 2705,
"çĶŁæĪIJ": 2706,
"æķ°åŃĹ": 2707,
"Ġdem": 2708,
"ires": 2709,
"åı¯ä»¥éĢļè¿ĩ": 2710,
"æĸ°çļĦ": 2711,
"Ġdeep": 2712,
"å¨": 2713,
"çĭĹ": 2714,
"åħ³æ³¨": 2715,
"çĶŁåij½": 2716,
"ä¼łç»Ł": 2717,
"Ġstay": 2718,
"æŃĮ": 2719,
"åħ³éĶ®": 2720,
"Ġplace": 2721,
"主é¢ĺ": 2722,
"å¾Īå¤ļ": 2723,
"èĪĴ": 2724,
"Ġprofessional": 2725,
"yle": 2726,
"æĽ²": 2727,
"19": 2728,
"Ġessay": 2729,
"Ġgive": 2730,
"ç³ĸ": 2731,
"Ġonly": 2732,
"æŁIJ": 2733,
"Ġphys": 2734,
"对è¯Ŀ": 2735,
"Ġcontro": 2736,
"Ġamount": 2737,
"cept": 2738,
"ization": 2739,
"ç¼ĸåĨĻ": 2740,
"åıĹåΰ": 2741,
"Ġalways": 2742,
"æ¯Ķå¦Ĥ": 2743,
"Ġprivacy": 2744,
"au": 2745,
"________": 2746,
"Ġresponsible": 2747,
"()": 2748,
"çŃīçŃī": 2749,
"Ġmaterial": 2750,
"Ġonline": 2751,
"é¼": 2752,
"æĶ¿": 2753,
"åĽĽ": 2754,
"Ġenjoy": 2755,
"åľŁ": 2756,
"Ġsafety": 2757,
"Ġtw": 2758,
"Ġcommunication": 2759,
"丽": 2760,
"æĺ¾": 2761,
"olution": 2762,
"erg": 2763,
"įä½ľ": 2764,
"Ġuser": 2765,
"Ġemotional": 2766,
"time": 2767,
"é¾": 2768,
"Ġsecurity": 2769,
"Ġsense": 2770,
"elines": 2771,
"åĬ±": 2772,
"çī©è´¨": 2773,
"ura": 2774,
"Ġshare": 2775,
"Ġanalyzing": 2776,
"ital": 2777,
"é±": 2778,
"irtual": 2779,
"Ġvisit": 2780,
"bers": 2781,
"Ġcour": 2782,
"Ġproble": 2783,
"设å¤ĩ": 2784,
"atch": 2785,
"land": 2786,
"é±¼": 2787,
"æĪij们éľĢè¦ģ": 2788,
"稳": 2789,
"ibility": 2790,
"Ġefficiency": 2791,
"声": 2792,
"èĴ": 2793,
"æľºåύ": 2794,
"Ġclear": 2795,
"åζå®ļ": 2796,
"izing": 2797,
"Ġconditions": 2798,
"lusion": 2799,
"Ġlow": 2800,
"Ġlim": 2801,
"hers": 2802,
"Ġrisks": 2803,
"ç¿»": 2804,
"Ġlet": 2805,
"åĴĸ": 2806,
"å¿ĥçIJĨ": 2807,
"è¿ľ": 2808,
"print": 2809,
"Ġchanges": 2810,
"Ġmeas": 2811,
"Ġimproving": 2812,
"Ġcrit": 2813,
"50": 2814,
"å¸ĮæľĽ": 2815,
"Ġaud": 2816,
"åįĹ": 2817,
"æĹłæ³ķ": 2818,
"Ġnegative": 2819,
"é¡¹çĽ®": 2820,
"und": 2821,
"ats": 2822,
"Ġcompanies": 2823,
"æī¾åΰ": 2824,
"Ġcontribut": 2825,
"æŃ£ç¡®": 2826,
"é»Ħ": 2827,
"å±ŀ": 2828,
"Ġunderstanding": 2829,
"Ġmult": 2830,
"Ġclo": 2831,
"å¾ģ": 2832,
"Ġprior": 2833,
"rim": 2834,
"人工æĻºèĥ½": 2835,
"Ġvariety": 2836,
"Ġtaking": 2837,
"åĤ": 2838,
"aster": 2839,
"ody": 2840,
"Ġ{": 2841,
"çļĦéĩįè¦ģ": 2842,
"Ġfore": 2843,
"èµĦæºIJ": 2844,
"è¦ģæ±Ĥ": 2845,
"Ġfeatures": 2846,
"èįī": 2847,
"me": 2848,
"èĮĥ": 2849,
"Ġoper": 2850,
"级": 2851,
"é²ľ": 2852,
"æĬĢå·§": 2853,
"ijæĪĺ": 2854,
"ç±»åŀĭ": 2855,
"æĿ¿": 2856,
"软": 2857,
"ew": 2858,
"Ġrestaur": 2859,
"Ġwithout": 2860,
"ructure": 2861,
"çļĦæĺ¯": 2862,
"çı": 2863,
"Ġlist": 2864,
"urate": 2865,
"Ġbook": 2866,
"亲": 2867,
"åºĹ": 2868,
"ä¹Łæĺ¯": 2869,
"ä»»ä½ķ": 2870,
"Ġcam": 2871,
"ĠBe": 2872,
"Ġgovern": 2873,
"Ġbehavior": 2874,
"è®Ńç»ĥ": 2875,
"Ġfamily": 2876,
"æĿĤ": 2877,
"Ġcity": 2878,
"Ġapproach": 2879,
"Ġaccurate": 2880,
"Ġsom": 2881,
"Ġel": 2882,
"èĪŀ": 2883,
"èŀ": 2884,
"åŁºæľ¬": 2885,
"Ġdise": 2886,
"Ġencoura": 2887,
"ĠWhat": 2888,
"åĥ": 2889,
"详": 2890,
"¦Ĥ": 2891,
"å·¥åħ·": 2892,
"åķ¡": 2893,
"Ġstill": 2894,
"chool": 2895,
"æĦŁåΰ": 2896,
"çĶŁçī©": 2897,
"åĴĸåķ¡": 2898,
"åĩĨå¤ĩ": 2899,
"Ġwaste": 2900,
"Ġevents": 2901,
"æķĻèĤ²": 2902,
"Ġ8": 2903,
"Ġmust": 2904,
"ied": 2905,
"asing": 2906,
"å½¢æĪIJ": 2907,
"Ġproducts": 2908,
"åħ¸": 2909,
"讲": 2910,
"fter": 2911,
"å·®": 2912,
"less": 2913,
"Ġcro": 2914,
"Ġfinan": 2915,
"åıįåºĶ": 2916,
"åĪĽéĢł": 2917,
"Ġguidelines": 2918,
"åΤ": 2919,
"ä½ľåĵģ": 2920,
"表示": 2921,
"å¼Ĥ": 2922,
"Ġknown": 2923,
"Ġtest": 2924,
"误": 2925,
"ope": 2926,
"Ġusers": 2927,
"AI": 2928,
"å¾·": 2929,
"new": 2930,
"追": 2931,
"iques": 2932,
"模åŀĭ": 2933,
"åĬĽåĴĮ": 2934,
"Ġhistory": 2935,
"ĠAl": 2936,
"æĬķèµĦ": 2937,
"å°Ŀè¯ķ": 2938,
"ank": 2939,
"Ġhome": 2940,
"éĴŁ": 2941,
"丰": 2942,
"èĪĴéĢĤ": 2943,
"Ġincrease": 2944,
"Ġhab": 2945,
"åĪ»": 2946,
"è¾ĵåĩº": 2947,
"Ġleading": 2948,
"Ġ7": 2949,
"é£İéĻ©": 2950,
"Ġperformance": 2951,
"Ġhapp": 2952,
"åŃ£": 2953,
"Ġstand": 2954,
"ty": 2955,
"ç¦ı": 2956,
"Ġcustomers": 2957,
"åįİ": 2958,
"Ġbelie": 2959,
"Ġcompany": 2960,
"å½ķ": 2961,
"é£Łçī©": 2962,
"ĠUn": 2963,
"Ġsumm": 2964,
"rent": 2965,
"ĠCon": 2966,
"éĢĤéĩı": 2967,
"anced": 2968,
"Ġi": 2969,
"Ġlight": 2970,
"Ġanalysis": 2971,
"å°Ĭ": 2972,
"ĠUse": 2973,
"ouse": 2974,
"ted": 2975,
"Ġcharact": 2976,
"Ġ#": 2977,
"to": 2978,
"绾": 2979,
"ä¸įæĺ¯": 2980,
"Ġdeveloping": 2981,
"åŁ¹": 2982,
"Ġstrategies": 2983,
"Ġmight": 2984,
"çŁŃ": 2985,
"çļĦæİ": 2986,
"Ġfirst": 2987,
"èĥĮ": 2988,
"çĮ«": 2989,
"Ġincludes": 2990,
"åĽŃ": 2991,
"Ġdiagn": 2992,
"Ġgrowth": 2993,
"ä¸ĵä¸ļ": 2994,
"Ġdoes": 2995,
"12": 2996,
"绿": 2997,
"Ġkeep": 2998,
"详ç»Ĩ": 2999,
"åĥı": 3000,
"åıijçĶŁ": 3001,
"fact": 3002,
"åı¯ä»¥åľ¨": 3003,
"ç«Ļ": 3004,
"æĭī": 3005,
"æµİ": 3006,
"Ġchatbots": 3007,
"Ġbreak": 3008,
"è¡¡": 3009,
"çŁ³": 3010,
"æĮģç»Ń": 3011,
"life": 3012,
"Ġ10": 3013,
"æ´Ĺ": 3014,
"ĠAdditionally": 3015,
"士": 3016,
"ember": 3017,
"Ġgoals": 3018,
"å¾®": 3019,
"Ġview": 3020,
"·": 3021,
"ove": 3022,
"åŁºç¡": 3023,
"Ġoptimize": 3024,
"Ġtem": 3025,
"Ġdown": 3026,
"åŁºç¡Ģ": 3027,
"è¶ħ": 3028,
"ercis": 3029,
"Ġless": 3030,
"ees": 3031,
"æĿĥ": 3032,
"Ġkey": 3033,
"Ġworks": 3034,
"讨": 3035,
"åı¥åŃIJ": 3036,
"Ġrobot": 3037,
"uss": 3038,
"åħ¨çIJĥ": 3039,
"ç»ıæµİ": 3040,
"æīįèĥ½": 3041,
"egr": 3042,
"ä»ĸ们çļĦ": 3043,
"äºĶ": 3044,
"èµ·æĿ¥": 3045,
"çĵ": 3046,
"Ġfactors": 3047,
"Ġcultural": 3048,
"æľ¨": 3049,
"Ġworking": 3050,
"ä¼¼": 3051,
"èIJ½": 3052,
"éĢŁåº¦": 3053,
"ä½ı": 3054,
"Ġeffects": 3055,
"å©ļ": 3056,
"br": 3057,
"åİħ": 3058,
"rain": 3059,
"\")": 3060,
"åѦçĶŁ": 3061,
"\",": 3062,
"Ġpar": 3063,
"atform": 3064,
"Ġensuring": 3065,
"çͱäºİ": 3066,
"Ġmuch": 3067,
"Ġwords": 3068,
"Ġmar": 3069,
"ç»ıéªĮ": 3070,
"为äºĨ": 3071,
"åIJĪä½ľ": 3072,
"ven": 3073,
"Ġ/": 3074,
"Ġfinancial": 3075,
"work": 3076,
"ories": 3077,
"æ²»": 3078,
"Ġtechniques": 3079,
"æĭ¥æľī": 3080,
"rap": 3081,
"å°Ķ": 3082,
"Ġest": 3083,
"Ġavailable": 3084,
"Ġlit": 3085,
"æ¹": 3086,
"Ġefficient": 3087,
"els": 3088,
"over": 3089,
"Ġland": 3090,
"Ġarea": 3091,
"Ġintellig": 3092,
"Ġpref": 3093,
"ature": 3094,
"çŁ¥è¯Ĩ": 3095,
"æĵįä½ľ": 3096,
"å¾ħ": 3097,
"igate": 3098,
"çļĦæĶ": 3099,
"Ġmean": 3100,
"bo": 3101,
"Ġcontrol": 3102,
"éĩĩç͍": 3103,
"ricult": 3104,
"Ġprogramm": 3105,
"Ġtowards": 3106,
"thing": 3107,
"ä¸įè¦ģ": 3108,
"Ġthough": 3109,
"彩": 3110,
"Ġcertain": 3111,
"Ġwild": 3112,
"ä»Ĭ": 3113,
"Ġconservation": 3114,
"çŁ¥éģĵ": 3115,
"Ġreally": 3116,
"çļĦåľ°": 3117,
"io": 3118,
"饰": 3119,
"Ġful": 3120,
"çݯä¿Ŀ": 3121,
"Ġexplore": 3122,
"çļĦæ¸": 3123,
"Ġdiverse": 3124,
"åĬłå¼º": 3125,
"çļ®": 3126,
"Ġemotions": 3127,
"Ġavoid": 3128,
"'ll": 3129,
"çļĦæī": 3130,
"åį¡": 3131,
"Ġplatform": 3132,
"ances": 3133,
"Ġsitu": 3134,
"ä»ĺ": 3135,
"ä½įç½®": 3136,
"oring": 3137,
"çĽIJ": 3138,
"ä¸ĩ": 3139,
"Ġdev": 3140,
"nov": 3141,
"ash": 3142,
"Ġtwo": 3143,
"å®ł": 3144,
"bon": 3145,
"èµ°": 3146,
"åĪĹ表": 3147,
"Ġcy": 3148,
"èįIJ": 3149,
"ĠSome": 3150,
"Ġexplain": 3151,
"Ġaware": 3152,
"社交": 3153,
"day": 3154,
"åıĮ": 3155,
"æ²ŁéĢļ": 3156,
"æ°§": 3157,
"å¼Ģåıij": 3158,
"åħ¬åı¸çļĦ": 3159,
"Ġair": 3160,
"åĩ»": 3161,
"aring": 3162,
"éĥ½æĺ¯": 3163,
"Ġlevels": 3164,
"ods": 3165,
"Ġsteps": 3166,
"Ġcap": 3167,
"æ´ŀ": 3168,
"马": 3169,
"Ġreturn": 3170,
"Ġmet": 3171,
"çĶŁæĢģ": 3172,
"丰å¯Į": 3173,
"æŁĵ": 3174,
"æīĢ以": 3175,
"é¡»": 3176,
"Ġer": 3177,
"Ġfra": 3178,
"30": 3179,
"èĵ": 3180,
"âĢĶ": 3181,
"Ġå½ĵ": 3182,
"ah": 3183,
"ä¿ĥ": 3184,
"Ġlikely": 3185,
"ĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ": 3186,
"åĪĿ": 3187,
"Ġcreating": 3188,
"Ġfarm": 3189,
"Ġbal": 3190,
"Ġlives": 3191,
"å®ĥçļĦ": 3192,
"Ġability": 3193,
"ä¸ĬçļĦ": 3194,
"Ġsentence": 3195,
"åĤ¨": 3196,
"Ġrout": 3197,
"Ġprovides": 3198,
"Ġagain": 3199,
"å®łçī©": 3200,
"éĢIJ": 3201,
"Ġyears": 3202,
"èŀį": 3203,
"Ġphysical": 3204,
"Python": 3205,
"ĠEx": 3206,
"iting": 3207,
"è°ĥæķ´": 3208,
"ç½ij绾": 3209,
"æħ¢": 3210,
"空éĹ´": 3211,
"åĽ°": 3212,
"è±Ĩ": 3213,
"æĽ´å¤ļçļĦ": 3214,
"ĠAr": 3215,
"Ġmaintain": 3216,
"å®ŀéĻħ": 3217,
"Ġtravel": 3218,
"Ġsat": 3219,
"pro": 3220,
"ç͵åŃIJ": 3221,
"æ±½": 3222,
"ex": 3223,
"åģĩ": 3224,
"æIJŃ": 3225,
"éļıçĿĢ": 3226,
"è¿ĺæľī": 3227,
"礼": 3228,
"ale": 3229,
"Ġconsum": 3230,
"ĊĠ": 3231,
"ncy": 3232,
"Ġquestions": 3233,
"fort": 3234,
"making": 3235,
"Ġdesc": 3236,
"15": 3237,
"Ġinvolves": 3238,
"Ġstress": 3239,
"åŃĹ符": 3240,
"here": 3241,
"Ġimpacts": 3242,
"Ġexercis": 3243,
"åĿļ": 3244,
"ledge": 3245,
"ç§ijæĬĢ": 3246,
"oci": 3247,
"Ġeffectively": 3248,
"æ¶Īè´¹": 3249,
"Ġconclusion": 3250,
"éĺħ": 3251,
"Ġstre": 3252,
"issions": 3253,
"æ·»": 3254,
"It": 3255,
"éĿĻ": 3256,
"Ġvirtual": 3257,
"è¡£": 3258,
"Ġachieve": 3259,
"ource": 3260,
"è¿ŀ": 3261,
"acks": 3262,
"è¡¨æł¼": 3263,
"Ġimportance": 3264,
"èĩªæĪij": 3265,
"These": 3266,
"num": 3267,
"çļĦæł": 3268,
"Ġrelationships": 3269,
"Ġworkers": 3270,
"gical": 3271,
"orpor": 3272,
"erson": 3273,
"åij¢": 3274,
"nds": 3275,
"æİ¨èįIJ": 3276,
"ohn": 3277,
"å¿ħé¡»": 3278,
"容æĺĵ": 3279,
"ĠGo": 3280,
"Ġtell": 3281,
"ĠRes": 3282,
"onom": 3283,
"Ġbec": 3284,
"æ³Ľ": 3285,
"pos": 3286,
"Ġmove": 3287,
"Ġstory": 3288,
"æŃ¢": 3289,
"Ġpriorit": 3290,
"Ġindustries": 3291,
"èľ": 3292,
"Ġpossible": 3293,
"ĠMan": 3294,
"Ġexpress": 3295,
"abilities": 3296,
"Ġintegr": 3297,
"代表": 3298,
"Ġrespond": 3299,
"åĪĨéĴŁ": 3300,
"æľºä¼ļ": 3301,
"Ġthings": 3302,
"交æµģ": 3303,
"Ġmeth": 3304,
"urther": 3305,
"Ġwide": 3306,
"èijĹ": 3307,
"æĪijçļĦ": 3308,
"ĸçķ¥": 3309,
"ides": 3310,
"ething": 3311,
"ĠWhile": 3312,
"pan": 3313,
"çŃĸçķ¥": 3314,
"Ġcent": 3315,
"Ġplease": 3316,
"ology": 3317,
"uracy": 3318,
"循": 3319,
"ward": 3320,
"nce": 3321,
"Ġthen": 3322,
"çªģ": 3323,
"å¥ĩ": 3324,
"Ġblo": 3325,
"ai": 3326,
"æŀĹ": 3327,
"ç®Ĺæ³ķ": 3328,
"综": 3329,
"Ġprint": 3330,
"aces": 3331,
"lu": 3332,
"ªæĸ½": 3333,
"pre": 3334,
"çļĦæĦı": 3335,
"Ġsol": 3336,
"Ġoverall": 3337,
"hold": 3338,
"Ġes": 3339,
"çļĦä¸Ģ": 3340,
"éģĩ": 3341,
"Ġpopul": 3342,
"å°ı说": 3343,
"æ³¢": 3344,
"åįģ": 3345,
"ä¹Łåı¯ä»¥": 3346,
"é£Łåĵģ": 3347,
"Ġcontent": 3348,
"å°Ħ": 3349,
"Ġrequires": 3350,
"æ£ĢæŁ¥": 3351,
"ĊĠĠĠĠĠĠĠĠĠĠĠ": 3352,
"Ġgroups": 3353,
"Ġfair": 3354,
"Ġbl": 3355,
"å®ŀéªĮ": 3356,
"æĮīçħ§": 3357,
"osp": 3358,
"str": 3359,
"ä¸įèĥ½": 3360,
"Ġharm": 3361,
"Ġprodu": 3362,
"çļĦæĬĢ": 3363,
"çĩ": 3364,
"tle": 3365,
"Ġanimals": 3366,
"è§Ĵèī²": 3367,
"lev": 3368,
"æ¸IJ": 3369,
"å¤įæĿĤ": 3370,
"Ġdepend": 3371,
"æĮijæĪĺ": 3372,
"åĮħåIJ«": 3373,
"Ġhelps": 3374,
"Ġopen": 3375,
"Ġnet": 3376,
"ĠĠĠĠĠ": 3377,
"Ġstrong": 3378,
"Ġjour": 3379,
"å¹¿æ³Ľ": 3380,
"æķ´ä¸ª": 3381,
"Ġelect": 3382,
"Ġresponse": 3383,
"åįķè¯į": 3384,
"æľĭ": 3385,
"Ġ<": 3386,
"åĮĸåѦ": 3387,
"éĴĪ": 3388,
"Ġquick": 3389,
"ually": 3390,
"Ġsomething": 3391,
"Ġtrack": 3392,
"度åĴĮ": 3393,
"erences": 3394,
"æłij": 3395,
"Ġaccuracy": 3396,
"Ġexc": 3397,
"é£ŀ": 3398,
"Ġfield": 3399,
"寻æī¾": 3400,
"éħ¸": 3401,
"Ġhope": 3402,
"çij": 3403,
"Ġinnov": 3404,
"绪": 3405,
"alk": 3406,
"Ġtypes": 3407,
"Ġdid": 3408,
"åĬª": 3409,
"Ġcall": 3410,
"è¯Ĺ": 3411,
"Ġearly": 3412,
"ĠOne": 3413,
"app": 3414,
"Ġcommon": 3415,
"æľĢç»Ī": 3416,
"Ġcheck": 3417,
"Ġsym": 3418,
"çĤĴ": 3419,
"æĬĢèĥ½": 3420,
"Ġenh": 3421,
"Ġagricult": 3422,
"Ġimm": 3423,
"ç»ĩ": 3424,
"满足": 3425,
"Ġschool": 3426,
"bal": 3427,
"Ġfollowing": 3428,
"based": 3429,
"Ġwebs": 3430,
"Ġculture": 3431,
"ĠCom": 3432,
"way": 3433,
"ä¸Ģå®ļ": 3434,
"åķĨåĵģ": 3435,
"ude": 3436,
"çļĦåıijå±ķ": 3437,
"çĶŁäº§": 3438,
"osystem": 3439,
"Ġplant": 3440,
"åı¶": 3441,
"åIJĥ": 3442,
"ä»ĸçļĦ": 3443,
"der": 3444,
"询": 3445,
"å®¶åħ·": 3446,
"Ġfree": 3447,
"ç§»": 3448,
"æİĮ": 3449,
"Ġbody": 3450,
"Ġpresent": 3451,
"Ġparticularly": 3452,
"Ġchildren": 3453,
"Ġstudent": 3454,
").": 3455,
"çī¹å¾ģ": 3456,
"èĶ": 3457,
"éĺħ读": 3458,
"æķĪçİĩ": 3459,
"Ġprogram": 3460,
"éħ±": 3461,
"åıĺå¾Ĺ": 3462,
"ix": 3463,
"Ġcome": 3464,
"çļĦæ²": 3465,
"ĠTe": 3466,
"ĠTo": 3467,
"åħ±åIJĮ": 3468,
"Ġemployees": 3469,
"说æĺİ": 3470,
"Ġheart": 3471,
"Ġmot": 3472,
"æľĭåıĭ": 3473,
"eric": 3474,
"è¯ij": 3475,
"Ġcurrent": 3476,
"æĪIJæľ¬": 3477,
"Ġtoo": 3478,
"çݩ家": 3479,
"åĪĽæĸ°": 3480,
"Ġecosystem": 3481,
"常è§ģ": 3482,
"ä¸ĢæŃ¥": 3483,
"Ġpres": 3484,
"Ġmulti": 3485,
"åijĬè¯ī": 3486,
"严": 3487,
"Ġmit": 3488,
"Ġaction": 3489,
"çĨŁ": 3490,
"Ġhabit": 3491,
"åı£æĦŁ": 3492,
"ç®±": 3493,
"Ġuses": 3494,
"å¢ŀ强": 3495,
"ç»Ļåĩº": 3496,
"Ġ9": 3497,
"Ġdep": 3498,
"Ġeconomic": 3499,
"æĢ§çļĦ": 3500,
"18": 3501,
"åĨ°": 3502,
"Ġhelped": 3503,
"åIJ¸å¼ķ": 3504,
"çİĭ": 3505,
"Ġdiagnos": 3506,
"åł": 3507,
"èģĶç³»": 3508,
"群": 3509,
"ç»ĥä¹ł": 3510,
"æĪIJéķ¿": 3511,
"Ġpoint": 3512,
"å®ļæľŁ": 3513,
"åij¼": 3514,
"èį¯": 3515,
"æĿ¯": 3516,
"æ¤Ĵ": 3517,
"æķĪæŀľ": 3518,
"Ġspecial": 3519,
"æ··": 3520,
"åĩłä¸ª": 3521,
"ause": 3522,
"éĨ": 3523,
"æ¯ĶèµĽ": 3524,
"è·Ŀ": 3525,
"What": 3526,
"Ġtimes": 3527,
"icles": 3528,
"Ġ*": 3529,
"ç´§": 3530,
"å¦Ĥæŀľä½ł": 3531,
"çĭ¬çī¹": 3532,
"çģµ": 3533,
"ç¨İ": 3534,
"Ġcarbon": 3535,
"Ġbias": 3536,
"åĬ©äºİ": 3537,
"Ġconst": 3538,
"èĩªçͱ": 3539,
"æĿ¥è¯´": 3540,
"å°±æĺ¯": 3541,
"åį°": 3542,
"Ġmeet": 3543,
"è§ĦåĪĴ": 3544,
"çļĦç¾": 3545,
"èIJ¥åħ»": 3546,
"ators": 3547,
"稳å®ļ": 3548,
"ode": 3549,
"çħ®": 3550,
"Ġassoci": 3551,
"å¿Ĺ": 3552,
"è¡ĮæĺŁ": 3553,
"æĿİ": 3554,
"Ġreview": 3555,
"åĩĢ": 3556,
"ĠRo": 3557,
"Ġknowledge": 3558,
"以便": 3559,
"æµĭè¯ķ": 3560,
"åIJĪéĢĤ": 3561,
"sc": 3562,
"å½¢å¼ı": 3563,
"Ġfriends": 3564,
"Ġnature": 3565,
"Ġcritical": 3566,
"æ´ĭ": 3567,
"Ġafter": 3568,
"erve": 3569,
"Ġrece": 3570,
"çļĦæŃ": 3571,
"汽车": 3572,
"çķĮ": 3573,
"Ġloss": 3574,
"Ġapplications": 3575,
"å¤ļç§į": 3576,
"éĶħ": 3577,
"串": 3578,
"Ġinsp": 3579,
"---": 3580,
"ĠSh": 3581,
"Ġvol": 3582,
"lut": 3583,
"oks": 3584,
"sequ": 3585,
"Ġbir": 3586,
"åIJĪçIJĨ": 3587,
"Ġnecess": 3588,
"æĪijæĥ³": 3589,
"çŃīæĸ¹éĿ¢": 3590,
"é¼ĵ": 3591,
"Ġsoft": 3592,
"Ġlive": 3593,
"å°ıæĺİ": 3594,
"ĠInd": 3595,
"Ġbring": 3596,
"æĺ¯æĮĩ": 3597,
"Ġsoil": 3598,
"ilar": 3599,
"举": 3600,
"æĿ¡ä»¶": 3601,
"Ġtri": 3602,
"亮": 3603,
"Ġmom": 3604,
"æı¡": 3605,
"ä¼°": 3606,
"ŀäºī": 3607,
"çĽij": 3608,
"èĤ¤": 3609,
"è´¢åĬ¡": 3610,
"æ·»åĬł": 3611,
"é¥®é£Ł": 3612,
"Ġallowing": 3613,
"åºķ": 3614,
"Ġright": 3615,
"Ġexpert": 3616,
"Ġsupp": 3617,
"Ġinit": 3618,
"çļĦæµ": 3619,
"arget": 3620,
"Ġexpect": 3621,
"Ġ19": 3622,
"Ġmeasures": 3623,
"olutions": 3624,
"just": 3625,
"arc": 3626,
"å°ļ": 3627,
"Ġpractice": 3628,
"æľīåĬ©äºİ": 3629,
"大éĩı": 3630,
"',": 3631,
"iment": 3632,
"Ġcontinue": 3633,
"Ġdiscuss": 3634,
"100": 3635,
"éļľ": 3636,
"çļĦæĦŁ": 3637,
"Ġreflect": 3638,
"itation": 3639,
"åį«": 3640,
"äºĨä¸Ģ": 3641,
"ney": 3642,
"ĠLe": 3643,
"ised": 3644,
"è¶ĭ": 3645,
"äºĨä¸Ģ个": 3646,
"Ġincreasing": 3647,
"çļĦæĮ": 3648,
"Ġstru": 3649,
"æĢ»ç»ĵ": 3650,
"ely": 3651,
"å®ĩ": 3652,
"Ġauthor": 3653,
"表éĿ¢": 3654,
"Ġx": 3655,
"æķħäºĭ": 3656,
"emic": 3657,
"Ġrepresent": 3658,
"ger": 3659,
"Ġincreased": 3660,
"ones": 3661,
"ains": 3662,
"Ġtrained": 3663,
"Ġfish": 3664,
"Ġstate": 3665,
"åĨ·": 3666,
"çĶŁéķ¿": 3667,
"Ġrenew": 3668,
"ording": 3669,
"åĮĹ": 3670,
"æİªæĸ½": 3671,
"平衡": 3672,
"Ġsuccessful": 3673,
"ä¸ĭéĿ¢": 3674,
"Ġactivity": 3675,
"èĮ¶": 3676,
"éĢĤåºĶ": 3677,
"èĦij": 3678,
"æİ¢ç´¢": 3679,
"ffic": 3680,
"ç»ĦæĪIJ": 3681,
"atives": 3682,
"äºļ": 3683,
"Ġscen": 3684,
"æ²Ļ": 3685,
"gress": 3686,
"使å¾Ĺ": 3687,
"æī¿": 3688,
"Ġdiscrim": 3689,
"Ġassistants": 3690,
"Ġexist": 3691,
"çķĻ": 3692,
"Ġspace": 3693,
"æľĢè¿ij": 3694,
"Ġideas": 3695,
"éĩĩåıĸ": 3696,
"light": 3697,
"注éĩį": 3698,
"çļĦæĹ¶éĹ´": 3699,
"è¿İ": 3700,
"Ġcomb": 3701,
"éĢĤå½ĵ": 3702,
"Ġyourself": 3703,
"rite": 3704,
"ason": 3705,
"åĮĢ": 3706,
"åı¯ä»¥ä½¿ç͍": 3707,
"åħħ满": 3708,
"Ġvalues": 3709,
"æ½": 3710,
"Ġbiases": 3711,
"ä¿ĥè¿Ľ": 3712,
"åľºæĻ¯": 3713,
"ross": 3714,
"åį³åı¯": 3715,
"Ġcru": 3716,
"Ġnumber": 3717,
"Ġtype": 3718,
"rast": 3719,
"åĩĨç¡®": 3720,
"This": 3721,
"Ġpast": 3722,
"çģ¯": 3723,
"å®ļä¹ī": 3724,
"Ġsolutions": 3725,
"Ġter": 3726,
"ä¿Ŀè¯ģ": 3727,
"èͬ": 3728,
"幸": 3729,
"åī§": 3730,
"åħ´è¶£": 3731,
"åª": 3732,
"ention": 3733,
"avor": 3734,
"Ġscient": 3735,
"åĬªåĬĽ": 3736,
"Ġproviders": 3737,
"Ġpolicies": 3738,
"alu": 3739,
"ĠIm": 3740,
"Ġallows": 3741,
"Ġintelligence": 3742,
"çļĦæĸ¹æ³ķ": 3743,
"è¿Ļæĺ¯": 3744,
"Ġ`": 3745,
"Ġemissions": 3746,
"Ġå°Ĩ": 3747,
"Ġmeaning": 3748,
"Ġstyle": 3749,
"åİŁåĽł": 3750,
"Ġstrugg": 3751,
"çļĦç¾İ": 3752,
"iful": 3753,
"dition": 3754,
"éĥ½æľī": 3755,
"空æ°Ķ": 3756,
"å®ĥ们çļĦ": 3757,
"ä¼ĺåĮĸ": 3758,
"Ġinflu": 3759,
"åŁºäºİ": 3760,
"Ġdetails": 3761,
"Ġtransparency": 3762,
"Ġmess": 3763,
"ĠCl": 3764,
"Ġgame": 3765,
"pri": 3766,
"è¶ĭåĬ¿": 3767,
"å½Ĵ": 3768,
"ç¿»è¯ij": 3769,
"æķ£": 3770,
"By": 3771,
"éŃ": 3772,
"ĠAmeric": 3773,
"Ġproduction": 3774,
"Ġincorpor": 3775,
"æĻļ": 3776,
"Ġinvolve": 3777,
"Ġhot": 3778,
"æĻ®": 3779,
"by": 3780,
"Ġflow": 3781,
"Ġemerg": 3782,
"座": 3783,
"Ġidea": 3784,
"åİĭåĬĽ": 3785,
"éĿĴ": 3786,
"oms": 3787,
"èģĮä¸ļ": 3788,
"Ġreport": 3789,
"Ġpap": 3790,
"Ġtherap": 3791,
"Ġsal": 3792,
"åıĤä¸İ": 3793,
"æĸĩåѦ": 3794,
"æIJŃéħį": 3795,
"oot": 3796,
"),": 3797,
"Ġcr": 3798,
"Ġprocesses": 3799,
"gin": 3800,
"å¹³åı°": 3801,
"å¯Ł": 3802,
"Ġpromoting": 3803,
"æļĸ": 3804,
"akehold": 3805,
"ç»§": 3806,
"iver": 3807,
"æ¦Ĥ": 3808,
"Ġmodels": 3809,
"Ġdra": 3810,
"èĸ": 3811,
"Ġgroup": 3812,
"è¶³å¤Ł": 3813,
"Ġgreen": 3814,
"Ġhealthy": 3815,
"Ġcomfort": 3816,
"Ġadditional": 3817,
"ä¸Ģ次": 3818,
"é¤IJåİħ": 3819,
"Ġmaterials": 3820,
"Ġmanage": 3821,
"çļĦæ¯": 3822,
"伤": 3823,
"åıĬæĹ¶": 3824,
"Ġglo": 3825,
"Ġstat": 3826,
"å¿«éĢŁ": 3827,
"Ġmonitoring": 3828,
"aily": 3829,
"rand": 3830,
"oice": 3831,
"resh": 3832,
"ç»Ħç»ĩ": 3833,
"Ġunder": 3834,
"Ġnecessary": 3835,
"Ġhelpful": 3836,
"ĠCol": 3837,
"é»ijæ´ŀ": 3838,
"åģļåĩº": 3839,
"Ġcourse": 3840,
"Ġmat": 3841,
"Ġleg": 3842,
"Ġface": 3843,
"令": 3844,
"èī¯å¥½çļĦ": 3845,
"ock": 3846,
"åĮ»çĸĹ": 3847,
"çĽĸ": 3848,
"idence": 3849,
"Ġassociated": 3850,
"Ġprogress": 3851,
"åľĨ": 3852,
"Ġeveryone": 3853,
"ç¼ĵ": 3854,
"ĠEng": 3855,
"word": 3856,
"èĵĿ": 3857,
"天æ°Ķ": 3858,
"Ġactions": 3859,
"ems": 3860,
"ĠPl": 3861,
"å®Ļ": 3862,
"ush": 3863,
"顾": 3864,
"Ġcosts": 3865,
"ator": 3866,
"ç©¿": 3867,
"Ġamounts": 3868,
"èͬèıľ": 3869,
"..": 3870,
"Ġmanner": 3871,
"Ġconsequ": 3872,
"æ°ĶåĢĻ": 3873,
"Ġinsights": 3874,
"being": 3875,
"atory": 3876,
"ener": 3877,
"lex": 3878,
"Ġmeans": 3879,
"Ġcollaboration": 3880,
"Ġperspect": 3881,
"orm": 3882,
"priate": 3883,
"å°Ĭéĩį": 3884,
"Ġtarget": 3885,
"è®°å½ķ": 3886,
"åĢĴ": 3887,
"Ġrenewable": 3888,
"æĦ¿": 3889,
"èĥ½æºIJ": 3890,
"Ġinput": 3891,
"å®ĩå®Ļ": 3892,
"ape": 3893,
"Ġadjust": 3894,
"eries": 3895,
"Ġdire": 3896,
"ä¾Ŀ": 3897,
"ustr": 3898,
"fect": 3899,
"Ġbeautiful": 3900,
"Ġdue": 3901,
"reci": 3902,
"çĮ®": 3903,
"èĥĮæĻ¯": 3904,
"èĤ¡": 3905,
"Ġdam": 3906,
"ik": 3907,
"Ġadvanced": 3908,
"çĽ¸å¯¹": 3909,
"åIJįç§°": 3910,
"Ġshort": 3911,
"Ġobject": 3912,
"è¿ĻéĩĮ": 3913,
"éĢłæĪIJ": 3914,
"èIJ¥éĶĢ": 3915,
"çļĦæĥħæĦŁ": 3916,
"票": 3917,
"Ġcountries": 3918,
"ining": 3919,
"istic": 3920,
"Ġplans": 3921,
"责任": 3922,
"Ġstakehold": 3923,
"the": 3924,
"Ġassess": 3925,
"æĢĿèĢĥ": 3926,
"ech": 3927,
"æĪIJåijĺ": 3928,
"21": 3929,
"Ġdaily": 3930,
"Ġcomput": 3931,
"çļĦæĥħåĨµ": 3932,
"æıIJåĩº": 3933,
"ĠâĢľ": 3934,
"åªĴ": 3935,
"ä¸Ńå¿ĥ": 3936,
"ished": 3937,
"ĠSe": 3938,
"onomous": 3939,
"ern": 3940,
"ç»´æĬ¤": 3941,
"ames": 3942,
"Ġprioritize": 3943,
"纸": 3944,
"èĤ¥": 3945,
"Ġtemper": 3946,
"æ¸ħæ´ģ": 3947,
"use": 3948,
"污": 3949,
"Ġminim": 3950,
"æĺ¯åľ¨": 3951,
"大å°ı": 3952,
"åĵªäºĽ": 3953,
"Ġappreci": 3954,
"reng": 3955,
"Ġregulations": 3956,
"ĠZ": 3957,
"éĶĻ误": 3958,
"rans": 3959,
"èĢĮä¸Ķ": 3960,
"èά": 3961,
"èij±": 3962,
"èĨ": 3963,
"æ°´å¹³": 3964,
"è´Ńçī©": 3965,
"åŃĹ符串": 3966,
"对æĸ¹": 3967,
"Ġhim": 3968,
"Ġconsequences": 3969,
"å·´": 3970,
"é¼ĵåĬ±": 3971,
"Ġfil": 3972,
"人åijĺ": 3973,
"è·Ŀ离": 3974,
"ĠWhen": 3975,
"çļĦæ°´": 3976,
"çī©çIJĨ": 3977,
"åIJĮæĹ¶ä¹Ł": 3978,
"åľ¨è¿Ļ个": 3979,
"åħ¶æ¬¡": 3980,
",\"": 3981,
"æ¶²": 3982,
"çĶ·": 3983,
"ival": 3984,
"åı¯ä»¥è®©": 3985,
"æĥ¯": 3986,
"Ġadvance": 3987,
"Ġveh": 3988,
"å¦ĤæŀľæĤ¨": 3989,
"Ġestab": 3990,
"ript": 3991,
"端": 3992,
"ä¸įä¼ļ": 3993,
"Ġtransparent": 3994,
"æķ°éĩı": 3995,
"çĽĺ": 3996,
"Ġspeak": 3997,
"Ġpark": 3998,
"Ġstakeholders": 3999,
"éº": 4000,
"Ġevent": 4001,
"çļĦæķ°æį®": 4002,
"èĩªåĬ¨": 4003,
"ç»ĨèĬĤ": 4004,
"è¯Ħä¼°": 4005,
"润": 4006,
"Ġpreferences": 4007,
"Ġveget": 4008,
"æįŁ": 4009,
"equ": 4010,
"Ġgl": 4011,
"Ġpain": 4012,
"ogra": 4013,
"Ġtraffic": 4014,
"Ġoce": 4015,
"ä¹ĺ": 4016,
"ext": 4017,
"âĢĿï¼Į": 4018,
"Ġanother": 4019,
"å¤ļå°ij": 4020,
"Ġagainst": 4021,
"ç»ıåİĨ": 4022,
"计ç®Ĺæľº": 4023,
"èĢIJ": 4024,
"软件": 4025,
"ĠPre": 4026,
"Ġplants": 4027,
"缸äºĴ": 4028,
"é¢ij": 4029,
"\\_": 4030,
"Ġsame": 4031,
"rug": 4032,
"Ġvalu": 4033,
"Ġocc": 4034,
"çļĦç¤": 4035,
"Ġsustainability": 4036,
"ĠShe": 4037,
"de": 4038,
"ote": 4039,
"Ġdig": 4040,
"NA": 4041,
"Ġcrucial": 4042,
"æī§": 4043,
"å±Ģ": 4044,
"æĭŁ": 4045,
"æĭĮ": 4046,
"Ġnon": 4047,
"Ġengaging": 4048,
"Ġintern": 4049,
"LP": 4050,
"温度": 4051,
"æł¸": 4052,
"æĬ¥åijĬ": 4053,
"æĿ¥è¶Ĭ": 4054,
"hood": 4055,
"ä¸ī个": 4056,
"å¦Ĥä¸ĭ": 4057,
"çī©ä½ĵ": 4058,
"force": 4059,
"Ġneeded": 4060,
"Ġimages": 4061,
"Ġbuilding": 4062,
"icious": 4063,
"ĠæĪij": 4064,
"è¶ĬæĿ¥è¶Ĭ": 4065,
"æĶ¾åħ¥": 4066,
"go": 4067,
"éĻįä½İ": 4068,
"å½ĵåľ°": 4069,
"æ¶Īè´¹èĢħ": 4070,
"ç£": 4071,
"iversity": 4072,
"é¢Ħç®Ĺ": 4073,
"icle": 4074,
"æ··åIJĪ": 4075,
"Ġparticip": 4076,
"Ġdishes": 4077,
"Ġthroughout": 4078,
"Ġwithin": 4079,
"åı³": 4080,
"é«ĺçļĦ": 4081,
"Ġphot": 4082,
"Ġtrust": 4083,
"æĦıè¯Ĩ": 4084,
"以确ä¿Ŀ": 4085,
"çĬ¶æĢģ": 4086,
"Ġautomation": 4087,
"11": 4088,
"Ġpost": 4089,
"æīĭæľº": 4090,
"works": 4091,
"éĢı": 4092,
"åºĵ": 4093,
"Ġwind": 4094,
"Ġ==": 4095,
"Ġprocessing": 4096,
"èĮĥåĽ´": 4097,
"æĦıä¹ī": 4098,
"追æ±Ĥ": 4099,
"é": 4100,
"å¾Ħ": 4101,
"éĿł": 4102,
"ä¸ĸ": 4103,
"èϽ": 4104,
"ç«ŀäºī": 4105,
"Ġappropriate": 4106,
"æĽ´å¥½çļĦ": 4107,
"Ġcharacter": 4108,
"cl": 4109,
"ç§ĺ": 4110,
"itude": 4111,
"Ġteac": 4112,
"leep": 4113,
"ĠDevelop": 4114,
"ince": 4115,
"å·¦": 4116,
"ground": 4117,
"è¡Įä¸ļ": 4118,
"éĴĪ对": 4119,
"å¿ħè¦ģ": 4120,
"Ġdeterm": 4121,
"----------------": 4122,
"Ġstreng": 4123,
"do": 4124,
"Ġchallenging": 4125,
"ork": 4126,
"Ġanx": 4127,
"èī²çļĦ": 4128,
"Ġhard": 4129,
"æĺİç¡®": 4130,
"åĪĨ享": 4131,
"æĶ¹åıĺ": 4132,
"ä½³": 4133,
"åıªæľī": 4134,
"å±ķ示": 4135,
"Ġcamp": 4136,
"纳": 4137,
"aj": 4138,
"etic": 4139,
"ument": 4140,
"ä½łåı¯ä»¥": 4141,
"Ġpollut": 4142,
"Ġhig": 4143,
"pping": 4144,
"ead": 4145,
"çĦ¶èĢĮ": 4146,
"第äºĮ": 4147,
"鸣": 4148,
"çī©åĵģ": 4149,
"举": 4150,
"Ġencourage": 4151,
"pecial": 4152,
"Ġacross": 4153,
"elves": 4154,
"äºĭä»¶": 4155,
"cle": 4156,
"æ©": 4157,
"åªĴä½ĵ": 4158,
"ners": 4159,
"Ġcal": 4160,
"èϽçĦ¶": 4161,
"åĽº": 4162,
"ä¹łæĥ¯": 4163,
"Ġsafe": 4164,
"èĥ½éĩı": 4165,
"istics": 4166,
"ä¹ĭåīį": 4167,
"Ġissue": 4168,
"å¤ļ个": 4169,
"åĨ³çŃĸ": 4170,
"è¾¾åΰ": 4171,
"æĹ©": 4172,
"ä¸įåı¯": 4173,
"ä¸Ģ缴": 4174,
"å·¨": 4175,
"æĦŁè°¢": 4176,
"ĠNew": 4177,
"ä¸Ģ段": 4178,
"Ġmachines": 4179,
"å°Ĩåħ¶": 4180,
"ç»§ç»Ń": 4181,
"Ġword": 4182,
"çī¹åĪ«": 4183,
"Ġagriculture": 4184,
"æĢİ": 4185,
"éĢIJæ¸IJ": 4186,
"éĵ¾": 4187,
"课": 4188,
"Ġkind": 4189,
"å¢Ļ": 4190,
"谢谢": 4191,
"Ġalgorithm": 4192,
"è£ħ饰": 4193,
"Ġalong": 4194,
"Ġeasy": 4195,
"äºij": 4196,
"è§£åĨ³æĸ¹æ¡Ī": 4197,
"Ġawareness": 4198,
"'ve": 4199,
"æĸ¹åIJij": 4200,
"Ġnever": 4201,
"Ġquickly": 4202,
"Ġrespect": 4203,
"çļĦæĻ": 4204,
"Ġamong": 4205,
"Ġaccountability": 4206,
"Ġlaw": 4207,
"ening": 4208,
"Ġdefin": 4209,
"Ġsurround": 4210,
"éĵģ": 4211,
"Ġpowerful": 4212,
"An": 4213,
"Ġcause": 4214,
"æ¥": 4215,
"æİĮæı¡": 4216,
"è¿ĺæĺ¯": 4217,
"Ġcreative": 4218,
"è¡Ģ": 4219,
"Ġlocated": 4220,
"unning": 4221,
"åľ°åĮº": 4222,
"éĿ¢ç§¯": 4223,
"鼨": 4224,
"Ġnear": 4225,
"Ġiniti": 4226,
"ression": 4227,
"ä¸ĭæĿ¥": 4228,
"25": 4229,
"é©¶": 4230,
"¾çĹħ": 4231,
"ables": 4232,
"æľīè¶£": 4233,
"循çݯ": 4234,
"çŃĶæ¡Ī": 4235,
"çł´": 4236,
"ication": 4237,
"éĻ¢": 4238,
"æ²»çĸĹ": 4239,
"Ġaddition": 4240,
"äºĭæĥħ": 4241,
"Ġbecause": 4242,
"åıĪ": 4243,
"èĤĮ": 4244,
"纪": 4245,
"side": 4246,
"æĭħ": 4247,
"湿": 4248,
"åįĬ": 4249,
"顺": 4250,
"ĠAnd": 4251,
"Ġrestaurant": 4252,
"Ġvide": 4253,
"Ġproblem": 4254,
"azing": 4255,
"Ġmembers": 4256,
"Ġnut": 4257,
"Ġcou": 4258,
"浪": 4259,
"Ġè¿Ļ": 4260,
"Ġhelping": 4261,
"ĠIs": 4262,
"æıIJåįĩ": 4263,
"ĠĠĠĠĠĠ": 4264,
"Ġsho": 4265,
"Ġrelev": 4266,
"Ġarg": 4267,
"Ġbalance": 4268,
"illed": 4269,
"æĺ¯ä»Ģä¹Ī": 4270,
"åĬĽéĩı": 4271,
"ired": 4272,
"å¤ľ": 4273,
"åı¯æĮģç»Ń": 4274,
"Ġperfect": 4275,
"**": 4276,
"ification": 4277,
"æ¶ī": 4278,
"Ġwildlife": 4279,
"ane": 4280,
"Ġrelated": 4281,
"室åĨħ": 4282,
"åºľ": 4283,
"享åıĹ": 4284,
"ours": 4285,
"è·ij": 4286,
"åķĨä¸ļ": 4287,
"aching": 4288,
"Ġsun": 4289,
"Ġrecognition": 4290,
"elt": 4291,
"Ġorder": 4292,
"å¹³åĿĩ": 4293,
"ging": 4294,
"临": 4295,
"çĤ¼": 4296,
"Ġgoing": 4297,
"åij¼åIJ¸": 4298,
"Ġsoftware": 4299,
"Ġremot": 4300,
"èijĹåIJį": 4301,
"幸ç¦ı": 4302,
"Ġenhance": 4303,
"èĻļ": 4304,
"Ġnow": 4305,
"Ġthreat": 4306,
"Ġdest": 4307,
"åĿĩåĮĢ": 4308,
"Ġacad": 4309,
"åºĶ对": 4310,
"çľĭåΰ": 4311,
"cast": 4312,
"è¾Ĩ": 4313,
"ificial": 4314,
"Ġvery": 4315,
"ook": 4316,
"åĮºåŁŁ": 4317,
"¹ģ": 4318,
"æĪ¿éĹ´": 4319,
"æıIJä¾ĽäºĨ": 4320,
"Ġmotiv": 4321,
"Ġaccessible": 4322,
"åĨ³å®ļ": 4323,
"Ġhy": 4324,
"å®Ī": 4325,
"Ġflo": 4326,
"ug": 4327,
"Ġinformed": 4328,
"åĵģè´¨": 4329,
"çļĦçŁ": 4330,
"aves": 4331,
"arr": 4332,
"ĠWith": 4333,
"let": 4334,
"è§ĤçĤ¹": 4335,
"enge": 4336,
"è¡ĮåĬ¨": 4337,
"friend": 4338,
"ç³ķ": 4339,
"Ġfurther": 4340,
"ĠEns": 4341,
"ç§ģ": 4342,
"Ġado": 4343,
"Ġclean": 4344,
"缸åºĶ": 4345,
"Ġfre": 4346,
"pecially": 4347,
"èĹ": 4348,
"Ġcapt": 4349,
"çļĦçľ": 4350,
"Ġsomeone": 4351,
"Ġcell": 4352,
"æĶ¾åľ¨": 4353,
"欢è¿İ": 4354,
"ĠâĢ": 4355,
"Ġdevices": 4356,
"çļĦæĸ¹å¼ı": 4357,
"Ġjobs": 4358,
"augh": 4359,
"not": 4360,
"æľīäºĽ": 4361,
"åħ¬åħ±": 4362,
"gest": 4363,
"çļĦçĶŁæ´»": 4364,
"çľ¼": 4365,
"çļĦä¿¡æģ¯": 4366,
"ĠCons": 4367,
"æİĴåºı": 4368,
"Ġbenefit": 4369,
"rect": 4370,
"å¤ı": 4371,
"unte": 4372,
"符åIJĪ": 4373,
"ä¸Ģä½į": 4374,
"åĨħéĥ¨": 4375,
"Ġlooking": 4376,
"ding": 4377,
"æĬĺ": 4378,
"è¾ij": 4379,
"è¿Ļ个éĹ®é¢ĺ": 4380,
"Ġespecially": 4381,
"çľł": 4382,
"âĢĿãĢĤ": 4383,
"å¥ı": 4384,
"ray": 4385,
"è¿ĺåı¯ä»¥": 4386,
"åĪĽä½ľ": 4387,
"coming": 4388,
"Ġmultiple": 4389,
"éļIJ": 4390,
"泡": 4391,
"æłĩåĩĨ": 4392,
"Ġmil": 4393,
"éľĢè¦ģ注æĦı": 4394,
"Ġanxiety": 4395,
"æĶ¹è¿Ľ": 4396,
"å±ĭ": 4397,
"污æŁĵ": 4398,
"ç¼ĸç¨ĭ": 4399,
"è´¹ç͍": 4400,
"Ġevalu": 4401,
"imately": 4402,
"Ġliter": 4403,
"ograph": 4404,
"Ġsearch": 4405,
"16": 4406,
"enced": 4407,
"Ġmethods": 4408,
"çĥĪ": 4409,
"模å¼ı": 4410,
"çĬ¶åĨµ": 4411,
"æĶ¹åĸĦ": 4412,
"å¤ļæł·": 4413,
"cer": 4414,
"å¥ĸ": 4415,
"Ġsatis": 4416,
"Ġwebsite": 4417,
"åĬŀ": 4418,
"åģ¥èº«": 4419,
"Ġglobal": 4420,
"Ġask": 4421,
"Ġplatforms": 4422,
"Ġdiseases": 4423,
"çݰ象": 4424,
"tics": 4425,
"æ±ģ": 4426,
"åΤæĸŃ": 4427,
"Ġconvers": 4428,
"Ġrelationship": 4429,
"设置": 4430,
"æ³ķå¾ĭ": 4431,
"Ġmindful": 4432,
"é¢Ħæµĭ": 4433,
"overy": 4434,
"åģľ": 4435,
"ç͵è§Ĩ": 4436,
"è§ĦåĪĻ": 4437,
"aken": 4438,
"Ġimplementing": 4439,
"ising": 4440,
"åıĤåĬł": 4441,
"æĥħ绪": 4442,
"Ġprovided": 4443,
"æ·±åħ¥": 4444,
"Ġprogrammed": 4445,
"Ġrelevant": 4446,
"çļĦçĥ": 4447,
"çĸ¾çĹħ": 4448,
"åĮ»çĶŁ": 4449,
"åĪĽå»º": 4450,
"Ġgenerate": 4451,
"æĶ¶åħ¥": 4452,
"ä¼ij": 4453,
"izes": 4454,
"Ġtransform": 4455,
"éģµ": 4456,
"astic": 4457,
"åijĪ": 4458,
"æ¯ı个人": 4459,
"è¿Ķ": 4460,
"iet": 4461,
"Ġvoice": 4462,
"éĢĶ": 4463,
"æĶ¾æĿ¾": 4464,
"åį´": 4465,
"èĥľ": 4466,
"Ġstructure": 4467,
"æĹ¶å°ļ": 4468,
"ĠQ": 4469,
"Ġelse": 4470,
"duc": 4471,
"Ġemp": 4472,
"èģļ": 4473,
"è´§": 4474,
"aches": 4475,
"ç§Ģ": 4476,
"anks": 4477,
"Ġnight": 4478,
"Ġprofessionals": 4479,
"Ġbas": 4480,
"è´µ": 4481,
"ec": 4482,
"Ġdiversity": 4483,
"ites": 4484,
"dr": 4485,
"åĽ°éļ¾": 4486,
"ĥåľ": 4487,
"åŀĥåľ": 4488,
"åŀĥåľ¾": 4489,
"Ġdrug": 4490,
"碳": 4491,
"Ġname": 4492,
"åĮĸçļĦ": 4493,
"aid": 4494,
"æľĢ大": 4495,
"æijĦ": 4496,
"ç®ĢåįķçļĦ": 4497,
"Ġwarm": 4498,
"Ġdone": 4499,
"Ġfunction": 4500,
"asc": 4501,
"强è°ĥ": 4502,
"Ġdemand": 4503,
"Ġvisual": 4504,
"Ġupd": 4505,
"æŃ£åľ¨": 4506,
"Ġsimilar": 4507,
"éĢĴ": 4508,
"æ¯Ľ": 4509,
"éĶ»": 4510,
"ently": 4511,
"Ġvaluable": 4512,
"Ġdisaster": 4513,
"ä¸Ģèά": 4514,
"æ´²": 4515,
"ĠReg": 4516,
"Ġdiscrimination": 4517,
"åĨĻä¸Ģç¯ĩ": 4518,
"Ġgovernment": 4519,
"Ġ好çļĦ": 4520,
"500": 4521,
"lying": 4522,
"Ġprev": 4523,
"Ġprepare": 4524,
"Ġproblems": 4525,
"è·³": 4526,
"Ġprom": 4527,
"åĨ²": 4528,
"å®īè£ħ": 4529,
"éĶ»çĤ¼": 4530,
"æµĵ": 4531,
"è¹": 4532,
"åºĶç͍ç¨ĭåºı": 4533,
"ng": 4534,
"Ġcompet": 4535,
"åĪĨåĪ«": 4536,
"ological": 4537,
"审": 4538,
"Ġtransl": 4539,
"Ġdirect": 4540,
"åīĤ": 4541,
"Ġsuggestions": 4542,
"Ġpaper": 4543,
"Ġrecognize": 4544,
"ton": 4545,
"Ġmitigate": 4546,
"讨论": 4547,
"äºĴåĬ¨": 4548,
"ĠEar": 4549,
"Ġamazing": 4550,
"cre": 4551,
"é¦Ī": 4552,
"Ġinvolved": 4553,
"face": 4554,
"æľīåħ³": 4555,
"))": 4556,
"Ġexce": 4557,
"Ġproductivity": 4558,
"èŃ": 4559,
"é¦Ĩ": 4560,
"Ġsounds": 4561,
"Ġidentifying": 4562,
"],": 4563,
"é¾Ļ": 4564,
"Ġfit": 4565,
"Ġcontribute": 4566,
"ths": 4567,
"friendly": 4568,
"ele": 4569,
"ified": 4570,
"iveness": 4571,
"itely": 4572,
"ĠX": 4573,
"Ġled": 4574,
"åĿı": 4575,
"Ġhistor": 4576,
"Ġdat": 4577,
"Ġjourney": 4578,
"Ġ}": 4579,
"Ġselect": 4580,
"漫": 4581,
"Ġconduct": 4582,
"è¿Ľä¸ĢæŃ¥": 4583,
"ç»ĻæĪij": 4584,
"Ġlif": 4585,
"è£ħä¿®": 4586,
"为ä»Ģä¹Ī": 4587,
"京": 4588,
"Ġnav": 4589,
"Ġwhole": 4590,
"ç¹ģ": 4591,
"åĨľ": 4592,
"æĶ»": 4593,
"Ġbreat": 4594,
"Ġmiss": 4595,
"é¾Ħ": 4596,
"tt": 4597,
"sw": 4598,
"Ġbar": 4599,
"请éĹ®": 4600,
"èģĶç½ij": 4601,
"Ġattract": 4602,
"æĤ¨åı¯ä»¥": 4603,
"One": 4604,
"åħħåĪĨ": 4605,
"ring": 4606,
"Ġå½ĵçĦ¶": 4607,
"ream": 4608,
"Ġevol": 4609,
"Ġsn": 4610,
"ĠEm": 4611,
"mosp": 4612,
"Ġchoose": 4613,
"view": 4614,
"Ġarr": 4615,
"Ġsleep": 4616,
"ended": 4617,
"æŀ¶": 4618,
"Ġvehicles": 4619,
"Ġfresh": 4620,
"Ġorganization": 4621,
"è¿Ļ段": 4622,
"汤": 4623,
"ĠInt": 4624,
"Ġcontext": 4625,
"åı¦å¤ĸ": 4626,
"Ġocean": 4627,
"æĦŁåıĹ": 4628,
"Ġpollution": 4629,
"urb": 4630,
"æī§è¡Į": 4631,
"ersonal": 4632,
"ĠHealth": 4633,
"ä¼ĺçĤ¹": 4634,
"Ġattention": 4635,
"æľīçĿĢ": 4636,
"é£ŁæĿIJ": 4637,
"Ġerr": 4638,
"çļĦæĿ¥": 4639,
"çļĦçĪ": 4640,
"èѦ": 4641,
"è·Ł": 4642,
"æĹħè¡Į": 4643,
"èĴľ": 4644,
"çļĦæĢĿ": 4645,
"Ġchatbot": 4646,
"çļĦéľĢæ±Ĥ": 4647,
"çķ¥": 4648,
"Ġfeeling": 4649,
"Ġimplemented": 4650,
"社åĮº": 4651,
"çļĦ建议": 4652,
"æIJħ": 4653,
"éĹ»": 4654,
"åıįé¦Ī": 4655,
"缴æİ¥": 4656,
"æĺ¥": 4657,
"itable": 4658,
"æĪijä¼ļ": 4659,
"åį±": 4660,
"èī¯å¥½": 4661,
"Ġliving": 4662,
"åıĺéĩı": 4663,
"ĠBut": 4664,
"Ġcomplete": 4665,
"Ġtrends": 4666,
"Ġmakes": 4667,
"ä»Ĭ天": 4668,
"Ġdistribut": 4669,
"Ġcommit": 4670,
"Ġatmosp": 4671,
"ä¼´": 4672,
"Ġsensors": 4673,
"Ġsw": 4674,
"æĹłè®º": 4675,
"omen": 4676,
"æĶ¿åºľ": 4677,
"Ġchallenge": 4678,
"Ġturn": 4679,
"çIJĨ论": 4680,
"par": 4681,
"Ġwrite": 4682,
"ç»ıåħ¸": 4683,
"emember": 4684,
"é¥Ń": 4685,
"æĸ¹ä¾¿": 4686,
"Ġcu": 4687,
"Ġvalue": 4688,
"Ġfund": 4689,
"pose": 4690,
"è°ĥæŁ¥": 4691,
"çĿ¡": 4692,
"Ġcommunicate": 4693,
"Ġdisease": 4694,
"Ġresearc": 4695,
"Ġlack": 4696,
"arning": 4697,
"ĠPark": 4698,
"çĦ¦": 4699,
"é«ĺ度": 4700,
"Ġrather": 4701,
"宣": 4702,
"çζ": 4703,
"éĺ¶": 4704,
"订": 4705,
"çĥ§": 4706,
"Ġhigher": 4707,
"Ġsummary": 4708,
"ĠAut": 4709,
"çļĦæ³": 4710,
"Ġele": 4711,
"isms": 4712,
"Ġreli": 4713,
"ä¹Łä¼ļ": 4714,
"fra": 4715,
"åijĬè¯īæĪij": 4716,
"æĬ½": 4717,
"Ġsituations": 4718,
"Ġmarine": 4719,
"æĥ³è¦ģ": 4720,
"inci": 4721,
"inal": 4722,
"Ġgain": 4723,
"Ġdifference": 4724,
"æľºåĻ¨äºº": 4725,
"æµģç¨ĭ": 4726,
"ĠChat": 4727,
"ç½ijç«Ļ": 4728,
"æľ«": 4729,
"Ġcolor": 4730,
"Ġaspect": 4731,
"ç½Ĺ": 4732,
"ĠEduc": 4733,
"Ġdeploy": 4734,
"Ġbeauty": 4735,
"æĤ£": 4736,
"ruction": 4737,
"itut": 4738,
"æĿŁ": 4739,
"让æĪij们": 4740,
"éķ¿åº¦": 4741,
"ules": 4742,
"æ¶īåıĬ": 4743,
"Ġdigital": 4744,
"Ġexisting": 4745,
"ĠOr": 4746,
"\\_\\_": 4747,
"Ġbackground": 4748,
"çĹĩ": 4749,
"æ¯ı天": 4750,
"python": 4751,
"Ġfarmers": 4752,
"Ġcontinu": 4753,
"\":": 4754,
"Ġgiven": 4755,
"å°ıæĹ¶": 4756,
"Ġmoment": 4757,
"200": 4758,
"John": 4759,
"éĿ¢å¯¹": 4760,
"Ġintro": 4761,
"Ġtherapy": 4762,
"è¿ĶåĽŀ": 4763,
"å¹¶åľ¨": 4764,
"Ġz": 4765,
"Ġafford": 4766,
"ä¸Ŀ": 4767,
"宽": 4768,
"ĠÃ": 4769,
"ĠNational": 4770,
"èĥ¡": 4771,
"Ġexercise": 4772,
"æIJħæĭĮ": 4773,
"æĶ¯ä»ĺ": 4774,
"éĺ³åħī": 4775,
"è¯ļ": 4776,
"Ġsect": 4777,
"ĠSu": 4778,
"å¢ŀéķ¿": 4779,
"ç¾İ丽": 4780,
"Ġwa": 4781,
"以ä¸ĭæĺ¯ä¸ĢäºĽ": 4782,
"èĽĭç³ķ": 4783,
"Ġill": 4784,
"æ¸ħæĻ": 4785,
"etry": 4786,
"梦": 4787,
"ç¾İåĽ½": 4788,
"ä»į": 4789,
"oney": 4790,
"Ġecosystems": 4791,
"æĮĩ导": 4792,
"def": 4793,
"99": 4794,
"æŁĶ": 4795,
"pped": 4796,
"Ġlimit": 4797,
"çİī": 4798,
"Ġacademic": 4799,
"Ġrestaurants": 4800,
"Ġhead": 4801,
"ä¿¡ä»»": 4802,
"asters": 4803,
"å²ģ": 4804,
"akers": 4805,
"14": 4806,
"As": 4807,
"æł¡": 4808,
"é«ĺæķĪ": 4809,
"phas": 4810,
"yn": 4811,
"ç¨ĭ度": 4812,
"è¾£": 4813,
"ä¸ĬéĿ¢": 4814,
"å®¶å±ħ": 4815,
"term": 4816,
"ç¾İé£Ł": 4817,
"Ġovers": 4818,
"å®ĺ": 4819,
"Ġindic": 4820,
"ĠYour": 4821,
"St": 4822,
"形象": 4823,
"è´¡": 4824,
"åºĬ": 4825,
"ĠSc": 4826,
"agra": 4827,
"羣æŃ£": 4828,
"oint": 4829,
"ids": 4830,
"arent": 4831,
"éĵ¶": 4832,
"èģĬ": 4833,
"Ġregular": 4834,
"ä¼ĺç§Ģ": 4835,
"Ġcolle": 4836,
"çĸij": 4837,
"Ġsubject": 4838,
"Ġgreater": 4839,
"Ġstore": 4840,
"åŁ¹è®Ń": 4841,
"Ġimag": 4842,
"Ġansw": 4843,
"ä½Ļ": 4844,
"Ġspot": 4845,
"åĪĨåŃIJ": 4846,
"Ġaudience": 4847,
"pet": 4848,
"Ġvers": 4849,
"Ġtrail": 4850,
"åĭĩ": 4851,
"erous": 4852,
"Ġguidance": 4853,
"Ġspeech": 4854,
"åĵ²": 4855,
"æĺ¯çͱ": 4856,
"è´¡çĮ®": 4857,
"åIJĪéĢĤçļĦ": 4858,
"设æĸ½": 4859,
"ä»ĸ人": 4860,
"ensive": 4861,
"å̾": 4862,
"aling": 4863,
"Ġprojects": 4864,
"å³": 4865,
"Ġtakes": 4866,
"绩": 4867,
"That": 4868,
"Ġbro": 4869,
"ived": 4870,
"Ġ&": 4871,
"åĿIJ": 4872,
"placement": 4873,
"è¿ŀæİ¥": 4874,
"çļĦ社": 4875,
"ĠTra": 4876,
"Ġrelax": 4877,
"ufact": 4878,
"éģį": 4879,
"Ġsurv": 4880,
"åı£åij³": 4881,
"Ġcreativity": 4882,
"of": 4883,
"å¨ģ": 4884,
"çļĦçł": 4885,
"Ġbreath": 4886,
"Ġplaces": 4887,
"Ġdescrib": 4888,
"èĭ±è¯Ń": 4889,
"Ġdamage": 4890,
"oration": 4891,
"为æĤ¨": 4892,
"ift": 4893,
"Ġcase": 4894,
"å¹´é¾Ħ": 4895,
"Ġpress": 4896,
"çĶľ": 4897,
"éĩİ": 4898,
"æĹħ游": 4899,
"Ġtaken": 4900,
"ined": 4901,
"Ġconcept": 4902,
"æĴŃ": 4903,
"Ġinteresting": 4904,
"è·µ": 4905,
"Ġsea": 4906,
"60": 4907,
"Ġfoot": 4908,
"ĠName": 4909,
"Ġresearchers": 4910,
"éĢģ": 4911,
"Ġwee": 4912,
");": 4913,
"çļĦåħ³éĶ®": 4914,
"ä¼½": 4915,
"elebr": 4916,
"å¡ij": 4917,
"We": 4918,
"ç»ı常": 4919,
"Ġpopulations": 4920,
"åħ¬å¼ı": 4921,
"orn": 4922,
"çĩĥ": 4923,
"人çĶŁ": 4924,
"17": 4925,
"æİ¥åıĹ": 4926,
"Ġlocation": 4927,
"Ġinequ": 4928,
"Ġintervent": 4929,
"Ġinterested": 4930,
"Ġdefinitely": 4931,
"Ġassistance": 4932,
"è¿Ļä¸Ģ": 4933,
"åIJĪåIJĮ": 4934,
"ä¼ĺåĬ¿": 4935,
"çļĦå·¥ä½ľ": 4936,
"Ġ12": 4937,
"Ġmov": 4938,
"åģı": 4939,
"åŃĺåĤ¨": 4940,
"usive": 4941,
"æĹı": 4942,
"ï¼īï¼Į": 4943,
"Ġgas": 4944,
"Ġinterests": 4945,
"æ¸ħæĻ°": 4946,
"Ġgard": 4947,
"çĸ«": 4948,
"Ġsay": 4949,
"夫": 4950,
"ges": 4951,
"èIJ¨": 4952,
"ä¸ļåĬ¡": 4953,
"个æĢ§": 4954,
"åIJ¯": 4955,
"Ġengagement": 4956,
"Ġbig": 4957,
"éľĢè¦ģèĢĥèĻij": 4958,
"Ġprinci": 4959,
"åij¨åĽ´": 4960,
"Ġopportunity": 4961,
"çģ¾": 4962,
"èĹı": 4963,
"rel": 4964,
"缺çĤ¹": 4965,
"Ġhappy": 4966,
"åĴĮåħ¶ä»ĸ": 4967,
"ava": 4968,
"Ġestablish": 4969,
"鸡èĽĭ": 4970,
"iking": 4971,
"ĠTrans": 4972,
"rastructure": 4973,
"forest": 4974,
"èİ·åıĸ": 4975,
"èĦļ": 4976,
"inally": 4977,
"èµı": 4978,
"Ġdelicious": 4979,
"Ġresults": 4980,
"è§Ĥå¯Ł": 4981,
"å®ŀè·µ": 4982,
"Ġlast": 4983,
"Ġpolit": 4984,
"æĢ§èĥ½": 4985,
"For": 4986,
"bi": 4987,
"çĽ¸ä¿¡": 4988,
"ffee": 4989,
"Ġphr": 4990,
"Ġforest": 4991,
"elling": 4992,
"æµģè¡Į": 4993,
"atic": 4994,
"大家": 4995,
"ĠInst": 4996,
"æķ°åѦ": 4997,
"æī©": 4998,
"å®Įåħ¨": 4999,
"å¼ķèµ·": 5000,
"ese": 5001,
"转æį¢": 5002,
"Ġaffected": 5003,
"Ġrobotics": 5004,
"综ä¸Ĭ": 5005,
"Ġprop": 5006,
"让人": 5007,
"æ²³": 5008,
"ä¸ŃæľĢ": 5009,
"Ġautonomous": 5010,
"Ġhaving": 5011,
"Ġtrip": 5012,
"ury": 5013,
"Ġbiased": 5014,
"Ġconsiderations": 5015,
"Ġparticular": 5016,
"åįł": 5017,
"æİ¨å¹¿": 5018,
"Ġinitiatives": 5019,
"ials": 5020,
"åij³éģĵ": 5021,
"Ġtreatments": 5022,
"Ġemphas": 5023,
"çĭ¬çī¹çļĦ": 5024,
"Ġlay": 5025,
"æĶ¿çŃĸ": 5026,
"æĢİä¹Ī": 5027,
"ronic": 5028,
"play": 5029,
"Ġcook": 5030,
"è¿Ľåħ¥": 5031,
"è½®": 5032,
"Ġvolunte": 5033,
"Ġrain": 5034,
"ĠMon": 5035,
"Ġconsumption": 5036,
"èĽĭçϽ": 5037,
"ĠSoc": 5038,
"壤": 5039,
"Ġroutine": 5040,
"Ġimproved": 5041,
"To": 5042,
"人çī©": 5043,
"读èĢħ": 5044,
"Ġgoal": 5045,
"广åijĬ": 5046,
"éķ¿æľŁ": 5047,
"Ġey": 5048,
"He": 5049,
"Ġoutdo": 5050,
"Ġcuis": 5051,
"Ġaway": 5052,
"Ġbooks": 5053,
"Ġtopic": 5054,
"大åĪ©": 5055,
"house": 5056,
"Ġones": 5057,
"ç§Ł": 5058,
"':": 5059,
"æĪ¿å±ĭ": 5060,
"ç§»åĬ¨": 5061,
"Ġdisasters": 5062,
"ests": 5063,
"illing": 5064,
"绿èī²": 5065,
"åĵ²åѦ": 5066,
"æĪIJåĪĨ": 5067,
"Ġoccur": 5068,
"ľä¼½": 5069,
"åľŁå£¤": 5070,
"çļĦ主è¦ģ": 5071,
"çݰå®ŀ": 5072,
"Ġanimal": 5073,
"é¢Ĩ导": 5074,
"Ġviews": 5075,
"éĤ®": 5076,
"æ°§åĮĸ": 5077,
"athy": 5078,
"éģĵå¾·": 5079,
"社交åªĴä½ĵ": 5080,
"ĠPersonal": 5081,
"ĽåĽ´": 5082,
"Ġpurch": 5083,
"Ġcountry": 5084,
"Ġremind": 5085,
"寸": 5086,
"Ġrights": 5087,
"çļĦçݯå¢ĥ": 5088,
"ĠPr": 5089,
"Ġline": 5090,
"ibr": 5091,
"驾": 5092,
"Ġmaj": 5093,
"Ġovercome": 5094,
"Ġnext": 5095,
"æīĢè¿°": 5096,
"è§Ħå®ļ": 5097,
"Ġinteractions": 5098,
"Ġconflic": 5099,
"Ġwhy": 5100,
"ç³»åĪĹ": 5101,
"å°¼": 5102,
"ibly": 5103,
"çīĽå¥¶": 5104,
"Ġresponses": 5105,
"ses": 5106,
"åѦä¼ļ": 5107,
"bol": 5108,
"Ġstandards": 5109,
"ulner": 5110,
"对è¯ĿåĨħ容": 5111,
"lished": 5112,
"çļĦæĢ§": 5113,
"çĶŁæĢģç³»ç»Ł": 5114,
"ann": 5115,
"æĥħåĨµä¸ĭ": 5116,
"寻æ±Ĥ": 5117,
"Ġhold": 5118,
"den": 5119,
"åįĥ": 5120,
"Ġmention": 5121,
"ĠMany": 5122,
"缴åΰ": 5123,
"éģĹ": 5124,
"hel": 5125,
"Ġbelieve": 5126,
"aries": 5127,
"æľīä¸Ģ个": 5128,
"13": 5129,
"Ġatmosphere": 5130,
"Ġmor": 5131,
"æĹ¥æľŁ": 5132,
"ä¹ħ": 5133,
"ä½łå¥½": 5134,
"Ġaddressing": 5135,
"ĠâĢĵ": 5136,
"çļĦåľ°æĸ¹": 5137,
"ming": 5138,
"Ġcannot": 5139,
"Ġmanufact": 5140,
"Ġpie": 5141,
"icing": 5142,
"Ġstudies": 5143,
"ç¾İåij³": 5144,
"ĠAmerican": 5145,
"ĠNLP": 5146,
"Ġaccording": 5147,
"mselves": 5148,
"èĦĤ": 5149,
"èĩªä¿¡": 5150,
"æīĢéľĢ": 5151,
"Ġthemselves": 5152,
"Ġremote": 5153,
"åŁ¹åħ»": 5154,
"å®īæİĴ": 5155,
"ä½łéľĢè¦ģ": 5156,
"Ġregard": 5157,
"iring": 5158,
"è¯ĨåĪ«": 5159,
"Ġarticle": 5160,
"æģĴ": 5161,
"æĢ»çļĦæĿ¥": 5162,
"Ġalign": 5163,
"æ±ł": 5164,
"tenance": 5165,
"faction": 5166,
"åĬ¨ä½ľ": 5167,
"çļĦç©": 5168,
"缩": 5169,
"æĢ¥": 5170,
"Ġ100": 5171,
"Ġtesting": 5172,
"åŃĹæ¯į": 5173,
"å¹´è½»": 5174,
"åζéĢł": 5175,
"Ġswe": 5176,
"å°º": 5177,
"hens": 5178,
"æ°´æŀľ": 5179,
"Ġinfrastructure": 5180,
"èī²å½©": 5181,
"æĢ»çļĦæĿ¥è¯´": 5182,
"æľīä»Ģä¹Ī": 5183,
"text": 5184,
"车è¾Ĩ": 5185,
"Ġpay": 5186,
"rop": 5187,
"ĊĠĠ": 5188,
"Ġcaused": 5189,
"Ġcorrect": 5190,
"Ġì": 5191,
"èĥŀ": 5192,
"ĠMed": 5193,
"ç²¾ç¥ŀ": 5194,
"æ°ĶåĢĻåıĺåĮĸ": 5195,
"ĠRed": 5196,
"äºĴèģĶç½ij": 5197,
"Ġengage": 5198,
"åĪĨ为": 5199,
"ĠData": 5200,
"Ġfull": 5201,
"enc": 5202,
"éĩįæĸ°": 5203,
"æŃ£ç¡®çļĦ": 5204,
"çļĦæ°Ķ": 5205,
"åıĮæĸ¹": 5206,
"Ġcomes": 5207,
"åı¤ä»£": 5208,
"æŁIJäºĽ": 5209,
"åijĪçݰ": 5210,
"Ġtoday": 5211,
"aged": 5212,
"æĪijåı¯ä»¥": 5213,
"æĹ¥å¸¸": 5214,
"æ»ij": 5215,
"Ġclin": 5216,
"Ġ\\": 5217,
"Ġobs": 5218,
"Ġartificial": 5219,
"Ġexcell": 5220,
"çļĦç¬": 5221,
"alls": 5222,
"Ġproduce": 5223,
"ĠDes": 5224,
"oss": 5225,
"è¹Ī": 5226,
"Ġdraw": 5227,
"Ġletter": 5228,
"Ġadvice": 5229,
"Ġhighly": 5230,
"çĬ¯": 5231,
"综ä¸ĬæīĢè¿°": 5232,
"满æĦı": 5233,
"Ġprinciples": 5234,
"èĮĦ": 5235,
"Ġfeelings": 5236,
"çļĦæ´": 5237,
"Ġhom": 5238,
"Ġfail": 5239,
"Ġcrop": 5240,
"å§ľ": 5241,
"Ġquestion": 5242,
"Ġdisabilities": 5243,
"èĪŀè¹Ī": 5244,
"Ġimplications": 5245,
"ral": 5246,
"Ġsing": 5247,
"40": 5248,
"Ġfamil": 5249,
"Ġgovernments": 5250,
"Ġrecord": 5251,
"å½¢çĬ¶": 5252,
"Ġbegin": 5253,
"ises": 5254,
"çļĦæĥ³": 5255,
"achine": 5256,
"è°±": 5257,
"Ġvulner": 5258,
"Ġproper": 5259,
"Ġoversight": 5260,
"è´ŁéĿ¢": 5261,
"Ġemail": 5262,
"Ġnews": 5263,
"Ġexploring": 5264,
"Ġfavor": 5265,
"楼": 5266,
"å®ľ": 5267,
"Ġunivers": 5268,
"å·®å¼Ĥ": 5269,
"ï¼īãĢĤ": 5270,
"è§£åĨ³éĹ®é¢ĺ": 5271,
"Ġfamous": 5272,
"gn": 5273,
"Ġmessage": 5274,
"atitude": 5275,
"Ġcra": 5276,
"Ġcover": 5277,
"æ·±åĪ»": 5278,
"åı¯ä»¥éĢīæĭ©": 5279,
"çĶŁæ´»ä¸Ń": 5280,
"ç§įç±»": 5281,
"Ġsmart": 5282,
"onstr": 5283,
"vey": 5284,
"çͲ": 5285,
"Ġregularly": 5286,
"ĠSm": 5287,
"æĦŁè§ī": 5288,
"Ġthought": 5289,
"Ġexh": 5290,
"cure": 5291,
"ç»ĺ": 5292,
"认è¯Ĩ": 5293,
"Ġold": 5294,
"æĦī": 5295,
"称为": 5296,
"Ġfields": 5297,
"Ġconsist": 5298,
"ãģ": 5299,
"ç»Ĩèĥŀ": 5300,
"Ġhours": 5301,
"80": 5302,
"alking": 5303,
"è§īå¾Ĺ": 5304,
"ç»Ŀ": 5305,
"ä½łä»¬": 5306,
"ĠEnglish": 5307,
"Ġsignificantly": 5308,
"Ġsource": 5309,
"Ġant": 5310,
"Ġeducational": 5311,
"Ġtask": 5312,
"Ġhandle": 5313,
"æIJľ": 5314,
"ĠSp": 5315,
"Ġcalled": 5316,
"Ġterms": 5317,
"æ²ī": 5318,
"Ġwin": 5319,
"duction": 5320,
"Ġmodern": 5321,
"Ġcuisine": 5322,
"å¥Ĺ": 5323,
"触": 5324,
"olutely": 5325,
"ç«¥": 5326,
"pite": 5327,
"Ġfelt": 5328,
"Ġcompre": 5329,
"Ġwond": 5330,
"è¿IJè¡Į": 5331,
"Ġresil": 5332,
"çĽ¸ä¼¼": 5333,
"éĩijèŀį": 5334,
"çαæĥħ": 5335,
"ç¬Ķ": 5336,
"èĪª": 5337,
"è°Ī": 5338,
"åĬĽçļĦ": 5339,
"æľīæīĢ": 5340,
"æ½ľ": 5341,
"ulate": 5342,
"Ġdetection": 5343,
"å®£ä¼ł": 5344,
"Ġmatter": 5345,
"éĩıåŃIJ": 5346,
"Write": 5347,
"ç»ĵåIJĪ": 5348,
"ç»ıè¿ĩ": 5349,
"Ġdevelopers": 5350,
"èª": 5351,
"Ġ---": 5352,
"人éĻħ": 5353,
"çѾ": 5354,
"ï¼ļâĢľ": 5355,
"Ġinnovative": 5356,
"ãĢĤâĢĿ": 5357,
"å½¼": 5358,
"饼": 5359,
"è¿ĩ度": 5360,
"Ġplanet": 5361,
"åħ°": 5362,
"å¸ģ": 5363,
"æķ¬": 5364,
"Ġlegal": 5365,
"Ġlot": 5366,
"æĪIJ为äºĨ": 5367,
"iate": 5368,
"Ġmis": 5369,
"åģĩ设": 5370,
"çļĦæĸĩ竳": 5371,
"ĠCompan": 5372,
"Ġdoc": 5373,
"Ġcareful": 5374,
"Ġever": 5375,
"æĪij们å°Ĩ": 5376,
"ä¾ĭåŃIJ": 5377,
"ä¹³": 5378,
"ä½ľèĢħ": 5379,
"åIJ§": 5380,
"æļ´": 5381,
"Ġremember": 5382,
"缮çļĦ": 5383,
"Ġput": 5384,
"常è§ģçļĦ": 5385,
"Ġfest": 5386,
"建设": 5387,
"å®ŀç͍": 5388,
"Ġactive": 5389,
"çªĹ": 5390,
"outh": 5391,
"åİŁçIJĨ": 5392,
"Ġtrying": 5393,
"è¿·": 5394,
"缸åIJĮ": 5395,
"éħĴåºĹ": 5396,
"Another": 5397,
"æľĢä½³": 5398,
"Ġanalytics": 5399,
"Ġperpet": 5400,
"ipment": 5401,
"Ġå¦Ĥæŀľ": 5402,
"è§Ĥä¼Ĺ": 5403,
"Ġcelebr": 5404,
"Ġheav": 5405,
"Ġmeditation": 5406,
"大æ°Ķ": 5407,
"And": 5408,
"ä¸įéĶĻ": 5409,
"Ġwhether": 5410,
"set": 5411,
"Ġdemonstr": 5412,
"ä¸Ģ款": 5413,
"æĶ¶éĽĨ": 5414,
"éĻIJåζ": 5415,
"Ġing": 5416,
"Ġrevolution": 5417,
"çľģ": 5418,
"Ġscience": 5419,
"缮åīį": 5420,
"Ġthinking": 5421,
"±ä¹IJ": 5422,
"课ç¨ĭ": 5423,
"Ġpack": 5424,
"Ġimage": 5425,
"loc": 5426,
"Ġstories": 5427,
"uck": 5428,
"Ġsatisfaction": 5429,
"Ġcollection": 5430,
"ho": 5431,
"èµŀ": 5432,
"éĿ¢ä¸´": 5433,
"Ġla": 5434,
"Ġsymbol": 5435,
"Ġemb": 5436,
"Ġhabitats": 5437,
"Ġlower": 5438,
"Ġcontinues": 5439,
"éľĩ": 5440,
"åĵĪ": 5441,
"ĠTake": 5442,
"Ġenvironments": 5443,
"Ġthree": 5444,
"Ġenc": 5445,
"ĠAcc": 5446,
"æĦıåij³": 5447,
"åݨ": 5448,
"chan": 5449,
"ĠHum": 5450,
"Ġtrue": 5451,
"åĪĩæĪIJ": 5452,
"sing": 5453,
"âĢĶâĢĶ": 5454,
"åĩºæĿ¥": 5455,
"Ġregion": 5456,
"Ġinterpre": 5457,
"Ġdiagnosis": 5458,
"éŀ": 5459,
"Ġdoing": 5460,
"Ġrun": 5461,
"Ġcoffee": 5462,
"Ġmajor": 5463,
"Ġmindfulness": 5464,
"Ġaffordable": 5465,
"çϾ": 5466,
"Ġdetailed": 5467,
"éĿŀ常éĩįè¦ģçļĦ": 5468,
"çļĦæ²ŁéĢļ": 5469,
"çļĦæķħ": 5470,
"åĢĴåħ¥": 5471,
"Ġthemes": 5472,
"Ġnetwork": 5473,
"ï¼īï¼ļ": 5474,
"ĠUnited": 5475,
"çļĦæĮĩ": 5476,
"orts": 5477,
"åį«çĶŁ": 5478,
"Ġplanning": 5479,
"æĥł": 5480,
"åīª": 5481,
"ĠProv": 5482,
"çļĦåºĶç͍": 5483,
"Ġperi": 5484,
"Ġaccountable": 5485,
"çīĻ": 5486,
"çļĦçģ": 5487,
"Ġchoice": 5488,
"ĠComm": 5489,
"idents": 5490,
"çļĦå®īåħ¨": 5491,
"å¹¶ä¸į": 5492,
"太éĺ³ç³»": 5493,
"Ġreceive": 5494,
"Ġclose": 5495,
"çļĦæĹ¶åĢĻ": 5496,
"Ġchanging": 5497,
"ä»·å̼è§Ĥ": 5498,
"Ġperpetu": 5499,
"Ġseason": 5500,
"Ġmen": 5501,
"Ġlearned": 5502,
"Ġsituation": 5503,
"Ġreplace": 5504,
"head": 5505,
"让æĪij": 5506,
"åľ¨ä¸Ģèµ·": 5507,
"çļĦ空": 5508,
"éľ²": 5509,
"Ġenough": 5510,
"å±ķçݰ": 5511,
"Ġleaders": 5512,
"ancing": 5513,
"Ġtemperature": 5514,
"åı«": 5515,
"Ġ30": 5516,
"æĦıåij³çĿĢ": 5517,
"æ±ĩ": 5518,
"ĠGovern": 5519,
"Ġfocused": 5520,
"uro": 5521,
"Ġsimple": 5522,
"Ġhiking": 5523,
"æ¯Ĵ": 5524,
"Ġcomprehens": 5525,
"äºĪ": 5526,
"Ġcreated": 5527,
"cond": 5528,
"页": 5529,
"ĠWor": 5530,
"è¯ģæį®": 5531,
"Ġworkplace": 5532,
"Ġcharacters": 5533,
"çļĦ设计": 5534,
"Ġmechan": 5535,
"ĠDis": 5536,
"ç¥ŀç§ĺ": 5537,
"å·ŀ": 5538,
"ĠOn": 5539,
"": 5540,
"ç§įæ¤į": 5541,
"Ġpath": 5542,
"Ġlimited": 5543,
"Ġsolar": 5544,
"çļĦæı": 5545,
"22": 5546,
"Ġappreciate": 5547,
"å¿«ä¹IJ": 5548,
"æĦŁåıĹåΰ": 5549,
"èĢĹ": 5550,
"med": 5551,
"icine": 5552,
"Ġnote": 5553,
"å½ĵåīį": 5554,
"æĪij们åºĶ该": 5555,
"Ġseen": 5556,
"ä¸ĢåIJį": 5557,
"å°½åı¯èĥ½": 5558,
"è¿IJç®Ĺ": 5559,
"è§Ĵ度": 5560,
"Ġequipment": 5561,
"Ġspread": 5562,
"è¸": 5563,
"访": 5564,
"åı¥è¯Ŀ": 5565,
"æĮ¥": 5566,
"Ġpurpose": 5567,
"è¯·ä½ł": 5568,
"Your": 5569,
"arian": 5570,
"仪": 5571,
"Ġperspectives": 5572,
"åĩºäºĨ": 5573,
"å©ļ礼": 5574,
"Ġexcellent": 5575,
"ĠEnsuring": 5576,
"Ġreach": 5577,
"éĺ¶æ®µ": 5578,
"ä¿Ŀéļľ": 5579,
"Ġempathy": 5580,
"ĠMy": 5581,
"çijľä¼½": 5582,
"Ġver": 5583,
"abel": 5584,
"ĠPredict": 5585,
"Ġmaintenance": 5586,
"è¯Ħä»·": 5587,
"Ġult": 5588,
"åĴ¨": 5589,
"ox": 5590,
"åĴ¨è¯¢": 5591,
"Ġshared": 5592,
"ina": 5593,
"list": 5594,
"Ġoutdoor": 5595,
"Ġthoughts": 5596,
"inating": 5597,
"éĴ±": 5598,
"Ġframe": 5599,
"éĺ¿": 5600,
"åĪ©æ¶¦": 5601,
"çļĦæİ¨": 5602,
"åįļ": 5603,
"Ġrecent": 5604,
"Ġaltern": 5605,
"ared": 5606,
"==": 5607,
"Ġroad": 5608,
"äºĭ项": 5609,
"ged": 5610,
"ynt": 5611,
"Ġspend": 5612,
"罪": 5613,
"åıĸå¾Ĺ": 5614,
"é¹": 5615,
"li": 5616,
"æĹ¶æľŁ": 5617,
"严éĩį": 5618,
"å¿Ĩ": 5619,
"å©´": 5620,
"æİ¥ä¸ĭæĿ¥": 5621,
"ĠEarth": 5622,
"ĠChatbots": 5623,
"Ġsetting": 5624,
"ç¥Ŀ": 5625,
"éĶĢåĶ®é¢Ŀ": 5626,
"伦": 5627,
"Ġreading": 5628,
"æİ¢è®¨": 5629,
"aign": 5630,
"éŀĭ": 5631,
"Ġyoung": 5632,
"Ġcareer": 5633,
"Ġteachers": 5634,
"çļĦè´¨éĩı": 5635,
"å±ŀäºİ": 5636,
"Ġeasier": 5637,
"Ġscientific": 5638,
"ç¾İåħĥ": 5639,
"Ġspir": 5640,
"åĬ³": 5641,
"çļĦæĶ¯": 5642,
"rist": 5643,
"èµĦ产": 5644,
"çĶŁåŃĺ": 5645,
"èĩ³å°ij": 5646,
"å§¿": 5647,
"Ġvideo": 5648,
"Ġaim": 5649,
"å®Ŀå®Ŀ": 5650,
"çζæ¯į": 5651,
"________________": 5652,
"alities": 5653,
"Ġbud": 5654,
"Ġstreet": 5655,
"Ġæĺ¯": 5656,
"æĸ¹ç¨ĭ": 5657,
"ä¸ĸ纪": 5658,
"ches": 5659,
"earch": 5660,
"æĴ°": 5661,
"Ġengine": 5662,
"Ġdisplacement": 5663,
"ĠRobots": 5664,
"ervised": 5665,
"é¡¶": 5666,
"oud": 5667,
"Ġwalk": 5668,
"Ġemergency": 5669,
"èģĺ": 5670,
"nal": 5671,
"Ġdatas": 5672,
"åĢº": 5673,
"åIJİçļĦ": 5674,
"å¾Ī好": 5675,
"Ġmyself": 5676,
"çļĦæīĭ": 5677,
"Ġusage": 5678,
"Ġshown": 5679,
"æ®Ĭ": 5680,
"Ġtypically": 5681,
"uly": 5682,
"æĸ°éĹ»": 5683,
"æĽ¿": 5684,
"Ġorig": 5685,
"è½»æĿ¾": 5686,
"æĺ¾ç¤º": 5687,
"Ġadopt": 5688,
"èĤ¡ç¥¨": 5689,
"Ġparent": 5690,
"aps": 5691,
"æĢĿæĥ³": 5692,
"Ġmarketing": 5693,
"èĻ«": 5694,
"éĥ¨éŨ": 5695,
"çļĦæķĪ": 5696,
"Ġcomfortable": 5697,
"åŃ¦ä¹łåĴĮ": 5698,
"Ġforecast": 5699,
"iction": 5700,
"Ġgetting": 5701,
"Ġtrees": 5702,
"aving": 5703,
"çļĦåŁºç¡Ģ": 5704,
"ready": 5705,
"æĸ°é²ľ": 5706,
"going": 5707,
"¹é¥": 5708,
"Ġevidence": 5709,
"¹é¥ª": 5710,
"ç§ĭ": 5711,
"æľīå¾Īå¤ļ": 5712,
"éĿ¢è¯ķ": 5713,
"éģĩåΰ": 5714,
"ç»Ļå®ļ": 5715,
"irc": 5716,
"åı¯ä»¥æł¹æį®": 5717,
"驾驶": 5718,
"å·§åħĭ": 5719,
"Ġstunning": 5720,
"çļĦæ¦Ĥ": 5721,
"æ¡Į": 5722,
"ĠJohn": 5723,
"ulation": 5724,
"åıĤèĢĥ": 5725,
"Ġflex": 5726,
"çĦ¦èĻij": 5727,
"ymakers": 5728,
"Ġforms": 5729,
"sh": 5730,
"val": 5731,
"ĠSo": 5732,
"co": 5733,
"æİ¨åĬ¨": 5734,
"èħ¿": 5735,
"ç®Ĭ": 5736,
"Ġenab": 5737,
"å°Ĩä¼ļ": 5738,
"æĶ¯åĩº": 5739,
"åĿļæĮģ": 5740,
"红èī²": 5741,
"Ġoption": 5742,
"Ġstarted": 5743,
"ration": 5744,
"Ġpoetry": 5745,
"Ġport": 5746,
"gen": 5747,
"èªī": 5748,
"Ġdeliv": 5749,
"çĶļ": 5750,
"éĢ»": 5751,
"éĢī项": 5752,
"Ġground": 5753,
"å½¼æŃ¤": 5754,
"ana": 5755,
"çļĦæĹ¥": 5756,
"åľ¨çº¿": 5757,
"Ġsecure": 5758,
"Ġæł¹æį®": 5759,
"饮æĸĻ": 5760,
"Ġgratitude": 5761,
"第ä¸ī": 5762,
"Ġsong": 5763,
"Ġpoints": 5764,
"Ġalready": 5765,
"çļĦçα": 5766,
"ĠTechn": 5767,
"Ġreality": 5768,
"çıŃ": 5769,
"Ġsince": 5770,
"Ġpopulation": 5771,
"yond": 5772,
"bor": 5773,
"ĠSocial": 5774,
"æıIJåıĸ": 5775,
"å·¥ç¨ĭ": 5776,
"aff": 5777,
"交æĺĵ": 5778,
"Ġworth": 5779,
"å¡«": 5780,
"娱ä¹IJ": 5781,
"Ġdog": 5782,
"ĠArt": 5783,
"硬": 5784,
"æµ·æ´ĭ": 5785,
"åĨĴ": 5786,
"çīĪ": 5787,
"Ġprogramming": 5788,
"ĠAss": 5789,
"ĠMachine": 5790,
"å̼å¾Ĺ": 5791,
"请è¾ĵåħ¥": 5792,
"å£°éŁ³": 5793,
"Ġexercises": 5794,
"åħī线": 5795,
"æ³ķåĴĮ": 5796,
"Ġfeature": 5797,
"eff": 5798,
"è¿ĽæŃ¥": 5799,
"女æĢ§": 5800,
"Ġefficiently": 5801,
"çļĦæĬĢæľ¯": 5802,
"Ġgenetic": 5803,
"令人": 5804,
"è´¦": 5805,
"çļĦ产åĵģ": 5806,
"åİļ": 5807,
"åĴĮæĸĩåĮĸ": 5808,
"éĻĦ": 5809,
"Ġmob": 5810,
"综åIJĪ": 5811,
"ters": 5812,
"æľīä¸Ģ": 5813,
"å¦Ĩ": 5814,
"åįĪ": 5815,
"Ġoutside": 5816,
"Ġpropert": 5817,
"éĤ®ä»¶": 5818,
"主ä¹ī": 5819,
"Ġpolicy": 5820,
"èĩªèº«": 5821,
"Ġnavigate": 5822,
"Ġsty": 5823,
"ç͵èĦij": 5824,
"Ġabilities": 5825,
"Ġfaced": 5826,
"çļĦç¼": 5827,
"çļĦå°ı": 5828,
"èķ": 5829,
"Ġtone": 5830,
"igation": 5831,
"åıĤæķ°": 5832,
"èĽĭçĻ½è´¨": 5833,
"ä½Ľ": 5834,
"çĶļèĩ³": 5835,
"Ġskin": 5836,
"èĴ¸": 5837,
"æĭĽ": 5838,
"éŃĶ": 5839,
"ashion": 5840,
"Ġingred": 5841,
"æĹĭ": 5842,
"Ġcampaign": 5843,
"Ġmount": 5844,
"Ġconsid": 5845,
"Ġmuse": 5846,
"nter": 5847,
"water": 5848,
"ä¼ļè®®": 5849,
"Ġprotection": 5850,
"ä¿ĿéĻ©": 5851,
"Ġcrops": 5852,
"ogle": 5853,
"éļıæĹ¶": 5854,
"æļĹ": 5855,
"ium": 5856,
"ä¹ı": 5857,
"Ġdiet": 5858,
"lies": 5859,
"ç͍æĿ¥": 5860,
"ĠEncoura": 5861,
"æĬĹ": 5862,
"apan": 5863,
"éĺ²æŃ¢": 5864,
"Wow": 5865,
"çļĦåŁºæľ¬": 5866,
"å¹³æĸ¹": 5867,
"Ġstep": 5868,
"åı¯éĿł": 5869,
"表æĺİ": 5870,
"Ġpredictions": 5871,
"Ġsympt": 5872,
"Ġdiagnoses": 5873,
"åħ¬åĽŃ": 5874,
"Ġsupply": 5875,
"Ġprevious": 5876,
"ç»ĦåIJĪ": 5877,
".,": 5878,
"çļĦè¿ĩç¨ĭ": 5879,
"æķı": 5880,
"su": 5881,
"aris": 5882,
"çķħ": 5883,
"ocol": 5884,
"æIJľç´¢": 5885,
"itle": 5886,
"éĨĴ": 5887,
"顾客": 5888,
"éĢ»è¾ij": 5889,
"éĿŀ常éĩįè¦ģ": 5890,
"ĠBi": 5891,
"å·¦åı³": 5892,
"amm": 5893,
"Ġeverything": 5894,
"æĺł": 5895,
"Ġincred": 5896,
"Ġpeace": 5897,
"èľľ": 5898,
"Ġmuseum": 5899,
"çĭ¬ç«ĭ": 5900,
"Ġcomprehensive": 5901,
"Ġrates": 5902,
"//": 5903,
"Ġrad": 5904,
"åĦ¿ç«¥": 5905,
"çī¹èī²": 5906,
"ĠPredictive": 5907,
"å¼ķåĬĽ": 5908,
"ler": 5909,
"å°¤": 5910,
"icro": 5911,
"è¡¥": 5912,
"Ġdetermine": 5913,
"çļĦåĨħ容": 5914,
"Ġcompl": 5915,
"Ġgreenhouse": 5916,
"èħIJ": 5917,
"Ġhighlight": 5918,
"Ġpartners": 5919,
"Ġdoct": 5920,
"çļĦ使ç͍": 5921,
"æŃĮæĽ²": 5922,
"æĮĩåįĹ": 5923,
"ĠAf": 5924,
"æľºæŀĦ": 5925,
"éĢĢ": 5926,
"Ġpoems": 5927,
"å¿ĥåĴĮ": 5928,
"Ġattend": 5929,
"çļĦ游": 5930,
"Ġside": 5931,
"ales": 5932,
"Ġmentioned": 5933,
"ĠAbs": 5934,
"Ġhistorical": 5935,
"Ġleft": 5936,
"以ä¸ĭåĩłä¸ª": 5937,
"åıĹæ¬¢è¿İ": 5938,
"èıľåĵģ": 5939,
"Ġremain": 5940,
"æĩ": 5941,
"Ġtours": 5942,
"łéģĵ": 5943,
"Ġerrors": 5944,
"æľºåζ": 5945,
"æ¦": 5946,
"æĤ£èĢħ": 5947,
"more": 5948,
"Ġexperts": 5949,
"çļĦçłĶç©¶": 5950,
"ç»ĵæĿŁ": 5951,
"Ġwritten": 5952,
"çłĶ": 5953,
"Ġet": 5954,
"input": 5955,
"æ°Ķä½ĵ": 5956,
"èļ": 5957,
"æĥĬ": 5958,
"Ġage": 5959,
"éĩįå¤į": 5960,
"å¼¹": 5961,
"åѤ": 5962,
"Ġsymptoms": 5963,
"Ġbelief": 5964,
"'d": 5965,
"iol": 5966,
"Ġ18": 5967,
"åħħè¶³": 5968,
"çıį": 5969,
"forcement": 5970,
"æĸĹ": 5971,
"ªèĮĦ": 5972,
"Ġ15": 5973,
"ä¸Ģ个人": 5974,
"Ġapplic": 5975,
"è´¥": 5976,
"ä½įäºİ": 5977,
"éϤäºĨ": 5978,
"=\"": 5979,
"ä¸īè§Ĵ": 5980,
"æĢĿç»´": 5981,
"åį·": 5982,
"Ġfru": 5983,
"ĠCollabor": 5984,
"Ġprim": 5985,
"Ġrequired": 5986,
"Ġwatch": 5987,
"è°ĥåij³": 5988,
"ç»ĵ论": 5989,
"ony": 5990,
"Ġguide": 5991,
"Ġmax": 5992,
"ĠCould": 5993,
"Ġadvent": 5994,
"ĠOverall": 5995,
"çļĦæĬķ": 5996,
"Ġexper": 5997,
"åĺ": 5998,
"icial": 5999,
"oster": 6000,
"çļĦé¢ľèī²": 6001,
"Ġoperations": 6002,
"éĥģ": 6003,
"Ġmoney": 6004,
"ley": 6005,
"cling": 6006,
"Ġoil": 6007,
"çļ®èĤ¤": 6008,
"Ġge": 6009,
"Ġbat": 6010,
"ĠPh": 6011,
"Ġsche": 6012,
"Ġelectric": 6013,
"vest": 6014,
"Ġchain": 6015,
"Ġcapabilities": 6016,
"ird": 6017,
"è¯ģæĺİ": 6018,
"æľĢ好": 6019,
"ivil": 6020,
"Ġdepending": 6021,
"Ġsave": 6022,
"Ġpractical": 6023,
"Ġcultures": 6024,
"缸åºĶçļĦ": 6025,
"sy": 6026,
"çļĦç²": 6027,
"Ġbehind": 6028,
"æĹ¶éĹ´åĴĮ": 6029,
"å¹ħ": 6030,
"ĠAg": 6031,
"Ġeffectiveness": 6032,
"Ad": 6033,
"ĠOf": 6034,
"Ġanything": 6035,
"å·§åħĭåĬĽ": 6036,
"Ġmist": 6037,
"Ġlanguages": 6038,
"ĠMake": 6039,
"å«": 6040,
"森": 6041,
"ĠCont": 6042,
"ĠAbsolutely": 6043,
"Ġinvestment": 6044,
"mat": 6045,
"çļĦæķħäºĭ": 6046,
"欧": 6047,
"Ġspeed": 6048,
"çļĦ温": 6049,
"Ġcities": 6050,
"åĨĻä½ľ": 6051,
"Thanks": 6052,
"Ġded": 6053,
"åĪĨéħį": 6054,
"Ġdark": 6055,
"Ġsupporting": 6056,
"å¹ķ": 6057,
"ĠKe": 6058,
"鼶": 6059,
"Ġsharing": 6060,
"Ġhouse": 6061,
"è®¤çŁ¥": 6062,
"Ġsurrounding": 6063,
"Ġreduced": 6064,
"Ġfu": 6065,
"Ġstor": 6066,
"Ġabs": 6067,
"Tom": 6068,
"cent": 6069,
"ĠEducation": 6070,
"Ġthr": 6071,
"ott": 6072,
"ĠThat": 6073,
"Ġhear": 6074,
"ung": 6075,
"Ġbeyond": 6076,
"ĠCo": 6077,
"room": 6078,
"è¯ĹæŃĮ": 6079,
"reme": 6080,
"Ġlittle": 6081,
"Ġgames": 6082,
"ä¹ĭåIJİ": 6083,
"éĥ½ä¼ļ": 6084,
"è¯ŃéŁ³": 6085,
"ç¬ij": 6086,
"çī¹å®ļ": 6087,
"第ä¸Ģ": 6088,
"Ġdepression": 6089,
"Ġinnovation": 6090,
"ĠFr": 6091,
"Ġcomputer": 6092,
"can": 6093,
"å³°": 6094,
"ç¼ĸåĨĻä¸Ģ个": 6095,
"Ġinternational": 6096,
"Ġcancer": 6097,
"åѦèĢħ": 6098,
"Ġdiscover": 6099,
"het": 6100,
"Ġcompos": 6101,
"Ġrecy": 6102,
"Ġ200": 6103,
"åIJ«æľī": 6104,
"çĹĽ": 6105,
"ç¼ĵè§£": 6106,
"Ġfrequ": 6107,
"çͳ": 6108,
"ĠMar": 6109,
"çļĦéĢīæĭ©": 6110,
"Ġunt": 6111,
"Ġregions": 6112,
"Ġopin": 6113,
"ĠGovernments": 6114,
"æ¶Ĥ": 6115,
"åĨħå¿ĥ": 6116,
"ä¸ĬæľĢ": 6117,
"ä»įçĦ¶": 6118,
"lier": 6119,
"æ³³": 6120,
"äºĴ缸": 6121,
"ĠStud": 6122,
"azon": 6123,
"Ġarch": 6124,
"Ġchem": 6125,
"çļĦèĥ½åĬĽ": 6126,
"çļĦä¸Ģ个": 6127,
"Ġap": 6128,
"Ġred": 6129,
"Ġwomen": 6130,
"Ġprote": 6131,
"Ġfinding": 6132,
"å§»": 6133,
"éĢĤå½ĵçļĦ": 6134,
"Ġforward": 6135,
"对象": 6136,
"Ġwait": 6137,
"Ġconsidered": 6138,
"dule": 6139,
"backs": 6140,
"Ġclinical": 6141,
"åħ·å¤ĩ": 6142,
"麦": 6143,
"Ġongoing": 6144,
"åĨĽ": 6145,
"Ġfar": 6146,
"åĴĮè°": 6147,
"XXX": 6148,
"Ġpolitical": 6149,
"Ġcamer": 6150,
"çļĦè¡Į为": 6151,
"æĦı大åĪ©": 6152,
"Ġapps": 6153,
"åĩıè½»": 6154,
"Ġreaders": 6155,
"å©ļå§»": 6156,
"æ°¸": 6157,
"ores": 6158,
"åħ¨éĿ¢": 6159,
"ĠAfric": 6160,
"Ġfavorite": 6161,
"Ġmill": 6162,
"Ġdang": 6163,
"ĠStates": 6164,
"åĢŁ": 6165,
"寿": 6166,
"Ġlat": 6167,
"è¿ĩåİ»": 6168,
"Ġtruly": 6169,
"åĽŀçŃĶéĹ®é¢ĺ": 6170,
"Ġcogn": 6171,
"ä»°": 6172,
"ĠJapan": 6173,
"izz": 6174,
"çļĦæĿIJ": 6175,
"xx": 6176,
"é¢ĺ缮": 6177,
"ription": 6178,
"éĤ£äºĽ": 6179,
"Ġbudget": 6180,
"Ġvast": 6181,
"éļIJç§ģ": 6182,
"Ġpolicymakers": 6183,
"è¿ĺéľĢè¦ģ": 6184,
"å¹¶æıIJä¾Ľ": 6185,
"Ġsweet": 6186,
"Ġgeneral": 6187,
"滤": 6188,
"Ġbirds": 6189,
"Ġplastic": 6190,
"Ċĉ": 6191,
"åĪº": 6192,
"mental": 6193,
"Ġinclusive": 6194,
"Ġtopics": 6195,
"Ġslow": 6196,
"ä½łèĥ½": 6197,
"è¶³å¤ŁçļĦ": 6198,
"è§Ĩè§ī": 6199,
"ww": 6200,
"Ġ使ç͍": 6201,
"æī¹": 6202,
"æ¦Ĥ念": 6203,
"é£Łç͍": 6204,
"è̳": 6205,
"cks": 6206,
"Ġfraud": 6207,
"Ġingredients": 6208,
"Ġfasc": 6209,
"åĮĹ京": 6210,
"Ġfr": 6211,
"Ġmanufacturing": 6212,
"Ġä½ľä¸º": 6213,
"Ġbeach": 6214,
"é¡¿": 6215,
"erious": 6216,
"å¤ĸè§Ĥ": 6217,
"é¢Ħéĺ²": 6218,
"æĿ¥èĩª": 6219,
"èĤĮèĤī": 6220,
"Ġdays": 6221,
"Ġassign": 6222,
"Ġadvant": 6223,
"Ġteams": 6224,
"é¢Ĺ": 6225,
"nown": 6226,
"ĠPo": 6227,
"}{": 6228,
"Ġminut": 6229,
"itions": 6230,
"Ġeasily": 6231,
"ĠBl": 6232,
"name": 6233,
"åŃ¦æł¡": 6234,
"Ġresponsibility": 6235,
"åıijæĮ¥": 6236,
"Ġsensitive": 6237,
"çŃīäºİ": 6238,
"cious": 6239,
"Ġsou": 6240,
"å±ı": 6241,
"Ġrich": 6242,
"å½ĵçĦ¶": 6243,
"man": 6244,
"Ġinterpret": 6245,
"24": 6246,
"Ġshows": 6247,
"èģĮåľº": 6248,
"Ġfall": 6249,
"è½½": 6250,
"丰å¯ĮçļĦ": 6251,
"('": 6252,
"ä¿®æĶ¹": 6253,
"æĽ´æį¢": 6254,
"Al": 6255,
"åı¯èĥ½æĺ¯": 6256,
"Ġrate": 6257,
"Ġprotecting": 6258,
"fit": 6259,
"Ġ50": 6260,
"Ġmovement": 6261,
"è§Ī": 6262,
"Ġemployee": 6263,
"Ġdisord": 6264,
"åĪĽæĦı": 6265,
"产åĵģçļĦ": 6266,
"æľĿ": 6267,
"ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ": 6268,
"Ġpred": 6269,
"Ġoffering": 6270,
"åįģåĪĨ": 6271,
"èĢĮä¸įæĺ¯": 6272,
"Thank": 6273,
"æĽ¾": 6274,
"Ġelements": 6275,
"ç²Ĵ": 6276,
"Ġcourses": 6277,
"Ġintegrated": 6278,
"ĠCar": 6279,
"agraph": 6280,
"åŁºåĽł": 6281,
"Ġinstead": 6282,
"èĦ±": 6283,
"åı¦ä¸Ģ个": 6284,
"å¯Ĩçłģ": 6285,
"Ġallowed": 6286,
"éĿ¢åĮħ": 6287,
"çķªèĮĦ": 6288,
"åĴĮåıijå±ķ": 6289,
"å°ģ": 6290,
"Ġconnection": 6291,
"åľ¨ä¸Ģ个": 6292,
"Ġuseful": 6293,
"è¯Ńåı¥": 6294,
"åĪĨå¸ĥ": 6295,
"表æ¼Ķ": 6296,
"æľīæĹ¶": 6297,
"çļĦæĹħ": 6298,
"çļĦæĢ»": 6299,
"Ġfashion": 6300,
"èĭ¦": 6301,
"è¦ģ注æĦı": 6302,
"çĶŁç´ł": 6303,
"Ġnutri": 6304,
"èĩªè¡Į": 6305,
"çļĦçĭ": 6306,
"çIJĨè§£åĴĮ": 6307,
"Ġcat": 6308,
"æľºåύåŃ¦ä¹ł": 6309,
"Ġexhib": 6310,
"åĴĮæľįåĬ¡": 6311,
"frac": 6312,
"epend": 6313,
"Ġimpacted": 6314,
"Ġut": 6315,
"æķ°ç»Ħ": 6316,
"ĠWorld": 6317,
"Ġanswer": 6318,
"erse": 6319,
"骨": 6320,
"Ġartists": 6321,
"åŃ©åŃIJçļĦ": 6322,
"ä»Ķ": 6323,
"çĻ»": 6324,
"ĠAre": 6325,
"Ġcool": 6326,
"Ġcognitive": 6327,
"åIJĦ个": 6328,
"like": 6329,
"å©´åĦ¿": 6330,
"åĪĹåĩº": 6331,
"å¹»": 6332,
"ront": 6333,
"å®¶éķ¿": 6334,
"缺ä¹ı": 6335,
"Ġcyber": 6336,
"ilt": 6337,
"Ġcapture": 6338,
"åĹ": 6339,
"åľ¨äºİ": 6340,
"Ġthreats": 6341,
"åĴĮ社ä¼ļ": 6342,
"Ġcells": 6343,
"æ¸ħåįķ": 6344,
"ĠVis": 6345,
"æİī": 6346,
"Ġhol": 6347,
"åŃIJçļĦ": 6348,
"Ch": 6349,
"èĿ": 6350,
"Ġsaid": 6351,
"Ġdream": 6352,
"unch": 6353,
"une": 6354,
"ĠDon": 6355,
"家人": 6356,
"ç±į": 6357,
"æĦŁåĴĮ": 6358,
"Ġexperienced": 6359,
"çļĦéĩįè¦ģæĢ§": 6360,
"å¼ĥ": 6361,
"ump": 6362,
"éĺIJ": 6363,
"Ġhabitat": 6364,
"è¢ĭ": 6365,
"Ġjo": 6366,
"ç®Ģæ´ģ": 6367,
"Ġbur": 6368,
"Ġvisitors": 6369,
"éĽħ": 6370,
"çļĦçŁ¥": 6371,
"Ġentire": 6372,
"讲述": 6373,
"äºĨä¸ĢäºĽ": 6374,
"åįıä½ľ": 6375,
"ĠBus": 6376,
"å°¾": 6377,
"çļĦæķĻ": 6378,
"olog": 6379,
"Ġsigns": 6380,
"Ġspeaker": 6381,
"çļĦéŁ³ä¹IJ": 6382,
"Ġnovel": 6383,
"å±ħæ°ij": 6384,
"çļĦåıĺåĮĸ": 6385,
"å°½éĩı": 6386,
"Ġspirit": 6387,
"å®Įç¾İ": 6388,
"è´·": 6389,
"å¿ħè¦ģçļĦ": 6390,
"ief": 6391,
"示ä¾ĭ": 6392,
"Ġdiv": 6393,
"æķ´æķ°": 6394,
"Ġeconomy": 6395,
"Ġethically": 6396,
"éĻĪ": 6397,
"Ġschools": 6398,
"Ġnetworks": 6399
},
"merges": [
[
"Ġ",
"t"
],
[
"Ġ",
"a"
],
[
"i",
"n"
],
[
"h",
"e"
],
[
"r",
"e"
],
[
"ï",
"¼"
],
[
"ä",
"¸"
],
[
"o",
"n"
],
[
"a",
"t"
],
[
"ç",
"ļ"
],
[
"çļ",
"Ħ"
],
[
"ï¼",
"Į"
],
[
"Ġ",
"s"
],
[
"Ġ",
"c"
],
[
"n",
"d"
],
[
"ã",
"Ģ"
],
[
"e",
"r"
],
[
"Ġt",
"he"
],
[
"e",
"s"
],
[
"e",
"n"
],
[
"o",
"r"
],
[
"a",
"n"
],
[
"Ġa",
"nd"
],
[
"in",
"g"
],
[
"Ġ",
"p"
],
[
"i",
"t"
],
[
"a",
"l"
],
[
"ãĢ",
"Ĥ"
],
[
"Ġ",
"o"
],
[
"Ġ",
"w"
],
[
"ä",
"»"
],
[
"Ġt",
"o"
],
[
"i",
"s"
],
[
"o",
"u"
],
[
"Ġ",
"m"
],
[
"ä",
"º"
],
[
"Ġ",
"in"
],
[
"Ġ",
"f"
],
[
"Ġ",
"b"
],
[
"e",
"d"
],
[
"i",
"on"
],
[
"å",
"ı"
],
[
"i",
"c"
],
[
"Ġ",
"d"
],
[
"Ġo",
"f"
],
[
"l",
"e"
],
[
"a",
"r"
],
[
"r",
"o"
],
[
"Ġ",
"Ġ"
],
[
"å",
"ħ"
],
[
"en",
"t"
],
[
"æ",
"ľ"
],
[
"Ġ",
"e"
],
[
"å",
"Ĵ"
],
[
"è",
"¿"
],
[
"ä",
"½"
],
[
"åĴ",
"Į"
],
[
"æ",
"Ī"
],
[
"å",
"®"
],
[
"å",
"Ī"
],
[
"v",
"e"
],
[
"u",
"s"
],
[
"Ġ",
"re"
],
[
"Ġ",
"h"
],
[
"Ġt",
"h"
],
[
"a",
"s"
],
[
"c",
"t"
],
[
"ç",
"Ķ"
],
[
"o",
"m"
],
[
"å",
"ľ"
],
[
"å",
"¤"
],
[
"æ",
"ĺ"
],
[
"å",
"Ĭ"
],
[
"å",
"IJ"
],
[
"ä¸",
"Ģ"
],
[
"i",
"m"
],
[
"è",
"¯"
],
[
"æ",
"ĸ"
],
[
"at",
"ion"
],
[
"l",
"o"
],
[
"ç",
"»"
],
[
"Ġb",
"e"
],
[
"ãĢ",
"ģ"
],
[
"i",
"d"
],
[
"Ġc",
"an"
],
[
"i",
"l"
],
[
"æĺ",
"¯"
],
[
"ä",
"¹"
],
[
"è",
"®"
],
[
"Ġ",
"A"
],
[
"Ġth",
"at"
],
[
"Ġ",
"T"
],
[
"ä»",
"¥"
],
[
"c",
"h"
],
[
"Ġ",
"y"
],
[
"c",
"e"
],
[
"ï¼",
"ļ"
],
[
"o",
"t"
],
[
"er",
"s"
],
[
"Ġ",
"n"
],
[
"é",
"Ģ"
],
[
"r",
"a"
],
[
"å",
"°"
],
[
"Ġ",
"g"
],
[
"Ġy",
"ou"
],
[
"å",
"Ń"
],
[
"Ġp",
"ro"
],
[
"e",
"t"
],
[
"å",
"º"
],
[
"åľ",
"¨"
],
[
"l",
"y"
],
[
"Ġ",
"is"
],
[
"ä¸",
"ª"
],
[
"Ġ",
"l"
],
[
"u",
"r"
],
[
"Ġf",
"or"
],
[
"åı",
"¯"
],
[
"é",
"ĩ"
],
[
"s",
"t"
],
[
"çļĦ",
"æ"
],
[
"u",
"t"
],
[
"Ġ",
"he"
],
[
"i",
"f"
],
[
"ĥ",
"½"
],
[
"ä",
"¼"
],
[
"Ġ",
"I"
],
[
"è",
"¡"
],
[
"i",
"r"
],
[
"it",
"h"
],
[
"å",
"¹"
],
[
"Ġa",
"re"
],
[
"i",
"g"
],
[
"Ġs",
"t"
],
[
"e",
"l"
],
[
"o",
"l"
],
[
"å",
"¸"
],
[
"u",
"l"
],
[
"æ",
"Ŀ"
],
[
"æĪ",
"ij"
],
[
"Ġ",
"on"
],
[
"è",
"¦"
],
[
"æľ",
"ī"
],
[
"æ",
"Ĺ"
],
[
"å",
"¯"
],
[
"è",
"§"
],
[
"è¦",
"ģ"
],
[
"Ġ",
"us"
],
[
"a",
"y"
],
[
"æ",
"ķ"
],
[
"ç",
"ī"
],
[
"o",
"w"
],
[
"m",
"ent"
],
[
"çĶ",
"¨"
],
[
"es",
"s"
],
[
"ä¸",
"Ń"
],
[
"ä»",
"¬"
],
[
"äº",
"º"
],
[
"å",
"ĩ"
],
[
"Ġe",
"x"
],
[
"ĠĠ",
"ĠĠ"
],
[
"å",
"Ľ"
],
[
"å",
"Į"
],
[
"å",
"¼"
],
[
"Ġc",
"on"
],
[
"s",
"e"
],
[
"è",
"ĥ½"
],
[
"ç",
"İ"
],
[
"Ġa",
"n"
],
[
"Ġw",
"ith"
],
[
"ä¸",
"º"
],
[
"at",
"e"
],
[
"i",
"v"
],
[
"a",
"m"
],
[
"Ġa",
"s"
],
[
"u",
"re"
],
[
"è¿",
"Ļ"
],
[
"å",
"Ĩ"
],
[
"ç",
"Ń"
],
[
"Ġ",
"or"
],
[
"å",
"·"
],
[
"Ġa",
"l"
],
[
"i",
"es"
],
[
"ç",
"§"
],
[
"Ġ",
"im"
],
[
"æ",
"Ģ"
],
[
"v",
"er"
],
[
"a",
"b"
],
[
"äº",
"Ĩ"
],
[
"Ġs",
"u"
],
[
"Ġd",
"e"
],
[
"g",
"e"
],
[
"t",
"h"
],
[
"åı¯",
"以"
],
[
"è",
"Ģ"
],
[
"ä¸",
"į"
],
[
"å",
"¾"
],
[
"ĠA",
"I"
],
[
"Ġ",
"en"
],
[
"é",
"Ĺ"
],
[
"æ",
"ī"
],
[
"a",
"k"
],
[
"i",
"ve"
],
[
"Ġm",
"o"
],
[
"å",
"¥"
],
[
"é",
"Ŀ"
],
[
"ç",
"Ľ"
],
[
"it",
"y"
],
[
"ä",
"¿"
],
[
"u",
"n"
],
[
"è",
"´"
],
[
"å",
"į"
],
[
"Ġ",
"it"
],
[
"Ġim",
"p"
],
[
"e",
"ct"
],
[
"æ",
"ł"
],
[
"å",
"½"
],
[
"è",
"ĩ"
],
[
"é",
"¢"
],
[
"å",
"ĵ"
],
[
"æ",
"³"
],
[
"or",
"t"
],
[
"a",
"d"
],
[
"æ",
"ŀ"
],
[
"e",
"m"
],
[
"Ġc",
"om"
],
[
"å",
"¦"
],
[
"he",
"r"
],
[
"e",
"re"
],
[
"Ġ",
"S"
],
[
"i",
"al"
],
[
"Ġ",
"C"
],
[
"ĠT",
"he"
],
[
"ç",
"IJ"
],
[
"çĶ",
"Ł"
],
[
"æ",
"Ħ"
],
[
"p",
"p"
],
[
"æ",
"Ń"
],
[
"æĸ",
"¹"
],
[
"q",
"u"
],
[
"Ġw",
"h"
],
[
"å¦",
"Ĥ"
],
[
"é",
"ľ"
],
[
"an",
"t"
],
[
"Ġ",
"le"
],
[
"Ġ",
"v"
],
[
"æ",
"ĭ"
],
[
"æ",
"Ĭ"
],
[
"us",
"t"
],
[
"æĹ",
"¶"
],
[
"çŃ",
"ī"
],
[
"å",
"ij"
],
[
"å¯",
"¹"
],
[
"t",
"er"
],
[
"l",
"d"
],
[
"è¡",
"Į"
],
[
"Ġc",
"h"
],
[
"u",
"d"
],
[
"éľ",
"Ģ"
],
[
"æ",
"°"
],
[
"æĪ",
"IJ"
],
[
"Ġ",
"|"
],
[
"a",
"c"
],
[
"a",
"in"
],
[
"i",
"z"
],
[
"æ",
"ı"
],
[
"ion",
"s"
],
[
"Ġh",
"a"
],
[
"æ",
"Ľ"
],
[
"-",
"-"
],
[
"æĿ",
"¥"
],
[
"om",
"e"
],
[
"å",
"¿"
],
[
"'",
"s"
],
[
"Ġn",
"e"
],
[
"es",
"t"
],
[
"ä",
"¾"
],
[
"u",
"m"
],
[
"åĪ",
"°"
],
[
"åľ",
"°"
],
[
"is",
"t"
],
[
"â",
"Ģ"
],
[
"çī",
"©"
],
[
"ä¸Ģ",
"个"
],
[
"l",
"p"
],
[
"æ",
"İ"
],
[
"èĩ",
"ª"
],
[
"Ġhe",
"lp"
],
[
"Ġthe",
"ir"
],
[
"æ",
"Ķ"
],
[
"ä½",
"ľ"
],
[
"ä¼",
"ļ"
],
[
"æ",
"Į"
],
[
"æĪij",
"们"
],
[
"n",
"t"
],
[
"äº",
"İ"
],
[
"åĪ",
"Ĩ"
],
[
"re",
"s"
],
[
"p",
"e"
],
[
"åĩ",
"º"
],
[
"id",
"e"
],
[
"æ",
"ĥ"
],
[
"Ġ",
"H"
],
[
"è",
"¾"
],
[
"Ġ",
"M"
],
[
"f",
"f"
],
[
"æ",
"¯"
],
[
"o",
"d"
],
[
"ic",
"al"
],
[
"Ġw",
"or"
],
[
"ä¸",
"Ĭ"
],
[
"a",
"re"
],
[
"æĽ",
"´"
],
[
"Ġyou",
"r"
],
[
"ä¸",
"ĭ"
],
[
"è",
"µ"
],
[
"ation",
"s"
],
[
"æķ",
"°"
],
[
"Ġt",
"e"
],
[
"å",
"İ"
],
[
"çIJ",
"Ĩ"
],
[
"ĠT",
"h"
],
[
"è¿",
"ĩ"
],
[
"å¹",
"¶"
],
[
"d",
"u"
],
[
"éĿ",
"¢"
],
[
"Ġa",
"d"
],
[
"il",
"l"
],
[
"æ",
"µ"
],
[
"å¥",
"½"
],
[
"o",
"c"
],
[
"a",
"ct"
],
[
"éľĢ",
"è¦ģ"
],
[
"ä»",
"ĸ"
],
[
"å",
"±"
],
[
"Ġ",
"r"
],
[
"Ġmo",
"re"
],
[
"åŃ",
"¦"
],
[
"ç",
"®"
],
[
"ig",
"h"
],
[
"äº",
"Ľ"
],
[
"Ġ",
"B"
],
[
"åĬ",
"¨"
],
[
"åĵ",
"ģ"
],
[
"è",
"ī"
],
[
"p",
"le"
],
[
"Ġin",
"c"
],
[
"åIJ",
"Į"
],
[
"Ġex",
"p"
],
[
"ou",
"ld"
],
[
"ä½",
"ł"
],
[
"æ",
"į"
],
[
"æı",
"IJ"
],
[
"å¤",
"§"
],
[
"çİ",
"°"
],
[
"p",
"t"
],
[
"Ġ",
"P"
],
[
"al",
"l"
],
[
"åĬ",
"ł"
],
[
"ç§",
"į"
],
[
"Ġs",
"e"
],
[
"åĬ",
"Ľ"
],
[
"ou",
"t"
],
[
"Ġha",
"ve"
],
[
"ç",
"º"
],
[
"ä½",
"ĵ"
],
[
"Ġpro",
"v"
],
[
"åĮ",
"ĸ"
],
[
"å¤",
"ļ"
],
[
"å®",
"ļ"
],
[
"Ġus",
"ed"
],
[
"éĢ",
"ļ"
],
[
"c",
"c"
],
[
"è¿",
"Ľ"
],
[
"æ",
"´"
],
[
"Ġs",
"h"
],
[
"Ġa",
"b"
],
[
"o",
"s"
],
[
"Ġre",
"s"
],
[
"ĠTh",
"is"
],
[
"ç",
"¨"
],
[
"æĢ",
"§"
],
[
"a",
"ge"
],
[
"r",
"i"
],
[
"æ",
"¸"
],
[
"ab",
"le"
],
[
"åŃ",
"IJ"
],
[
"Ġb",
"y"
],
[
"åı",
"ij"
],
[
"éĩ",
"ı"
],
[
"åº",
"Ķ"
],
[
"Ġ",
"lo"
],
[
"ä½",
"¿"
],
[
"åħ",
"¶"
],
[
"é",
"«"
],
[
"é",
"Ļ"
],
[
"é«",
"ĺ"
],
[
"åº",
"¦"
],
[
"è§",
"£"
],
[
"é",
"£"
],
[
"å°",
"Ĩ"
],
[
"æ³",
"ķ"
],
[
"a",
"nd"
],
[
"ä¿",
"Ŀ"
],
[
"an",
"s"
],
[
"f",
"or"
],
[
"ro",
"m"
],
[
"re",
"at"
],
[
"Ġp",
"l"
],
[
"çļĦ",
"ç"
],
[
"å¸",
"¸"
],
[
"è",
"½"
],
[
"Ġw",
"e"
],
[
"è¡",
"¨"
],
[
"ak",
"e"
],
[
"æĪ",
"ĸ"
],
[
"é¢",
"ĺ"
],
[
"å",
"Ł"
],
[
"Ġm",
"e"
],
[
"æĸ",
"ĩ"
],
[
"t",
"her"
],
[
"k",
"e"
],
[
"å®",
"¶"
],
[
"åIJ",
"Ī"
],
[
"æľ",
"Ģ"
],
[
"in",
"e"
],
[
"Ġs",
"ome"
],
[
"ç",
"±"
],
[
"éĩ",
"į"
],
[
"æŀ",
"ľ"
],
[
"Ġ",
"W"
],
[
"Ġ",
"E"
],
[
"é",
"ĺ"
],
[
"ou",
"r"
],
[
"r",
"ou"
],
[
"ç",
"Ĥ"
],
[
"æ",
"±"
],
[
"åħ",
"³"
],
[
"Ġin",
"t"
],
[
"an",
"ce"
],
[
"ä¹",
"Ł"
],
[
"é",
"ģ"
],
[
"ĠĠ",
"Ġ"
],
[
"å®",
"ĥ"
],
[
"a",
"g"
],
[
"æ",
"¬"
],
[
"0",
"0"
],
[
"è",
"°"
],
[
"ul",
"t"
],
[
"y",
"st"
],
[
"éĹ",
"´"
],
[
"ç",
"³"
],
[
"Ġt",
"r"
],
[
"p",
"l"
],
[
"ar",
"t"
],
[
"æĦ",
"Ł"
],
[
"æ",
"Ĥ"
],
[
"at",
"a"
],
[
"Ġ",
"F"
],
[
"for",
"m"
],
[
"è®",
"¡"
],
[
"Ġf",
"rom"
],
[
"Ġ",
"D"
],
[
"éĹ",
"®"
],
[
"igh",
"t"
],
[
"c",
"es"
],
[
"æį",
"®"
],
[
"lo",
"p"
],
[
"ä¹",
"ĭ"
],
[
"Ġf",
"e"
],
[
"å",
"ģ"
],
[
"ve",
"lop"
],
[
"Ġ",
"1"
],
[
"åĽ",
"ł"
],
[
"k",
"s"
],
[
"æ",
"²"
],
[
"Ġ",
"u"
],
[
"å°",
"ı"
],
[
"yst",
"em"
],
[
"Ġd",
"is"
],
[
"Ġ",
"R"
],
[
"g",
"y"
],
[
"å·",
"¥"
],
[
"ç¨",
"ĭ"
],
[
"å",
"¢"
],
[
"en",
"ce"
],
[
"è",
"Ĥ"
],
[
"ç",
"¡"
],
[
"Ġt",
"ra"
],
[
"å",
"»"
],
[
"åħ",
"¥"
],
[
"ig",
"n"
],
[
"al",
"th"
],
[
"Ġsu",
"ch"
],
[
"a",
"ch"
],
[
"æ",
"Ļ"
],
[
"ar",
"n"
],
[
"Ġd",
"ata"
],
[
"è",
"¶"
],
[
"å®",
"ŀ"
],
[
"s",
"o"
],
[
"Ġde",
"velop"
],
[
"ç",
"¤"
],
[
"Ġa",
"cc"
],
[
"as",
"t"
],
[
"èĢ",
"Į"
],
[
"Ġ",
"\""
],
[
"Ġo",
"ther"
],
[
"å»",
"º"
],
[
"Ġe",
"ff"
],
[
"ç",
"«"
],
[
"Ġm",
"an"
],
[
"åħ",
"¬"
],
[
"å",
"Ģ"
],
[
"ç",
"Ħ"
],
[
"m",
"s"
],
[
"å¼",
"ı"
],
[
"èī",
"²"
],
[
"å¾",
"Ĺ"
],
[
"if",
"ic"
],
[
"Ġ",
"j"
],
[
"Ġ",
"ro"
],
[
"Ġh",
"as"
],
[
"ch",
"n"
],
[
"o",
"lo"
],
[
"åĪ",
"¶"
],
[
"è",
"Ĭ"
],
[
"使",
"ç͍"
],
[
"ou",
"s"
],
[
"u",
"al"
],
[
"Ġa",
"t"
],
[
"Ġe",
"m"
],
[
"el",
"l"
],
[
"Ġs",
"ystem"
],
[
"Ġhe",
"alth"
],
[
"it",
"ies"
],
[
"Ġex",
"am"
],
[
"i",
"b"
],
[
"é",
"Ķ"
],
[
"Ġab",
"out"
],
[
"äº",
"§"
],
[
"åIJ",
"İ"
],
[
"æĦ",
"ı"
],
[
"ç±",
"»"
],
[
"Ġp",
"re"
],
[
"æĤ",
"¨"
],
[
"Ġal",
"so"
],
[
"ent",
"s"
],
[
"Ġin",
"d"
],
[
"in",
"d"
],
[
"éĢ",
"Ĥ"
],
[
"Ġte",
"chn"
],
[
"res",
"s"
],
[
"æĥ",
"ħ"
],
[
"éĹ®",
"é¢ĺ"
],
[
"Ġus",
"e"
],
[
"ï¼",
"Ł"
],
[
"Ġinc",
"l"
],
[
"Ġs",
"pe"
],
[
"ic",
"h"
],
[
"p",
"s"
],
[
"æľ",
"º"
],
[
"Ġthe",
"y"
],
[
"i",
"e"
],
[
"Ġh",
"ow"
],
[
"Ġwor",
"k"
],
[
"ä¸",
"ļ"
],
[
"ç",
"´"
],
[
"Ġimp",
"ro"
],
[
"Ġle",
"arn"
],
[
"æĸ",
"°"
],
[
"çĤ",
"¹"
],
[
"Ġcon",
"t"
],
[
"ar",
"d"
],
[
"çĦ",
"¶"
],
[
"æľ",
"¬"
],
[
"ç³",
"»"
],
[
"ç¡",
"®"
],
[
"è®",
"¾"
],
[
"åħ",
"·"
],
[
"éĢ",
"ī"
],
[
"èĢ",
"ħ"
],
[
"é",
"ħ"
],
[
"g",
"h"
],
[
"_",
"_"
],
[
"Ġn",
"ot"
],
[
"ç",
"ľ"
],
[
"çĽ",
"¸"
],
[
"Ġprov",
"ide"
],
[
"å",
"ī"
],
[
"ion",
"al"
],
[
"Ġen",
"s"
],
[
"ä¸",
"İ"
],
[
"è´",
"¨"
],
[
"ent",
"ial"
],
[
"ç»",
"ı"
],
[
"å¿",
"ĥ"
],
[
"an",
"g"
],
[
"æŃ",
"¤"
],
[
"e",
"nd"
],
[
"Ġp",
"o"
],
[
"è¿Ľ",
"è¡Į"
],
[
"ic",
"e"
],
[
"Ġ",
"-"
],
[
"Ġw",
"ay"
],
[
"å·",
"±"
],
[
"Ġ",
"2"
],
[
"im",
"e"
],
[
"ç",
"½"
],
[
"èĩª",
"å·±"
],
[
"Ġ",
"un"
],
[
"b",
"ot"
],
[
"Ġincl",
"ud"
],
[
"at",
"ed"
],
[
"æ°",
"´"
],
[
"é",
"ķ"
],
[
"æĮ",
"ģ"
],
[
"ä»",
"£"
],
[
"é",
"¡"
],
[
"æī",
"Ģ"
],
[
"ç",
"Ŀ"
],
[
"pp",
"ort"
],
[
"o",
"od"
],
[
"i",
"ke"
],
[
"r",
"u"
],
[
"Ġcom",
"m"
],
[
"Ġ",
"L"
],
[
"ä¿",
"¡"
],
[
"Ġ",
"G"
],
[
"ç",
"Ł"
],
[
"çĶ",
"µ"
],
[
"Ġw",
"as"
],
[
"lo",
"w"
],
[
"er",
"v"
],
[
"åĮ",
"ħ"
],
[
"ĠĠĠĠ",
"ĠĠĠĠ"
],
[
"Ġw",
"he"
],
[
"d",
"it"
],
[
"Ġwh",
"ich"
],
[
"Ġcom",
"p"
],
[
"é",
"ª"
],
[
"o",
"re"
],
[
"ç",
"¾"
],
[
"Ġ",
"="
],
[
"çī",
"¹"
],
[
"if",
"f"
],
[
"er",
"t"
],
[
"æ",
"ģ"
],
[
"r",
"it"
],
[
"Ġre",
"c"
],
[
"åĨ",
"ħ"
],
[
"æĺ",
"İ"
],
[
"or",
"s"
],
[
"Ġp",
"at"
],
[
"--",
"--"
],
[
"æ",
"Ł"
],
[
"Ġa",
"pp"
],
[
"n",
"s"
],
[
"åĬ",
"¡"
],
[
"al",
"y"
],
[
"a",
"ce"
],
[
"æ´",
"»"
],
[
"ä¾",
"Ľ"
],
[
"a",
"v"
],
[
"ä¸",
"»"
],
[
"Ġp",
"ers"
],
[
"ç",
"ĥ"
],
[
"è¯",
"¥"
],
[
"Ġm",
"y"
],
[
"ç",
"©"
],
[
"er",
"i"
],
[
"è®",
"©"
],
[
"æĬ",
"Ģ"
],
[
"éķ",
"¿"
],
[
"ac",
"k"
],
[
"Ġ",
"N"
],
[
"Ġd",
"iff"
],
[
"Ġth",
"is"
],
[
"å",
"Ŀ"
],
[
"Ġens",
"ure"
],
[
"å½",
"ĵ"
],
[
"Ġo",
"ut"
],
[
"Ġc",
"l"
],
[
"Ġ",
"k"
],
[
"é",
"¦"
],
[
"ou",
"nt"
],
[
"çİ",
"¯"
],
[
"åĬ",
"©"
],
[
"Ġtechn",
"olo"
],
[
"Ġthe",
"se"
],
[
"f",
"ul"
],
[
"é",
"ļ"
],
[
"æ",
"·"
],
[
"ä¸Ģ",
"äºĽ"
],
[
"Ġs",
"oc"
],
[
"å¼",
"Ģ"
],
[
"å¤",
"©"
],
[
"Ġe",
"v"
],
[
"Ġre",
"du"
],
[
"Ġthe",
"m"
],
[
"Ġ",
"("
],
[
"é",
"ĥ½"
],
[
"æĪ",
"·"
],
[
"è",
"·"
],
[
"åľ",
"º"
],
[
"æ°",
"Ķ"
],
[
"Ġ",
"Y"
],
[
"è¯",
"Ń"
],
[
"éĢļ",
"è¿ĩ"
],
[
"å±",
"ķ"
],
[
"Ġc",
"o"
],
[
"å½",
"±"
],
[
"ç",
"¬"
],
[
"Ġan",
"aly"
],
[
"æ¯",
"Ķ"
],
[
"åħ",
"¨"
],
[
"Ġimpro",
"ve"
],
[
"ç»",
"ĵ"
],
[
"å¹",
"´"
],
[
"ç",
"ķ"
],
[
"çĿ",
"Ģ"
],
[
"Ġh",
"um"
],
[
"Ġ",
"qu"
],
[
"ç®",
"Ĺ"
],
[
"Ġ",
"O"
],
[
"é£",
"Ł"
],
[
"il",
"ity"
],
[
"Ġsystem",
"s"
],
[
"åı",
"ĺ"
],
[
"a",
"il"
],
[
"ç",
"¼"
],
[
"ç",
"ł"
],
[
"è¿Ļ",
"个"
],
[
"æıIJ",
"ä¾Ľ"
],
[
"as",
"e"
],
[
"å",
"ŀ"
],
[
"ment",
"s"
],
[
"Ġp",
"ot"
],
[
"Ġan",
"y"
],
[
"ä½",
"Ĩ"
],
[
"Ġcon",
"s"
],
[
"ĠI",
"t"
],
[
"æł",
"¼"
],
[
"Ġa",
"r"
],
[
"æľ",
"¯"
],
[
"éĿ",
"ŀ"
],
[
"Ġd",
"o"
],
[
"Ġm",
"ay"
],
[
"æĭ",
"©"
],
[
"u",
"e"
],
[
"éĢī",
"æĭ©"
],
[
"r",
"y"
],
[
"é",
"ĥ"
],
[
"Ġl",
"ike"
],
[
"on",
"g"
],
[
"è",
"ģ"
],
[
"`",
"`"
],
[
"i",
"le"
],
[
"æ±",
"Ĥ"
],
[
"Ġne",
"w"
],
[
"i",
"ent"
],
[
"Ġimp",
"act"
],
[
"è¿",
"ĺ"
],
[
"æ³",
"¨"
],
[
"ä¹",
"Ī"
],
[
"çĽ",
"®"
],
[
"âĢ",
"ľ"
],
[
"âĢ",
"Ŀ"
],
[
"e",
"f"
],
[
"ä¾",
"ĭ"
],
[
"Ġpot",
"ential"
],
[
"o",
"k"
],
[
"åı¯",
"èĥ½"
],
[
"Ġtr",
"ans"
],
[
"Ġa",
"ct"
],
[
"ï¼",
"ī"
],
[
"Ġspe",
"c"
],
[
"æ",
"¶"
],
[
"Ġw",
"ill"
],
[
"äº",
"¤"
],
[
"iz",
"e"
],
[
"ç¾",
"İ"
],
[
"å¸",
"Ĥ"
],
[
"Ġst",
"ud"
],
[
"p",
"on"
],
[
"è",
"º"
],
[
"ä¸į",
"åIJĮ"
],
[
"on",
"e"
],
[
"å¾",
"Ī"
],
[
"åı",
"Ĭ"
],
[
"å¦Ĥ",
"æŀľ"
],
[
"çIJ",
"ĥ"
],
[
"an",
"ge"
],
[
"Ġne",
"ed"
],
[
"å¤",
"ĸ"
],
[
"et",
"y"
],
[
"ak",
"ing"
],
[
"è¯",
"·"
],
[
"at",
"er"
],
[
"Ġpers",
"on"
],
[
"id",
"ent"
],
[
"Ġs",
"o"
],
[
"Ġm",
"ake"
],
[
"å¹",
"³"
],
[
"å¤",
"Ł"
],
[
"èº",
"«"
],
[
"ï¼",
"Ī"
],
[
"Ġin",
"form"
],
[
"æ",
"¡"
],
[
"äº",
"ĭ"
],
[
"åı",
"Ĺ"
],
[
"as",
"ed"
],
[
"il",
"d"
],
[
"Ġof",
"f"
],
[
"Ġthe",
"re"
],
[
"c",
"is"
],
[
"è",
"¢"
],
[
"éĥ",
"¨"
],
[
"æ¯",
"ı"
],
[
"ra",
"ct"
],
[
"as",
"s"
],
[
"Ġlearn",
"ing"
],
[
"å",
"ĸ"
],
[
"å½",
"¢"
],
[
"i",
"re"
],
[
"ä»",
"İ"
],
[
"bot",
"s"
],
[
"è",
"Ļ"
],
[
"å¸",
"®"
],
[
"Ġd",
"es"
],
[
"ĠI",
"n"
],
[
"c",
"ess"
],
[
"Ġp",
"e"
],
[
"if",
"y"
],
[
"Ġwh",
"o"
],
[
"ä¹",
"ł"
],
[
"æľ",
"Ł"
],
[
"Ġexp",
"eri"
],
[
"é",
"Ĥ"
],
[
"Ġs",
"c"
],
[
"e",
"p"
],
[
"ä½",
"ķ"
],
[
"Ġt",
"ime"
],
[
"éĿŀ",
"常"
],
[
"æĭ",
"¬"
],
[
"å",
"ķ"
],
[
"以",
"ä¸ĭ"
],
[
"éģ",
"ĵ"
],
[
"Ġcomm",
"un"
],
[
"Ġc",
"ould"
],
[
"a",
"p"
],
[
"è",
"IJ"
],
[
"è°",
"ĥ"
],
[
"l",
"ic"
],
[
"du",
"ct"
],
[
"Ġit",
"s"
],
[
"c",
"y"
],
[
"è¯",
"´"
],
[
"Ġm",
"ed"
],
[
"Ġc",
"ol"
],
[
"ul",
"ar"
],
[
"éĩį",
"è¦ģ"
],
[
"Ġs",
"p"
],
[
"åĪ",
"©"
],
[
"èµ",
"·"
],
[
"Ġprov",
"id"
],
[
"ic",
"es"
],
[
"å",
"Ļ"
],
[
"æĸ",
"Ļ"
],
[
"Ġimp",
"ort"
],
[
"ur",
"al"
],
[
"åŃ",
"Ĺ"
],
[
"Ġu",
"nd"
],
[
"in",
"t"
],
[
"Ġo",
"ver"
],
[
"åı",
"¸"
],
[
"æł",
"¹"
],
[
"é",
"¥"
],
[
"pl",
"es"
],
[
"ä»ĸ",
"们"
],
[
"g",
"ra"
],
[
"ur",
"ing"
],
[
"n",
"ow"
],
[
"åį",
"ķ"
],
[
"è¿Ļ",
"äºĽ"
],
[
"åī",
"į"
],
[
"å®",
"ī"
],
[
"Ġp",
"r"
],
[
"åĮħ",
"æĭ¬"
],
[
"ç»",
"Ļ"
],
[
"T",
"he"
],
[
"ä½",
"į"
],
[
"å",
"§"
],
[
"ç´",
"ł"
],
[
"åij",
"ĺ"
],
[
"Ġ",
"ident"
],
[
"åŀ",
"ĭ"
],
[
"Ġad",
"d"
],
[
"å¼",
"º"
],
[
"æĺ¯",
"ä¸Ģ"
],
[
"i",
"p"
],
[
"g",
"or"
],
[
"Ġsu",
"pport"
],
[
"n",
"e"
],
[
"Ġdiff",
"ere"
],
[
"åħ",
"ĥ"
],
[
"Ġas",
"s"
],
[
"åĨ",
"³"
],
[
"é",
"Ľ"
],
[
"åIJ",
"į"
],
[
"Ġg",
"o"
],
[
"Ġtechnolo",
"gy"
],
[
"æĢ",
"»"
],
[
"è®",
"®"
],
[
"Ġin",
"ter"
],
[
"Ġin",
"v"
],
[
"Ġo",
"ur"
],
[
"æķ",
"Ī"
],
[
"ust",
"om"
],
[
"Ġre",
"l"
],
[
"if",
"e"
],
[
"åĻ",
"¨"
],
[
"ing",
"s"
],
[
"ä»",
"·"
],
[
"Ġp",
"art"
],
[
"è¢",
"«"
],
[
"æī",
"ĭ"
],
[
"ar",
"y"
],
[
"Ġres",
"pon"
],
[
"Ċ",
"ĠĠĠ"
],
[
"好",
"çļĦ"
],
[
"at",
"ive"
],
[
"帮",
"åĬ©"
],
[
"ç»",
"Ł"
],
[
"æĶ",
"¾"
],
[
"ĠH",
"ere"
],
[
"ç",
"ģ"
],
[
"Ġb",
"ut"
],
[
"æģ",
"¯"
],
[
"æŃ",
"£"
],
[
"ar",
"k"
],
[
"åħ¬",
"åı¸"
],
[
"or",
"y"
],
[
"å¢",
"ĥ"
],
[
"le",
"ct"
],
[
"é",
"Ł"
],
[
"æĥ",
"³"
],
[
"é£",
"İ"
],
[
"at",
"ing"
],
[
"Ġa",
"m"
],
[
"it",
"s"
],
[
"æ",
"»"
],
[
"gor",
"ith"
],
[
"åĵ",
"į"
],
[
"ure",
"s"
],
[
"Ġeff",
"ect"
],
[
"Ġsh",
"ould"
],
[
"Ġp",
"er"
],
[
"è",
"±"
],
[
"ç",
"²"
],
[
"ic",
"t"
],
[
"Ġal",
"gorith"
],
[
"u",
"c"
],
[
"rou",
"gh"
],
[
"ä»",
"»"
],
[
"ä»",
"¶"
],
[
"Ġbe",
"t"
],
[
"i",
"a"
],
[
"Ġanaly",
"z"
],
[
"æł¹",
"æį®"
],
[
"iz",
"ed"
],
[
"æµ",
"ģ"
],
[
"è§",
"Ĥ"
],
[
"è",
"£"
],
[
"æł",
"ĩ"
],
[
"ir",
"on"
],
[
"Ġc",
"ustom"
],
[
"Ġre",
"g"
],
[
"Ġperson",
"al"
],
[
"èĥ½",
"å¤Ł"
],
[
"ic",
"s"
],
[
"iv",
"id"
],
[
"ç",
"Ī"
],
[
"èµ",
"Ħ"
],
[
"æŃ",
"¥"
],
[
"å®",
"¹"
],
[
"åĪ",
"Ľ"
],
[
"è",
"Ī"
],
[
"ä¹",
"IJ"
],
[
"å¯",
"¼"
],
[
"g",
"an"
],
[
"èĬ",
"Ĥ"
],
[
"Ġal",
"l"
],
[
"en",
"s"
],
[
"am",
"e"
],
[
"n",
"ess"
],
[
"Ġu",
"p"
],
[
"Ġ",
"U"
],
[
"èĢ",
"ĥ"
],
[
"el",
"f"
],
[
"åĢ",
"¼"
],
[
"å°",
"ij"
],
[
"æľ",
"į"
],
[
"ar",
"i"
],
[
"th",
"ical"
],
[
"v",
"iron"
],
[
"è",
"ĥ"
],
[
"or",
"d"
],
[
"Ġs",
"ign"
],
[
"éĩ",
"Į"
],
[
"ou",
"nd"
],
[
"o",
"ple"
],
[
"åŁ",
"º"
],
[
"Ġinform",
"ation"
],
[
"Ġident",
"ify"
],
[
"åĽ",
"ŀ"
],
[
"Ġc",
"re"
],
[
"éŁ",
"³"
],
[
"ib",
"le"
],
[
"u",
"b"
],
[
"è¿",
"IJ"
],
[
"Ġle",
"ad"
],
[
"æ¸",
"¸"
],
[
"æ¬",
"¡"
],
[
"åĨ",
"Ļ"
],
[
"éĤ",
"£"
],
[
"g",
"et"
],
[
"è",
"į"
],
[
"Ġexam",
"ple"
],
[
"ä¼",
"ĺ"
],
[
"å½±",
"åĵį"
],
[
"is",
"h"
],
[
"x",
"t"
],
[
"æ",
"º"
],
[
"éª",
"Į"
],
[
"o",
"b"
],
[
"å®",
"¢"
],
[
"å¤",
"ĩ"
],
[
"åģ",
"¥"
],
[
"è½",
"¦"
],
[
"ç¤",
"¾"
],
[
"ivid",
"ual"
],
[
"ere",
"d"
],
[
"l",
"es"
],
[
"Ġen",
"viron"
],
[
"Ġpe",
"ople"
],
[
"æĺ",
"Ł"
],
[
"ç",
"ĸ"
],
[
"ç",
"ĭ"
],
[
"Ġd",
"et"
],
[
"æĹ",
"ł"
],
[
"Ġ",
"if"
],
[
"o",
"se"
],
[
"it",
"e"
],
[
"å¢",
"ŀ"
],
[
"é",
"Ĵ"
],
[
"åIJĮ",
"æĹ¶"
],
[
"è¿",
"°"
],
[
"æĸ¹",
"å¼ı"
],
[
"åĽ",
"½"
],
[
"é",
"»"
],
[
"å¤",
"Ħ"
],
[
"Ġexam",
"ples"
],
[
"æ",
"®"
],
[
"Ġint",
"o"
],
[
"æĮ",
"ĩ"
],
[
"Ġhum",
"an"
],
[
"åIJ",
"ij"
],
[
"ç¤",
"º"
],
[
"æķ°",
"æį®"
],
[
"Ġ",
"3"
],
[
"Ġ",
"J"
],
[
"è",
"ı"
],
[
"çݯ",
"å¢ĥ"
],
[
"al",
"s"
],
[
"ers",
"t"
],
[
"Ġe",
"thical"
],
[
"ç»",
"Ħ"
],
[
"ä¼",
"ł"
],
[
"Ġdiffere",
"nt"
],
[
"Ġk",
"now"
],
[
"åº",
"ı"
],
[
"Ġind",
"ividual"
],
[
"æıIJ",
"é«ĺ"
],
[
"rou",
"nd"
],
[
"å°",
"±"
],
[
"åı",
"ĸ"
],
[
"åŃ",
"ĺ"
],
[
"ä¸",
"¤"
],
[
"çŁ",
"¥"
],
[
"our",
"ces"
],
[
"c",
"k"
],
[
"å",
"£"
],
[
"in",
"es"
],
[
"è¾",
"¾"
],
[
"Ġman",
"y"
],
[
"æķ",
"´"
],
[
"æł",
"·"
],
[
"dit",
"ional"
],
[
"om",
"m"
],
[
"çĶ",
"±"
],
[
"éĢ",
"ł"
],
[
"å®ĥ",
"们"
],
[
"u",
"es"
],
[
"Ġm",
"ent"
],
[
"Ġimport",
"ant"
],
[
"Ġo",
"pt"
],
[
"Ġlo",
"c"
],
[
"p",
"h"
],
[
"Ġpro",
"cess"
],
[
"Ġalgorith",
"ms"
],
[
"设",
"计"
],
[
"Ġsoc",
"ial"
],
[
"ver",
"y"
],
[
"åĪ",
"Ļ"
],
[
"ä¾ĭ",
"å¦Ĥ"
],
[
"è®",
"¤"
],
[
"Ġa",
"ut"
],
[
"Ġs",
"erv"
],
[
"g",
"g"
],
[
"产",
"åĵģ"
],
[
"è§",
"Ħ"
],
[
"çľ",
"ĭ"
],
[
"ve",
"l"
],
[
"æĸ¹",
"æ³ķ"
],
[
"Ġb",
"en"
],
[
"åĽł",
"æŃ¤"
],
[
"c",
"are"
],
[
"p",
"er"
],
[
"åĬ",
"Ł"
],
[
"建",
"è®®"
],
[
"Ġp",
"os"
],
[
"æ",
"¤"
],
[
"w",
"e"
],
[
"åĮ",
"º"
],
[
"i",
"qu"
],
[
"Ġre",
"al"
],
[
"æĹ",
"¥"
],
[
"Ġredu",
"ce"
],
[
"a",
"f"
],
[
"ang",
"u"
],
[
"Ġs",
"k"
],
[
"Ġ",
"ed"
],
[
"erst",
"and"
],
[
"åĨ",
"µ"
],
[
"m",
"ot"
],
[
"åħ",
"Ī"
],
[
"ç",
"¥"
],
[
"åºĶ",
"该"
],
[
"Ġth",
"rough"
],
[
"Ġcon",
"c"
],
[
"åıij",
"å±ķ"
],
[
"è¯",
"ķ"
],
[
"æ¡",
"Ī"
],
[
"Ġenviron",
"ment"
],
[
"åı",
"£"
],
[
"Ġad",
"v"
],
[
"åĪ",
"«"
],
[
"Ġben",
"ef"
],
[
"æ¸",
"ħ"
],
[
"åij",
"³"
],
[
"åħ",
"ī"
],
[
"Ġdevelop",
"ment"
],
[
"en",
"g"
],
[
"å¦Ĥ",
"ä½ķ"
],
[
"ç®",
"¡"
],
[
"iv",
"ers"
],
[
"åIJ",
"Ħ"
],
[
"Ġr",
"is"
],
[
"ro",
"w"
],
[
"er",
"gy"
],
[
"计",
"ç®Ĺ"
],
[
"ä¿¡",
"æģ¯"
],
[
"Ġpro",
"duct"
],
[
"è¾",
"ĥ"
],
[
"è®",
"º"
],
[
"èĩªå·±",
"çļĦ"
],
[
"æĬ",
"¤"
],
[
"åı",
"į"
],
[
"åħ¶",
"ä»ĸ"
],
[
"åĪ",
"Ĺ"
],
[
"ç»",
"Ĩ"
],
[
"ç©",
"º"
],
[
"Ġg",
"reat"
],
[
"e",
"ar"
],
[
"æº",
"IJ"
],
[
"j",
"ect"
],
[
"çĶŁ",
"æ´»"
],
[
"ä¸Ń",
"çļĦ"
],
[
"Ġund",
"erstand"
],
[
"è",
"ĭ"
],
[
"h",
"at"
],
[
"Ġpro",
"gra"
],
[
"ç",
"Ĭ"
],
[
"éĩ",
"ij"
],
[
"Ġinclud",
"ing"
],
[
"Ġacc",
"ess"
],
[
"ĠĠĠĠ",
"ĠĠĠ"
],
[
"è¯",
"Ĩ"
],
[
"ç",
"¦"
],
[
"o",
"g"
],
[
"è£",
"ħ"
],
[
"Ġar",
"t"
],
[
"Ġw",
"rit"
],
[
"Ġinc",
"re"
],
[
"Ġp",
"h"
],
[
"æĸ¹",
"éĿ¢"
],
[
"Ġp",
"ract"
],
[
"Ġus",
"ing"
],
[
"é¡",
"¹"
],
[
"æİ",
"¥"
],
[
"Ġway",
"s"
],
[
"Ġl",
"angu"
],
[
"æĶ",
"¯"
],
[
"Ġch",
"all"
],
[
"åİ",
"»"
],
[
"__",
"__"
],
[
"im",
"ate"
],
[
"æĸ",
"Ń"
],
[
"è",
"¨"
],
[
"Ġw",
"ell"
],
[
"l",
"l"
],
[
"Ġp",
"ol"
],
[
"æĢ",
"ģ"
],
[
"Ġ",
"ra"
],
[
"C",
"an"
],
[
"åİ",
"Ł"
],
[
"b",
"er"
],
[
"è¨",
"Ģ"
],
[
"ç«",
"ĭ"
],
[
"Ġg",
"en"
],
[
"éħ",
"į"
],
[
"æ·",
"±"
],
[
"t",
"e"
],
[
"ä¸",
"ī"
],
[
"ç§",
"ij"
],
[
"ĠF",
"or"
],
[
"çº",
"¿"
],
[
"ç",
"ħ"
],
[
"æ",
"¼"
],
[
"åķ",
"Ĩ"
],
[
"æĿ",
"IJ"
],
[
"Ġsign",
"ific"
],
[
"Ġg",
"u"
],
[
"Ġde",
"cis"
],
[
"Ġtra",
"in"
],
[
"Ġa",
"g"
],
[
"Ġc",
"reat"
],
[
"å®",
"Į"
],
[
"æĹ¶",
"éĹ´"
],
[
"Ġon",
"e"
],
[
"è",
"Ħ"
],
[
"Ġn",
"at"
],
[
"åѦ",
"ä¹ł"
],
[
"çļĦæ",
"ķ"
],
[
"c",
"ed"
],
[
"Ġwhe",
"n"
],
[
"Ġb",
"i"
],
[
"è",
"İ"
],
[
"æĽ´",
"åĬł"
],
[
"iv",
"es"
],
[
"p",
"ort"
],
[
"å·¥",
"ä½ľ"
],
[
"v",
"ing"
],
[
"Ġbe",
"en"
],
[
"æĻ",
"º"
],
[
"Ġl",
"ife"
],
[
"å¼",
"ķ"
],
[
"ar",
"m"
],
[
"çİ",
"ĩ"
],
[
"ç͍",
"æĪ·"
],
[
"ä¹",
"ī"
],
[
"ä»",
"½"
],
[
"è¯",
"Ŀ"
],
[
"in",
"ess"
],
[
"c",
"om"
],
[
"åº",
"·"
],
[
"åĩ",
"ı"
],
[
"ä»",
"Ģ"
],
[
"è¾",
"ĵ"
],
[
"Ġv",
"ari"
],
[
"c",
"on"
],
[
"Ġmo",
"d"
],
[
"ä»Ģ",
"ä¹Ī"
],
[
"Ġen",
"ergy"
],
[
"æĬĢ",
"æľ¯"
],
[
"ert",
"ain"
],
[
"m",
"m"
],
[
"ver",
"all"
],
[
"åĪ",
"Ĵ"
],
[
"Ġro",
"bots"
],
[
"Ġor",
"gan"
],
[
"æİ",
"¨"
],
[
"ant",
"s"
],
[
"åĩ",
"Ĩ"
],
[
"d",
"s"
],
[
"æŀ",
"ģ"
],
[
"ç",
"Ļ"
],
[
"Ġre",
"qu"
],
[
"Ġ",
"ess"
],
[
"ç®",
"Ģ"
],
[
"ust",
"ain"
],
[
"æ",
"¨"
],
[
"Ġst",
"r"
],
[
"c",
"ing"
],
[
"ab",
"ility"
],
[
"re",
"e"
],
[
"Ġed",
"uc"
],
[
"åİ",
"Ĩ"
],
[
"Ġcre",
"ate"
],
[
"åģ¥",
"康"
],
[
"Ġdes",
"ign"
],
[
"i",
"ps"
],
[
"åģ",
"ļ"
],
[
"èĬ",
"±"
],
[
"in",
"k"
],
[
"èı",
"ľ"
],
[
"æī",
"¾"
],
[
"æ®",
"µ"
],
[
"æµ",
"ĭ"
],
[
"Ġ",
"V"
],
[
"ĠB",
"y"
],
[
"å",
"Ķ"
],
[
"é¦",
"ĸ"
],
[
"è¯",
"į"
],
[
"Ġwhe",
"re"
],
[
"Ġdis",
"c"
],
[
"äºĨ",
"è§£"
],
[
"r",
"ic"
],
[
"ä¸",
"Ķ"
],
[
"è¶",
"³"
],
[
"æĺ¯",
"ä¸Ģ个"
],
[
"ar",
"ch"
],
[
"ç§",
"¯"
],
[
"å¸",
"¦"
],
[
"Ġwh",
"ile"
],
[
"Ġsignific",
"ant"
],
[
"çł",
"ģ"
],
[
"æĪ",
"¿"
],
[
"Ġbe",
"ing"
],
[
"Ġlangu",
"age"
],
[
"it",
"ive"
],
[
"2",
"0"
],
[
"Ġanalyz",
"e"
],
[
"æĻ",
"¯"
],
[
"è",
"Į"
],
[
"ri",
"b"
],
[
"æ¨",
"¡"
],
[
"ĠS",
"t"
],
[
"è´",
"¹"
],
[
"'",
"t"
],
[
"Ġhealth",
"care"
],
[
"Ġexperi",
"ence"
],
[
"Ġ",
"5"
],
[
"个",
"人"
],
[
"ay",
"s"
],
[
"è±",
"¡"
],
[
"p",
"lo"
],
[
"Ġw",
"ould"
],
[
"èĻ",
"ij"
],
[
"æĶ",
"¶"
],
[
"é¢",
"Ħ"
],
[
"é¢",
"Ĩ"
],
[
"ä¿Ŀ",
"æĮģ"
],
[
"en",
"ces"
],
[
"åı",
"ª"
],
[
"èĩ",
"´"
],
[
"æĪ",
"ı"
],
[
"Ġment",
"al"
],
[
"Ġfe",
"w"
],
[
"at",
"es"
],
[
"è¿ĩ",
"ç¨ĭ"
],
[
"å®ī",
"åħ¨"
],
[
"Ġs",
"ustain"
],
[
"Ġw",
"ere"
],
[
"å¤",
"ª"
],
[
"ç",
"Į"
],
[
"Ġspec",
"ific"
],
[
"Ġwor",
"ld"
],
[
"çŃ",
"Ķ"
],
[
"``",
"`"
],
[
"Ġt",
"ake"
],
[
"åħ",
"»"
],
[
"éĢ",
"Ł"
],
[
"e",
"ver"
],
[
"S",
"S"
],
[
"éĶ",
"Ģ"
],
[
"Ġb",
"o"
],
[
"he",
"s"
],
[
"Ġm",
"us"
],
[
"æľį",
"åĬ¡"
],
[
"è§",
"Ĵ"
],
[
"t",
"en"
],
[
"æŀ",
"IJ"
],
[
"p",
"ow"
],
[
"d",
"ict"
],
[
"v",
"ent"
],
[
"1",
"0"
],
[
"çļĦæ",
"Ĺ"
],
[
"ĸ",
"çķ"
],
[
"Ġpro",
"t"
],
[
"ç½",
"®"
],
[
"Ġh",
"igh"
],
[
"Ġb",
"us"
],
[
"Ġind",
"ust"
],
[
"åIJ",
"¦"
],
[
"c",
"ial"
],
[
"人",
"们"
],
[
"ĠA",
"s"
],
[
"åij",
"Ĭ"
],
[
"ad",
"e"
],
[
"æĶ",
"¹"
],
[
"ç",
"Ĺ"
],
[
"Ġh",
"ad"
],
[
"Ġhe",
"r"
],
[
"Ġj",
"ust"
],
[
"ï¼",
"Ľ"
],
[
"è´",
"Ń"
],
[
"ç¬",
"¬"
],
[
"é",
"ĵ"
],
[
"Ġw",
"ater"
],
[
"Ġf",
"ood"
],
[
"éĺ",
"Ł"
],
[
"a",
"us"
],
[
"Ġchall",
"eng"
],
[
"åħ",
"į"
],
[
"æĸĩ",
"åĮĸ"
],
[
"Ġmo",
"st"
],
[
"é",
"¸"
],
[
"ç½",
"ij"
],
[
"çĽ",
"´"
],
[
"Ġs",
"m"
],
[
"Ġact",
"iv"
],
[
"plo",
"y"
],
[
"O",
"verall"
],
[
"å¿",
"«"
],
[
"ru",
"ct"
],
[
"Ġindividual",
"s"
],
[
"å§",
"ĭ"
],
[
"g",
"ies"
],
[
"æŁ",
"¥"
],
[
"çĪ",
"±"
],
[
"i",
"ety"
],
[
"I",
"n"
],
[
"åĪĨ",
"æŀIJ"
],
[
"è§",
"Ĩ"
],
[
"æ¸",
"©"
],
[
"ç»",
"´"
],
[
"ol",
"ut"
],
[
"åŁ",
"Ł"
],
[
"omm",
"end"
],
[
"Ġcom",
"ple"
],
[
"æķ",
"Ļ"
],
[
"Ġb",
"u"
],
[
"Ġeduc",
"ation"
],
[
"at",
"her"
],
[
"Ġ",
"4"
],
[
"t",
"ing"
],
[
"Ġf",
"ind"
],
[
"æ²",
"¡"
],
[
"Ġh",
"is"
],
[
"ä¹ĭ",
"éĹ´"
],
[
"Ġeffect",
"ive"
],
[
"Ġat",
"t"
],
[
"Ġre",
"se"
],
[
"èĥ½",
"åĬĽ"
],
[
"åŁ",
"İ"
],
[
"Ġal",
"low"
],
[
"Ġa",
"v"
],
[
"Ġpro",
"mot"
],
[
"æĻº",
"èĥ½"
],
[
"æ»",
"¡"
],
[
"åħ",
"±"
],
[
"ie",
"w"
],
[
"c",
"ome"
],
[
"ç³»",
"绣"
],
[
"Ġrespon",
"s"
],
[
"äº",
"Ĵ"
],
[
"Ġc",
"ult"
],
[
"pow",
"ered"
],
[
"Ġrec",
"ommend"
],
[
"èIJ",
"¥"
],
[
"O",
"SS"
],
[
"Ġch",
"ange"
],
[
"è¯",
"ģ"
],
[
"v",
"ed"
],
[
"æİ",
"Ĵ"
],
[
"è§£",
"åĨ³"
],
[
"ic",
"i"
],
[
"ĠH",
"ow"
],
[
"Ġfe",
"el"
],
[
"æľ",
"Ī"
],
[
"Ġwh",
"at"
],
[
"以",
"åıĬ"
],
[
"Ġse",
"e"
],
[
"åŃ",
"©"
],
[
"b",
"s"
],
[
"Ġs",
"ur"
],
[
"æ",
"£"
],
[
"al",
"ity"
],
[
"Ġv",
"is"
],
[
"ç¡®",
"ä¿Ŀ"
],
[
"p",
"ect"
],
[
"å®ŀ",
"çݰ"
],
[
"Ġc",
"are"
],
[
"å¹",
"¿"
],
[
"ill",
"s"
],
[
"åº",
"Ń"
],
[
"as",
"es"
],
[
"å¤",
"į"
],
[
"åºĶ",
"ç͍"
],
[
"çļĦæ",
"ĥ"
],
[
"ard",
"s"
],
[
"Ġadd",
"ress"
],
[
"Ġcomp",
"an"
],
[
"Ġinv",
"ol"
],
[
"Ġcustom",
"er"
],
[
"åĽł",
"为"
],
[
"Ġstud",
"ents"
],
[
"Ġin",
"s"
],
[
"注",
"æĦı"
],
[
"æŀ",
"Ħ"
],
[
"æ¬",
"¢"
],
[
"æµ",
"·"
],
[
"åı",
"Ĥ"
],
[
"èĩª",
"çĦ¶"
],
[
"é",
"©"
],
[
"ĠThe",
"se"
],
[
"w",
"n"
],
[
"æĺ",
"ĵ"
],
[
"çĬ",
"¶"
],
[
"re",
"n"
],
[
"Ġt",
"reat"
],
[
"Ġbenef",
"its"
],
[
"Ċ",
"ĠĠĠĠĠĠĠ"
],
[
"对",
"äºİ"
],
[
"æĢ",
"Ŀ"
],
[
"id",
"er"
],
[
"ĠY",
"es"
],
[
"Ġ",
"K"
],
[
"åĸ",
"ľ"
],
[
"Ġ",
"ke"
],
[
"Ġen",
"g"
],
[
"Ġpo",
"p"
],
[
"o",
"st"
],
[
"p",
"are"
],
[
"Ġm",
"on"
],
[
"æ¬",
"¾"
],
[
"ĠM",
"OSS"
],
[
"Ġem",
"ot"
],
[
"Ġa",
"c"
],
[
"ç¼",
"ĸ"
],
[
"f",
"ore"
],
[
"åı",
"¥"
],
[
"Ġv",
"al"
],
[
"il",
"y"
],
[
"Ġis",
"s"
],
[
"èĤ",
"ī"
],
[
"èĩ",
"³"
],
[
"游",
"æĪı"
],
[
"we",
"en"
],
[
"Ġinclud",
"e"
],
[
"Ġprot",
"ect"
],
[
"åħ³",
"ç³»"
],
[
"éĻ",
"©"
],
[
"Ġse",
"ver"
],
[
"Ġth",
"an"
],
[
"éľĢ",
"æ±Ĥ"
],
[
"ç»",
"ĥ"
],
[
"ĠThe",
"y"
],
[
"is",
"s"
],
[
"y",
"s"
],
[
"Ġj",
"ob"
],
[
"éĺ",
"³"
],
[
"æ",
"IJ"
],
[
"Ġbet",
"ween"
],
[
"Ġm",
"ach"
],
[
"----",
"----"
],
[
"èĢĥ",
"èĻij"
],
[
"è´¨",
"éĩı"
],
[
"Ġbus",
"iness"
],
[
"w",
"or"
],
[
"ic",
"k"
],
[
"e",
"g"
],
[
"åħ",
"ħ"
],
[
"ç",
"¯"
],
[
"æĿ",
"¡"
],
[
"n",
"er"
],
[
"a",
"pt"
],
[
"Ġapp",
"ro"
],
[
"Ġpl",
"ay"
],
[
"没",
"æľī"
],
[
"¤",
"IJ"
],
[
"æľ",
"ª"
],
[
"æĪ",
"ĺ"
],
[
"å®¶",
"åºŃ"
],
[
"ãĢ",
"ĭ"
],
[
"en",
"cy"
],
[
"ĠC",
"h"
],
[
"ãĢ",
"Ĭ"
],
[
"Ġprovid",
"ing"
],
[
"Ġres",
"ources"
],
[
"âĢ",
"Ļ"
],
[
"Ġass",
"ist"
],
[
"Ġnat",
"ural"
],
[
"è¯",
"Ħ"
],
[
"ä¾",
"¿"
],
[
"Ġs",
"af"
],
[
"åħ·",
"æľī"
],
[
"è°",
"¢"
],
[
"çĥ",
"Ń"
],
[
"s",
"s"
],
[
"et",
"h"
],
[
"ol",
"d"
],
[
"Ġper",
"form"
],
[
"Ġsever",
"al"
],
[
"é",
"¤IJ"
],
[
"Ġe",
"ach"
],
[
"è½",
"¬"
],
[
"c",
"i"
],
[
"Ġt",
"y"
],
[
"Ġp",
"ub"
],
[
"æ´»",
"åĬ¨"
],
[
"oc",
"us"
],
[
"çī",
"Į"
],
[
"è¶",
"Ĭ"
],
[
"åĽ",
"¢"
],
[
"è½",
"»"
],
[
"è¯Ń",
"è¨Ģ"
],
[
"Ġare",
"as"
],
[
"éĩ",
"ĩ"
],
[
"f",
"t"
],
[
"ri",
"end"
],
[
"å·",
"²"
],
[
"å¸Ĥ",
"åľº"
],
[
"it",
"ion"
],
[
"i",
"ents"
],
[
"管",
"çIJĨ"
],
[
"è®",
"¸"
],
[
"人",
"ç±»"
],
[
"身",
"ä½ĵ"
],
[
"iqu",
"e"
],
[
"Ġpart",
"ic"
],
[
"ç»",
"Ń"
],
[
"age",
"ment"
],
[
"v",
"es"
],
[
"ç¬",
"¦"
],
[
"l",
"ine"
],
[
"çº",
"¢"
],
[
"åIJ",
"¸"
],
[
"Ġpat",
"ter"
],
[
"00",
"0"
],
[
"社",
"ä¼ļ"
],
[
"åĨħ",
"容"
],
[
"Ġorgan",
"iz"
],
[
"ou",
"gh"
],
[
"Ġ",
"ve"
],
[
"åŃ©",
"åŃIJ"
],
[
"æĸ",
"½"
],
[
"æ¤",
"į"
],
[
"åĩ",
"ł"
],
[
"ä½Ĩ",
"æĺ¯"
],
[
"Ġa",
"ff"
],
[
"Ġn",
"um"
],
[
"le",
"ment"
],
[
"èī",
"º"
],
[
"è",
"ij"
],
[
"Ġc",
"ar"
],
[
"ag",
"es"
],
[
"ab",
"or"
],
[
"æĺ¯ä¸Ģ",
"ç§į"
],
[
"Ġin",
"st"
],
[
"è",
"Ľ"
],
[
"ä¹ĭ",
"ä¸Ģ"
],
[
"è·",
"¯"
],
[
"åį",
"³"
],
[
"Ġm",
"ain"
],
[
"éļ",
"ı"
],
[
"H",
"ow"
],
[
"å¿",
"ħ"
],
[
"ç¨ĭ",
"åºı"
],
[
"éŁ³",
"ä¹IJ"
],
[
"re",
"d"
],
[
"æ²",
"¹"
],
[
"Ġoff",
"er"
],
[
"et",
"s"
],
[
"ç",
"¢"
],
[
"Ġd",
"uring"
],
[
"çļĦ",
"人"
],
[
"æĽ´",
"å¤ļ"
],
[
"Ġd",
"i"
],
[
"代",
"çłģ"
],
[
"èİ",
"·"
],
[
"åħ",
"ĭ"
],
[
"Ġgu",
"id"
],
[
"主",
"è¦ģ"
],
[
"Ġf",
"am"
],
[
"æİ",
"§"
],
[
"éĢļ",
"常"
],
[
"ĠA",
"d"
],
[
"å¤Ħ",
"çIJĨ"
],
[
"ur",
"n"
],
[
"ow",
"er"
],
[
"åij",
"½"
],
[
"æı",
"ı"
],
[
"Ġsk",
"ills"
],
[
"Ġto",
"ol"
],
[
"w",
"are"
],
[
"æĸĩ",
"æľ¬"
],
[
"Ġpatter",
"ns"
],
[
"缮",
"æłĩ"
],
[
"ac",
"y"
],
[
"æī",
"ĵ"
],
[
"åŁİ",
"å¸Ĥ"
],
[
"Ġe",
"very"
],
[
"r",
"ies"
],
[
"è¯",
"»"
],
[
"éģ",
"¿"
],
[
"çĻ",
"½"
],
[
"éĢĤ",
"åIJĪ"
],
[
"Ġpat",
"ient"
],
[
"çľ",
"Ł"
],
[
"ot",
"h"
],
[
"å¥",
"¹"
],
[
"åĶ",
"®"
],
[
"ä¸Ģ",
"ç§į"
],
[
"Ġm",
"ade"
],
[
"ä½",
"İ"
],
[
"is",
"e"
],
[
"Ġre",
"m"
],
[
"æ¶",
"Ī"
],
[
"åIJ",
"«"
],
[
"a",
"ir"
],
[
"Ġgen",
"er"
],
[
"o",
"y"
],
[
"ç²",
"¾"
],
[
"æĥħ",
"åĨµ"
],
[
"ight",
"s"
],
[
"Ġexp",
"l"
],
[
"è§",
"ģ"
],
[
"Ġpre",
"dict"
],
[
"ç±",
"³"
],
[
"æĽ´",
"好"
],
[
"ä¿",
"®"
],
[
"Ġcl",
"imate"
],
[
"Ġf",
"ocus"
],
[
"Ġg",
"row"
],
[
"客",
"æĪ·"
],
[
"ä¸į",
"æĸŃ"
],
[
"it",
"or"
],
[
"ĠE",
"n"
],
[
"çº",
"¦"
],
[
"æĺ¯",
"åIJ¦"
],
[
"ä»",
"ħ"
],
[
"æĪij们",
"çļĦ"
],
[
"æľ",
"Ľ"
],
[
"o",
"p"
],
[
"Ġm",
"aking"
],
[
"y",
"th"
],
[
"cc",
"ess"
],
[
"Ġo",
"wn"
],
[
"gg",
"est"
],
[
"Ġt",
"as"
],
[
"ut",
"ure"
],
[
"Ġmod",
"el"
],
[
"p",
"ut"
],
[
"Ġrese",
"arch"
],
[
"ere",
"st"
],
[
"éļ",
"¾"
],
[
"Ġ",
"["
],
[
"i",
"el"
],
[
"ation",
"al"
],
[
"Ġcommun",
"ic"
],
[
"ç¥",
"ŀ"
],
[
"ç©",
"¶"
],
[
"Ġre",
"st"
],
[
"æĪIJ",
"为"
],
[
"k",
"ing"
],
[
"p",
"r"
],
[
"åĮ",
"»"
],
[
"c",
"ur"
],
[
"èĤ",
"²"
],
[
"Ġ",
"'"
],
[
"è¿Ļ",
"ç§į"
],
[
"ç¯",
"ĩ"
],
[
"Ġc",
"he"
],
[
"ow",
"n"
],
[
"éĻ",
"ħ"
],
[
"Ġf",
"in"
],
[
"åζ",
"ä½ľ"
],
[
"Ġsu",
"ggest"
],
[
"å¢ŀ",
"åĬł"
],
[
"Ġmed",
"ia"
],
[
"rib",
"ut"
],
[
"çļĦæĥ",
"ħ"
],
[
"åĬł",
"åħ¥"
],
[
"Ġc",
"le"
],
[
"åij",
"¨"
],
[
"ç«",
"ł"
],
[
"Ġth",
"ink"
],
[
"Ġloc",
"al"
],
[
"pport",
"un"
],
[
"ĠY",
"ou"
],
[
"Ġpl",
"an"
],
[
"Ġev",
"en"
],
[
"éĽ",
"Ĩ"
],
[
"å·",
"§"
],
[
"a",
"x"
],
[
"Ġchalleng",
"es"
],
[
"Ġpro",
"f"
],
[
"ĠC",
"an"
],
[
"Ġconc",
"er"
],
[
"Ġf",
"uture"
],
[
"åĬ",
"¿"
],
[
"Ġre",
"f"
],
[
"èģ",
"Ķ"
],
[
"Ġs",
"elf"
],
[
"æĪĸ",
"èĢħ"
],
[
"b",
"le"
],
[
"åĽ",
"´"
],
[
"è¿IJ",
"åĬ¨"
],
[
"Ġin",
"f"
],
[
"éĩ",
"Ĭ"
],
[
"Ġsustain",
"able"
],
[
"Ġte",
"xt"
],
[
"Ġg",
"ra"
],
[
"äº",
"Į"
],
[
"åĵģ",
"çīĮ"
],
[
"ä¸įåIJĮ",
"çļĦ"
],
[
"l",
"ed"
],
[
"çĭ",
"¬"
],
[
"Ġo",
"pportun"
],
[
"Ġcont",
"in"
],
[
"y",
"m"
],
[
"Ġg",
"et"
],
[
"å¯",
"Ĩ"
],
[
"éĻ",
"¤"
],
[
"æ",
"ħ"
],
[
"éģ¿",
"åħį"
],
[
"Ġ",
"+"
],
[
"è§",
"ī"
],
[
"Ġre",
"t"
],
[
"å¸",
"ĥ"
],
[
"Ġint",
"erest"
],
[
"Ġsoc",
"iety"
],
[
"ç»ĵ",
"æŀľ"
],
[
"åIJ",
"¬"
],
[
"é¦ĸ",
"åħĪ"
],
[
"Ġb",
"re"
],
[
"Ġ2",
"0"
],
[
"ĠHow",
"ever"
],
[
"è®",
"°"
],
[
"on",
"s"
],
[
"è¿",
"ij"
],
[
"å¼Ģ",
"å§ĭ"
],
[
"Ġbu",
"ild"
],
[
"Ġbe",
"h"
],
[
"'",
"m"
],
[
"v",
"ers"
],
[
"Ġg",
"ood"
],
[
"çIJĨ",
"è§£"
],
[
"res",
"ent"
],
[
"ç¦",
"»"
],
[
"åĬŁ",
"èĥ½"
],
[
"Ġeff",
"ort"
],
[
"l",
"abor"
],
[
"é»",
"ij"
],
[
"Ġbet",
"ter"
],
[
"Ġre",
"ad"
],
[
"å¾",
"ĭ"
],
[
"èĽ",
"ĭ"
],
[
"he",
"d"
],
[
"ä¹",
"°"
],
[
"导",
"èĩ´"
],
[
"Ġimp",
"lement"
],
[
"ç",
"¿"
],
[
"äº",
"«"
],
[
"å¤",
"´"
],
[
"en",
"se"
],
[
"Ġl",
"ong"
],
[
"ot",
"her"
],
[
"é¥",
"®"
],
[
"åŃĺ",
"åľ¨"
],
[
"çļĦæ",
"Ħ"
],
[
"ä¸Ģ",
"份"
],
[
"yth",
"on"
],
[
"n",
"ing"
],
[
"åĩı",
"å°ij"
],
[
"åĢ",
"Ļ"
],
[
"ä¸",
"ĵ"
],
[
"åIJĦ",
"ç§į"
],
[
"è",
"ħ"
],
[
"å°",
"½"
],
[
"åį",
"ĩ"
],
[
"æĬ",
"¥"
],
[
"Ġpub",
"lic"
],
[
"Ġl",
"ar"
],
[
"ä½ł",
"çļĦ"
],
[
"a",
"ut"
],
[
"é¢Ĩ",
"åŁŁ"
],
[
"æ",
"ļ"
],
[
"ol",
"low"
],
[
"èģ",
"Į"
],
[
"Ġch",
"ang"
],
[
"Ġb",
"est"
],
[
"h",
"ip"
],
[
"åĨ",
"į"
],
[
"ak",
"es"
],
[
"Ġch",
"at"
],
[
"it",
"ed"
],
[
"Ġp",
"ower"
],
[
"ä¿Ŀ",
"æĬ¤"
],
[
"ä¹",
"¦"
],
[
"计",
"åĪĴ"
],
[
"éĩįè¦ģ",
"çļĦ"
],
[
"åıĺ",
"åĮĸ"
],
[
"il",
"ities"
],
[
"Ġcons",
"ider"
],
[
"æĪij们",
"åı¯ä»¥"
],
[
"éĤ£",
"ä¹Ī"
],
[
"Ġ",
"ide"
],
[
"æ¼",
"Ķ"
],
[
"ag",
"ing"
],
[
"Ġb",
"ased"
],
[
"å®",
"Ŀ"
],
[
"Ġr",
"ange"
],
[
"Ġres",
"ult"
],
[
"Ġm",
"em"
],
[
"çħ",
"§"
],
[
"Ġle",
"vel"
],
[
"c",
"ou"
],
[
"Ġb",
"r"
],
[
"T",
"h"
],
[
"ä¼",
"ģ"
],
[
"建",
"ç«ĭ"
],
[
"Ġun",
"ique"
],
[
"è®",
"Ń"
],
[
"Ġm",
"ark"
],
[
"许",
"å¤ļ"
],
[
"è¡Į",
"为"
],
[
"Ķ",
"ç©¶"
],
[
"çļĦæ",
"Ĭ"
],
[
"Ġs",
"et"
],
[
"éª",
"¤"
],
[
"t",
"s"
],
[
"Ġh",
"ist"
],
[
"Ġa",
"round"
],
[
"Ġre",
"v"
],
[
"åħ¶",
"ä¸Ń"
],
[
"ï¼",
"ģ"
],
[
"æıı",
"è¿°"
],
[
"æľĢ",
"åIJİ"
],
[
"Ġs",
"im"
],
[
"n",
"ect"
],
[
"åĽŀ",
"çŃĶ"
],
[
"éĺ",
"²"
],
[
"èī",
"¯"
],
[
"åΰ",
"äºĨ"
],
[
"ä¸",
"ĸçķ"
],
[
"æĸ¹",
"æ¡Ī"
],
[
"æĿIJ",
"æĸĻ"
],
[
"ä¸ĸçķ",
"Į"
],
[
"æĽ´å¥½",
"åľ°"
],
[
"两",
"个"
],
[
"Ġem",
"ploy"
],
[
"Ġtr",
"y"
],
[
"æ",
"ĵ"
],
[
"Ġb",
"ack"
],
[
"åĪ",
"ĩ"
],
[
"Ġsu",
"ccess"
],
[
"Ġdecis",
"ions"
],
[
"Ġth",
"ose"
],
[
"å¯",
"Į"
],
[
"Ġf",
"act"
],
[
"æİ",
"¢"
],
[
"è¶",
"£"
],
[
"Ġpract",
"ices"
],
[
"åIJ",
"Ĺ"
],
[
"æī",
"į"
],
[
"çİ",
"©"
],
[
"pt",
"ion"
],
[
"æĸĩ",
"竳"
],
[
"Ġfe",
"at"
],
[
"Ġpre",
"vent"
],
[
"Ġwrit",
"ing"
],
[
"çļĦæ",
"Ģ"
],
[
"Ġn",
"o"
],
[
"ä»",
"ĭ"
],
[
"éĹ",
"¨"
],
[
"Ġd",
"el"
],
[
"æ",
"Ĵ"
],
[
"Ġopt",
"im"
],
[
"in",
"ation"
],
[
"Ġ",
"Ċ"
],
[
"us",
"ion"
],
[
"Ġacc",
"ount"
],
[
"l",
"ing"
],
[
"Ġd",
"ivers"
],
[
".",
"\""
],
[
"at",
"h"
],
[
"èĭ",
"±"
],
[
"ä¼ģ",
"ä¸ļ"
],
[
"Ġg",
"rou"
],
[
"åľ°",
"çIJĥ"
],
[
"å¤",
"±"
],
[
"Ġpersonal",
"ized"
],
[
"ĠH",
"e"
],
[
"表",
"è¾¾"
],
[
"cur",
"ity"
],
[
"Ġf",
"ollow"
],
[
"产",
"çĶŁ"
],
[
"Ġe",
"ar"
],
[
"åİ",
"ĭ"
],
[
"ver",
"n"
],
[
"Ġiss",
"ues"
],
[
"åĿ",
"ĩ"
],
[
"é",
"²"
],
[
"Ġd",
"r"
],
[
"iv",
"ing"
],
[
"Ġtrain",
"ing"
],
[
"Ġris",
"k"
],
[
"åĩ",
"½"
],
[
"åı",
"²"
],
[
"æ",
"ij"
],
[
"çļĦæĹ",
"¶"
],
[
"og",
"n"
],
[
"Ġrequ",
"ire"
],
[
"Ġenvironment",
"al"
],
[
"b",
"ack"
],
[
"éĶ",
"®"
],
[
"çĸ",
"Ĺ"
],
[
"Ġinter",
"act"
],
[
"åĽ¢",
"éĺŁ"
],
[
"æ¯ı",
"个"
],
[
"çĦ¶",
"åIJİ"
],
[
"Ġd",
"ist"
],
[
"ç͍",
"äºİ"
],
[
"认",
"为"
],
[
"åĩ½",
"æķ°"
],
[
"Ġs",
"ent"
],
[
"Ċ",
"ĠĠĠĠĠĠĠĠ"
],
[
"Ġredu",
"cing"
],
[
"å¹",
"²"
],
[
"Ġre",
"p"
],
[
"Ġc",
"aus"
],
[
"Ġmus",
"ic"
],
[
"ç",
"ª"
],
[
"Ġmon",
"itor"
],
[
"Ġfor",
"m"
],
[
"é¢",
"ľ"
],
[
"çĹ",
"ħ"
],
[
"é¦",
"Ļ"
],
[
"Ġof",
"ten"
],
[
"åı¯èĥ½",
"ä¼ļ"
],
[
"åijĺ",
"å·¥"
],
[
"Ġha",
"nd"
],
[
"æĬ",
"ķ"
],
[
"Ġneed",
"s"
],
[
"æŃ¤",
"å¤ĸ"
],
[
"åı",
"ĭ"
],
[
"iv",
"ity"
],
[
"Ġactiv",
"ities"
],
[
"åĸľ",
"欢"
],
[
"Ġp",
"ur"
],
[
"i",
"an"
],
[
"s",
"elf"
],
[
"åĬ¨",
"çī©"
],
[
"com",
"es"
],
[
"å",
"©"
],
[
"Ġpr",
"iv"
],
[
"a",
"z"
],
[
"Ġrel",
"ations"
],
[
"Ġmach",
"ine"
],
[
"çļĦæ",
"°"
],
[
"ä»·",
"æł¼"
],
[
"ä»·",
"å̼"
],
[
"ç´",
"¢"
],
[
"Ġfe",
"ed"
],
[
"ä¸Ģ",
"ä¸ĭ"
],
[
"Ġte",
"am"
],
[
"Ġindust",
"ry"
],
[
"è´",
"¢"
],
[
"ĠP",
"ro"
],
[
"Ġw",
"ant"
],
[
"ç§",
"°"
],
[
"Ġcl",
"ass"
],
[
"Ġlo",
"ve"
],
[
"åħ³",
"äºİ"
],
[
"è¾ĵ",
"åħ¥"
],
[
"Ġtrans",
"port"
],
[
"Ġcomple",
"x"
],
[
"Ġy",
"ear"
],
[
"éĶĢ",
"åĶ®"
],
[
"å¯",
"»"
],
[
"i",
"ence"
],
[
"ist",
"s"
],
[
"æĶ¯",
"æĮģ"
],
[
"Ġm",
"ind"
],
[
"Ġf",
"un"
],
[
"Ġch",
"ar"
],
[
"æĮ",
"ī"
],
[
"Ġconcer",
"ns"
],
[
"con",
"om"
],
[
"ç®Ģ",
"åįķ"
],
[
"以ä¸ĭ",
"æĺ¯"
],
[
"Ġst",
"art"
],
[
"å¹¶",
"ä¸Ķ"
],
[
"av",
"i"
],
[
"ä¸Ń",
"åĽ½"
],
[
"åħĥ",
"ç´ł"
],
[
"Ġcon",
"f"
],
[
"Ġpos",
"itive"
],
[
"Ġc",
"ur"
],
[
"Ġc",
"ount"
],
[
"er",
"y"
],
[
"å",
"¡"
],
[
"å®",
"¤"
],
[
"Ġco",
"st"
],
[
"Ġe",
"qu"
],
[
"Ġpol",
"ic"
],
[
"ast",
"e"
],
[
"a",
"w"
],
[
"éħ",
"Ĵ"
],
[
"cou",
"ra"
],
[
"iv",
"en"
],
[
"pl",
"ace"
],
[
"ch",
"ie"
],
[
"çļĦæķ",
"°"
],
[
"åĽł",
"ç´ł"
],
[
"Ġf",
"l"
],
[
"is",
"m"
],
[
"Ġmed",
"ical"
],
[
"Ġhum",
"ans"
],
[
"Ġaut",
"om"
],
[
"ertain",
"ly"
],
[
"Ġ",
"0"
],
[
"Ġoff",
"ers"
],
[
"Ġdet",
"ect"
],
[
"Ġ",
"6"
],
[
"é£İ",
"æł¼"
],
[
"Ġsh",
"ow"
],
[
"çģ",
"«"
],
[
"Ġan",
"im"
],
[
"é¢ľ",
"èī²"
],
[
"le",
"ase"
],
[
"a",
"ve"
],
[
"åĵ",
"ª"
],
[
"ĠThe",
"re"
],
[
"以",
"ä¸Ĭ"
],
[
"æľª",
"æĿ¥"
],
[
"X",
"X"
],
[
"çī",
"ĩ"
],
[
"u",
"ch"
],
[
"Ġtas",
"ks"
],
[
"åħ·",
"ä½ĵ"
],
[
"æ¤į",
"çī©"
],
[
"Ġm",
"in"
],
[
"èīº",
"æľ¯"
],
[
"ic",
"ult"
],
[
"Ġexperi",
"ences"
],
[
"æİ§",
"åζ"
],
[
"b",
"e"
],
[
"Ġpat",
"ients"
],
[
"å",
"²"
],
[
"ĠW",
"e"
],
[
"Ġrec",
"ogn"
],
[
"çĥ",
"¤"
],
[
"Ġsm",
"all"
],
[
"åĿ",
"Ĺ"
],
[
"å",
"Ħ"
],
[
"太",
"éĺ³"
],
[
"ct",
"ion"
],
[
"Ġ",
"ent"
],
[
"æį",
"¢"
],
[
"Ġbe",
"fore"
],
[
"Ġbe",
"come"
],
[
"å·²",
"ç»ı"
],
[
"表",
"çݰ"
],
[
"Ġexp",
"lo"
],
[
"Ġa",
"chie"
],
[
"ä»»",
"åĬ¡"
],
[
"大",
"çļĦ"
],
[
"Ġd",
"ay"
],
[
"Ġf",
"ound"
],
[
"å±",
"±"
],
[
"on",
"d"
],
[
"Ġtreat",
"ment"
],
[
"pe",
"nd"
],
[
"he",
"n"
],
[
"Ġcon",
"dit"
],
[
"ç¡®",
"å®ļ"
],
[
"Ġbusiness",
"es"
],
[
"ĠW",
"h"
],
[
"æīĢ",
"æľī"
],
[
"Ġdevelop",
"ed"
],
[
"ç»",
"Ī"
],
[
"æŃ¥",
"骤"
],
[
"Ġdiff",
"icult"
],
[
"åı",
"·"
],
[
"ĠR",
"e"
],
[
"éĶ",
"Ļ"
],
[
"Ġch",
"o"
],
[
"Ġqu",
"est"
],
[
"Ġtrans",
"pare"
],
[
"Ġpro",
"ject"
],
[
"Ġcommun",
"ity"
],
[
"o",
"v"
],
[
"å¸",
"Ī"
],
[
"å¼",
"ł"
],
[
"åĪĨ",
"ç±»"
],
[
"人",
"çļĦ"
],
[
"s",
"is"
],
[
"çĽ",
"Ĭ"
],
[
"o",
"id"
],
[
"ĠA",
"n"
],
[
"w",
"ays"
],
[
"Ġe",
"as"
],
[
"Ġaff",
"ect"
],
[
"Ġother",
"s"
],
[
"Ġreg",
"ul"
],
[
"æĢ§",
"åĴĮ"
],
[
"åĸ",
"Ħ"
],
[
"ag",
"n"
],
[
"ä½ľ",
"为"
],
[
"åı¯ä»¥",
"帮åĬ©"
],
[
"åĦ",
"¿"
],
[
"Ġorganiz",
"ations"
],
[
"é¸",
"¡"
],
[
"åħ",
"´"
],
[
"Ġf",
"riend"
],
[
"Ġ",
"$"
],
[
"Ġdet",
"ail"
],
[
"Ġtra",
"ditional"
],
[
"Ġdesign",
"ed"
],
[
"è´Ń",
"ä¹°"
],
[
"ä½ĵ",
"éªĮ"
],
[
"ç»",
"į"
],
[
"er",
"m"
],
[
"Ġcon",
"nect"
],
[
"è¿Ļ",
"æł·"
],
[
"Ġrecommend",
"ations"
],
[
"Ġb",
"oth"
],
[
"Ł",
"éĢļ"
],
[
"æ¯",
"į"
],
[
"Ġs",
"it"
],
[
"ä½ľ",
"ç͍"
],
[
"ä»ĭ",
"ç»į"
],
[
"Ġst",
"e"
],
[
"ĠS",
"ure"
],
[
"åı",
"°"
],
[
"æĤ¨",
"çļĦ"
],
[
"Ġs",
"he"
],
[
"Ġman",
"agement"
],
[
"j",
"oy"
],
[
"è´",
"Ł"
],
[
"Ġpromot",
"e"
],
[
"Ġvari",
"ous"
],
[
"(",
"\""
],
[
"p",
"or"
],
[
"Ġs",
"ens"
],
[
"Ġess",
"ential"
],
[
"get",
"her"
],
[
"ular",
"ly"
],
[
"äº",
"ī"
],
[
"ir",
"st"
],
[
"Ġo",
"p"
],
[
"Ġspec",
"ies"
],
[
"çݰ",
"åľ¨"
],
[
"ch",
"o"
],
[
"Ġbeh",
"avi"
],
[
"çŃ",
"ij"
],
[
"å¥",
"³"
],
[
"Ġqu",
"ality"
],
[
"Ġex",
"t"
],
[
"è",
"¥"
],
[
"å®Į",
"æĪIJ"
],
[
"æĢ»",
"ä¹ĭ"
],
[
"éĥ¨",
"åĪĨ"
],
[
"ä»İ",
"èĢĮ"
],
[
"åĽ",
"¾"
],
[
"Ġty",
"p"
],
[
"Ġstr",
"ate"
],
[
"è¥",
"¿"
],
[
"Ġhe",
"re"
],
[
"ar",
"s"
],
[
"å¸",
"Į"
],
[
"çļĦæ",
"Ŀ"
],
[
"å°",
"Ŀ"
],
[
"e",
"e"
],
[
"i",
"er"
],
[
"Ġe",
"c"
],
[
"ical",
"ly"
],
[
"er",
"ing"
],
[
"å¿",
"µ"
],
[
"ĠD",
"e"
],
[
"Ġne",
"g"
],
[
"建",
"çŃij"
],
[
"Ġserv",
"ices"
],
[
"Ġab",
"le"
],
[
"im",
"es"
],
[
"Ġopt",
"ions"
],
[
"缸",
"åħ³"
],
[
"Ġsu",
"b"
],
[
"Ġdecis",
"ion"
],
[
"ĠC",
"ertainly"
],
[
"Ġ",
"åľ¨"
],
[
"æ",
"¢"
],
[
"Ġserv",
"ice"
],
[
")",
":"
],
[
"带",
"æĿ¥"
],
[
"Ġch",
"ild"
],
[
"è§£",
"éĩĬ"
],
[
"ir",
"t"
],
[
"ç",
"Ĩ"
],
[
"ä¸į",
"ä»ħ"
],
[
"æĿ",
"¾"
],
[
"积",
"æŀģ"
],
[
"r",
"on"
],
[
"åı",
"¤"
],
[
"çł",
"Ķç©¶"
],
[
"ç²",
"ī"
],
[
"h",
"or"
],
[
"Ġprof",
"ess"
],
[
"çļĦ",
"éĹ®é¢ĺ"
],
[
"Ġopportun",
"ities"
],
[
"åİĨ",
"åı²"
],
[
"Ġde",
"f"
],
[
"ĠA",
"m"
],
[
"Ġg",
"r"
],
[
"a",
"ur"
],
[
"å±",
"Ĥ"
],
[
"çŃ",
"ĸ"
],
[
"Ġpop",
"ular"
],
[
"æ´",
"ģ"
],
[
"åıij",
"çݰ"
],
[
"Ġpo",
"em"
],
[
"èµ",
"Ľ"
],
[
"Ġo",
"b"
],
[
"Ġd",
"on"
],
[
"Ġs",
"ound"
],
[
"Ġtransport",
"ation"
],
[
"i",
"ous"
],
[
"åı",
"¦"
],
[
"Ġro",
"le"
],
[
"Ġf",
"iel"
],
[
"ç§ij",
"åѦ"
],
[
"èĢ",
"ģ"
],
[
"re",
"en"
],
[
"æľī",
"æķĪ"
],
[
"Ġc",
"or"
],
[
"Ġfeed",
"back"
],
[
"Ġtechnolo",
"gies"
],
[
"交",
"éĢļ"
],
[
"Ġad",
"apt"
],
[
"'",
"re"
],
[
"erv",
"ation"
],
[
"Ġcommun",
"ities"
],
[
"çݰ",
"代"
],
[
"Ġlo",
"ok"
],
[
"Ġf",
"ac"
],
[
"ç͵",
"å½±"
],
[
"Ġcol",
"lect"
],
[
"å¾Ĺ",
"åΰ"
],
[
"h",
"ips"
],
[
"Ġav",
"ail"
],
[
"ere",
"n"
],
[
"ä¸Ģ",
"èµ·"
],
[
"çī",
"Ľ"
],
[
"Ġpos",
"s"
],
[
"Ġwe",
"ather"
],
[
"Ġeffort",
"s"
],
[
"¿",
"Ģ"
],
[
"æĹ",
"ħ"
],
[
"o",
"h"
],
[
"Ġcol",
"labor"
],
[
"æĭ",
"¥"
],
[
"æĪIJ",
"åĬŁ"
],
[
"èİ·",
"å¾Ĺ"
],
[
"å±",
"ħ"
],
[
"Ġt",
"re"
],
[
"Ġs",
"ources"
],
[
"Ġstud",
"y"
],
[
"Ġprogra",
"ms"
],
[
"éĻ",
"IJ"
],
[
"Ġt",
"ips"
],
[
"Ġmark",
"et"
],
[
"al",
"ly"
],
[
"å®",
"³"
],
[
"w",
"ards"
],
[
"æ£",
"Ģ"
],
[
"ä¸Ģ",
"ç¯ĩ"
],
[
"ri",
"or"
],
[
"Ġto",
"p"
],
[
"Ġe",
"nd"
],
[
"å",
"ĭ"
],
[
"Ġlar",
"ge"
],
[
"ici",
"ency"
],
[
"Ġde",
"c"
],
[
"å®ļ",
"çļĦ"
],
[
"ic",
"ient"
],
[
"è¿ĩç¨ĭ",
"ä¸Ń"
],
[
"lic",
"ations"
],
[
"ç¼",
"º"
],
[
"Ġto",
"ur"
],
[
"Ġto",
"gether"
],
[
"人",
"å·¥"
],
[
"Ġtool",
"s"
],
[
"æĸ",
"¯"
],
[
"æ°",
"ij"
],
[
"æĬ",
"Ĭ"
],
[
"ä¹ĭéĹ´",
"çļĦ"
],
[
"çī¹",
"çĤ¹"
],
[
"Ġbe",
"l"
],
[
"ditional",
"ly"
],
[
"åĪ©",
"ç͍"
],
[
"è¾",
"¹"
],
[
"éĻ",
"į"
],
[
"ĠI",
"f"
],
[
"é¢",
"Ŀ"
],
[
"åį",
"ı"
],
[
"å¾",
"Ģ"
],
[
"l",
"ish"
],
[
"è¯",
"ī"
],
[
"in",
"s"
],
[
"å¥",
"¶"
],
[
"Ġe",
"conom"
],
[
"Ġinv",
"est"
],
[
"ĠD",
"o"
],
[
"t",
"ain"
],
[
"åĩº",
"çݰ"
],
[
"çļĦ",
"å½±åĵį"
],
[
"ater",
"ial"
],
[
"Ġs",
"ure"
],
[
"Ġp",
"ass"
],
[
"çĶ",
"»"
],
[
"è´",
"£"
],
[
"ç»ĵ",
"æŀĦ"
],
[
"æķ",
"ħ"
],
[
"æĥħ",
"æĦŁ"
],
[
"æ",
"¿Ģ"
],
[
"ell",
"ig"
],
[
"ä¼",
"Ĺ"
],
[
"æ¯Ķ",
"è¾ĥ"
],
[
"ter",
"n"
],
[
"Ġout",
"comes"
],
[
"u",
"p"
],
[
"Ġbe",
"aut"
],
[
"re",
"ad"
],
[
"çĶŁ",
"æĪIJ"
],
[
"æķ°",
"åŃĹ"
],
[
"Ġde",
"m"
],
[
"i",
"res"
],
[
"åı¯ä»¥",
"éĢļè¿ĩ"
],
[
"æĸ°",
"çļĦ"
],
[
"Ġde",
"ep"
],
[
"å",
"¨"
],
[
"çĭ",
"Ĺ"
],
[
"åħ³",
"注"
],
[
"çĶŁ",
"åij½"
],
[
"ä¼ł",
"绣"
],
[
"Ġst",
"ay"
],
[
"æŃ",
"Į"
],
[
"åħ³",
"éĶ®"
],
[
"Ġpl",
"ace"
],
[
"主",
"é¢ĺ"
],
[
"å¾Ī",
"å¤ļ"
],
[
"èĪ",
"Ĵ"
],
[
"Ġprofess",
"ional"
],
[
"y",
"le"
],
[
"æĽ",
"²"
],
[
"1",
"9"
],
[
"Ġess",
"ay"
],
[
"Ġg",
"ive"
],
[
"ç³",
"ĸ"
],
[
"Ġon",
"ly"
],
[
"æŁ",
"IJ"
],
[
"Ġph",
"ys"
],
[
"对",
"è¯Ŀ"
],
[
"Ġcont",
"ro"
],
[
"Ġam",
"ount"
],
[
"ce",
"pt"
],
[
"iz",
"ation"
],
[
"ç¼ĸ",
"åĨĻ"
],
[
"åıĹ",
"åΰ"
],
[
"Ġal",
"ways"
],
[
"æ¯Ķ",
"å¦Ĥ"
],
[
"Ġpriv",
"acy"
],
[
"a",
"u"
],
[
"____",
"____"
],
[
"Ġrespons",
"ible"
],
[
"(",
")"
],
[
"çŃī",
"çŃī"
],
[
"Ġm",
"aterial"
],
[
"Ġon",
"line"
],
[
"é",
"¼"
],
[
"æĶ",
"¿"
],
[
"åĽ",
"Ľ"
],
[
"Ġen",
"joy"
],
[
"åľ",
"Ł"
],
[
"Ġsaf",
"ety"
],
[
"Ġt",
"w"
],
[
"Ġcommunic",
"ation"
],
[
"ä¸",
"½"
],
[
"æĺ",
"¾"
],
[
"olut",
"ion"
],
[
"er",
"g"
],
[
"į",
"ä½ľ"
],
[
"Ġus",
"er"
],
[
"Ġemot",
"ional"
],
[
"t",
"ime"
],
[
"é",
"¾"
],
[
"Ġse",
"curity"
],
[
"Ġs",
"ense"
],
[
"el",
"ines"
],
[
"åĬ",
"±"
],
[
"çī©",
"è´¨"
],
[
"u",
"ra"
],
[
"Ġsh",
"are"
],
[
"Ġanalyz",
"ing"
],
[
"it",
"al"
],
[
"é",
"±"
],
[
"irt",
"ual"
],
[
"Ġvis",
"it"
],
[
"b",
"ers"
],
[
"Ġc",
"our"
],
[
"Ġpro",
"ble"
],
[
"设",
"å¤ĩ"
],
[
"at",
"ch"
],
[
"l",
"and"
],
[
"é±",
"¼"
],
[
"æĪij们",
"éľĢè¦ģ"
],
[
"ç¨",
"³"
],
[
"ib",
"ility"
],
[
"Ġeff",
"iciency"
],
[
"å£",
"°"
],
[
"è",
"Ĵ"
],
[
"æľº",
"åύ"
],
[
"Ġcle",
"ar"
],
[
"åζ",
"å®ļ"
],
[
"iz",
"ing"
],
[
"Ġcondit",
"ions"
],
[
"l",
"usion"
],
[
"Ġlo",
"w"
],
[
"Ġl",
"im"
],
[
"her",
"s"
],
[
"Ġris",
"ks"
],
[
"ç¿",
"»"
],
[
"Ġle",
"t"
],
[
"åĴ",
"ĸ"
],
[
"å¿ĥ",
"çIJĨ"
],
[
"è¿",
"ľ"
],
[
"pr",
"int"
],
[
"Ġchang",
"es"
],
[
"Ġme",
"as"
],
[
"Ġimpro",
"ving"
],
[
"Ġc",
"rit"
],
[
"5",
"0"
],
[
"å¸Į",
"æľĽ"
],
[
"Ġa",
"ud"
],
[
"åį",
"Ĺ"
],
[
"æĹł",
"æ³ķ"
],
[
"Ġneg",
"ative"
],
[
"项",
"缮"
],
[
"u",
"nd"
],
[
"at",
"s"
],
[
"Ġcompan",
"ies"
],
[
"æī¾",
"åΰ"
],
[
"Ġcont",
"ribut"
],
[
"æŃ£",
"ç¡®"
],
[
"é»",
"Ħ"
],
[
"å±",
"ŀ"
],
[
"Ġunderstand",
"ing"
],
[
"Ġm",
"ult"
],
[
"Ġc",
"lo"
],
[
"å¾",
"ģ"
],
[
"Ġp",
"rior"
],
[
"r",
"im"
],
[
"人工",
"æĻºèĥ½"
],
[
"Ġvari",
"ety"
],
[
"Ġt",
"aking"
],
[
"å",
"Ĥ"
],
[
"as",
"ter"
],
[
"od",
"y"
],
[
"Ġ",
"{"
],
[
"çļĦ",
"éĩįè¦ģ"
],
[
"Ġf",
"ore"
],
[
"èµĦ",
"æºIJ"
],
[
"è¦ģ",
"æ±Ĥ"
],
[
"Ġfeat",
"ures"
],
[
"èį",
"ī"
],
[
"m",
"e"
],
[
"èĮ",
"ĥ"
],
[
"Ġo",
"per"
],
[
"çº",
"§"
],
[
"é²",
"ľ"
],
[
"æĬĢ",
"å·§"
],
[
"ij",
"æĪĺ"
],
[
"ç±»",
"åŀĭ"
],
[
"æĿ",
"¿"
],
[
"è½",
"¯"
],
[
"e",
"w"
],
[
"Ġrest",
"aur"
],
[
"Ġwith",
"out"
],
[
"ruct",
"ure"
],
[
"çļĦ",
"æĺ¯"
],
[
"ç",
"ı"
],
[
"Ġl",
"ist"
],
[
"ur",
"ate"
],
[
"Ġbo",
"ok"
],
[
"äº",
"²"
],
[
"åº",
"Ĺ"
],
[
"ä¹Ł",
"æĺ¯"
],
[
"ä»»",
"ä½ķ"
],
[
"Ġc",
"am"
],
[
"ĠB",
"e"
],
[
"Ġgo",
"vern"
],
[
"Ġbehavi",
"or"
],
[
"è®Ń",
"ç»ĥ"
],
[
"Ġfam",
"ily"
],
[
"æĿ",
"Ĥ"
],
[
"Ġc",
"ity"
],
[
"Ġappro",
"ach"
],
[
"Ġacc",
"urate"
],
[
"Ġs",
"om"
],
[
"Ġe",
"l"
],
[
"èĪ",
"ŀ"
],
[
"è",
"ŀ"
],
[
"åŁº",
"æľ¬"
],
[
"Ġdis",
"e"
],
[
"Ġen",
"coura"
],
[
"ĠW",
"hat"
],
[
"å",
"ĥ"
],
[
"è¯",
"¦"
],
[
"¦",
"Ĥ"
],
[
"å·¥",
"åħ·"
],
[
"åķ",
"¡"
],
[
"Ġst",
"ill"
],
[
"cho",
"ol"
],
[
"æĦŁ",
"åΰ"
],
[
"çĶŁ",
"çī©"
],
[
"åĴĸ",
"åķ¡"
],
[
"åĩĨ",
"å¤ĩ"
],
[
"Ġw",
"aste"
],
[
"Ġev",
"ents"
],
[
"æķĻ",
"èĤ²"
],
[
"Ġ",
"8"
],
[
"Ġm",
"ust"
],
[
"i",
"ed"
],
[
"as",
"ing"
],
[
"å½¢",
"æĪIJ"
],
[
"Ġproduct",
"s"
],
[
"åħ",
"¸"
],
[
"è®",
"²"
],
[
"f",
"ter"
],
[
"å·",
"®"
],
[
"l",
"ess"
],
[
"Ġc",
"ro"
],
[
"Ġfin",
"an"
],
[
"åıį",
"åºĶ"
],
[
"åĪĽ",
"éĢł"
],
[
"Ġguid",
"elines"
],
[
"åĪ",
"¤"
],
[
"ä½ľ",
"åĵģ"
],
[
"表",
"示"
],
[
"å¼",
"Ĥ"
],
[
"Ġknow",
"n"
],
[
"Ġt",
"est"
],
[
"è¯",
"¯"
],
[
"o",
"pe"
],
[
"Ġus",
"ers"
],
[
"A",
"I"
],
[
"å¾",
"·"
],
[
"ne",
"w"
],
[
"è¿",
"½"
],
[
"iqu",
"es"
],
[
"模",
"åŀĭ"
],
[
"åĬĽ",
"åĴĮ"
],
[
"Ġhist",
"ory"
],
[
"ĠA",
"l"
],
[
"æĬķ",
"èµĦ"
],
[
"å°Ŀ",
"è¯ķ"
],
[
"an",
"k"
],
[
"Ġh",
"ome"
],
[
"éĴ",
"Ł"
],
[
"ä¸",
"°"
],
[
"èĪĴ",
"éĢĤ"
],
[
"Ġincre",
"ase"
],
[
"Ġh",
"ab"
],
[
"åĪ",
"»"
],
[
"è¾ĵ",
"åĩº"
],
[
"Ġlead",
"ing"
],
[
"Ġ",
"7"
],
[
"é£İ",
"éĻ©"
],
[
"Ġperform",
"ance"
],
[
"Ġha",
"pp"
],
[
"åŃ",
"£"
],
[
"Ġst",
"and"
],
[
"t",
"y"
],
[
"ç¦",
"ı"
],
[
"Ġcustom",
"ers"
],
[
"åį",
"İ"
],
[
"Ġbel",
"ie"
],
[
"Ġcompan",
"y"
],
[
"å½",
"ķ"
],
[
"é£Ł",
"çī©"
],
[
"ĠU",
"n"
],
[
"Ġsu",
"mm"
],
[
"re",
"nt"
],
[
"ĠC",
"on"
],
[
"éĢĤ",
"éĩı"
],
[
"an",
"ced"
],
[
"Ġ",
"i"
],
[
"Ġl",
"ight"
],
[
"Ġanaly",
"sis"
],
[
"å°",
"Ĭ"
],
[
"ĠU",
"se"
],
[
"ou",
"se"
],
[
"t",
"ed"
],
[
"Ġchar",
"act"
],
[
"Ġ",
"#"
],
[
"t",
"o"
],
[
"ç»",
"ľ"
],
[
"ä¸į",
"æĺ¯"
],
[
"Ġdevelop",
"ing"
],
[
"åŁ",
"¹"
],
[
"Ġstrate",
"gies"
],
[
"Ġm",
"ight"
],
[
"çŁ",
"Ń"
],
[
"çļĦæ",
"İ"
],
[
"Ġf",
"irst"
],
[
"èĥ",
"Į"
],
[
"çĮ",
"«"
],
[
"Ġinclud",
"es"
],
[
"åĽ",
"Ń"
],
[
"Ġdi",
"agn"
],
[
"Ġgrow",
"th"
],
[
"ä¸ĵ",
"ä¸ļ"
],
[
"Ġdo",
"es"
],
[
"1",
"2"
],
[
"ç»",
"¿"
],
[
"Ġke",
"ep"
],
[
"详",
"ç»Ĩ"
],
[
"åĥ",
"ı"
],
[
"åıij",
"çĶŁ"
],
[
"f",
"act"
],
[
"åı¯ä»¥",
"åľ¨"
],
[
"ç«",
"Ļ"
],
[
"æĭ",
"ī"
],
[
"æµ",
"İ"
],
[
"Ġchat",
"bots"
],
[
"Ġbre",
"ak"
],
[
"è¡",
"¡"
],
[
"çŁ",
"³"
],
[
"æĮģ",
"ç»Ń"
],
[
"l",
"ife"
],
[
"Ġ1",
"0"
],
[
"æ´",
"Ĺ"
],
[
"ĠAd",
"ditionally"
],
[
"å£",
"«"
],
[
"em",
"ber"
],
[
"Ġgo",
"als"
],
[
"å¾",
"®"
],
[
"Ġv",
"iew"
],
[
"Â",
"·"
],
[
"o",
"ve"
],
[
"åŁº",
"ç¡"
],
[
"Ġoptim",
"ize"
],
[
"Ġt",
"em"
],
[
"Ġd",
"own"
],
[
"åŁºç¡",
"Ģ"
],
[
"è¶",
"ħ"
],
[
"er",
"cis"
],
[
"Ġl",
"ess"
],
[
"e",
"es"
],
[
"æĿ",
"ĥ"
],
[
"Ġke",
"y"
],
[
"Ġwor",
"ks"
],
[
"è®",
"¨"
],
[
"åı¥",
"åŃIJ"
],
[
"Ġro",
"bot"
],
[
"us",
"s"
],
[
"åħ¨",
"çIJĥ"
],
[
"ç»ı",
"æµİ"
],
[
"æīį",
"èĥ½"
],
[
"eg",
"r"
],
[
"ä»ĸ们",
"çļĦ"
],
[
"äº",
"Ķ"
],
[
"èµ·",
"æĿ¥"
],
[
"ç",
"ĵ"
],
[
"Ġfact",
"ors"
],
[
"Ġcult",
"ural"
],
[
"æľ",
"¨"
],
[
"Ġwork",
"ing"
],
[
"ä¼",
"¼"
],
[
"èIJ",
"½"
],
[
"éĢŁ",
"度"
],
[
"ä½",
"ı"
],
[
"Ġeffect",
"s"
],
[
"å©",
"ļ"
],
[
"b",
"r"
],
[
"åİ",
"ħ"
],
[
"ra",
"in"
],
[
"\"",
")"
],
[
"åѦ",
"çĶŁ"
],
[
"\"",
","
],
[
"Ġp",
"ar"
],
[
"at",
"form"
],
[
"Ġens",
"uring"
],
[
"çͱ",
"äºİ"
],
[
"Ġm",
"uch"
],
[
"Ġwor",
"ds"
],
[
"Ġm",
"ar"
],
[
"ç»ı",
"éªĮ"
],
[
"为",
"äºĨ"
],
[
"åIJĪ",
"ä½ľ"
],
[
"v",
"en"
],
[
"Ġ",
"/"
],
[
"Ġfinan",
"cial"
],
[
"wor",
"k"
],
[
"or",
"ies"
],
[
"æ²",
"»"
],
[
"Ġtechn",
"iques"
],
[
"æĭ¥",
"æľī"
],
[
"ra",
"p"
],
[
"å°",
"Ķ"
],
[
"Ġ",
"est"
],
[
"Ġavail",
"able"
],
[
"Ġl",
"it"
],
[
"æ",
"¹"
],
[
"Ġeff",
"icient"
],
[
"el",
"s"
],
[
"o",
"ver"
],
[
"Ġl",
"and"
],
[
"Ġare",
"a"
],
[
"Ġint",
"ellig"
],
[
"Ġpre",
"f"
],
[
"at",
"ure"
],
[
"çŁ¥",
"è¯Ĩ"
],
[
"æĵ",
"įä½ľ"
],
[
"å¾",
"ħ"
],
[
"ig",
"ate"
],
[
"çļĦæ",
"Ķ"
],
[
"Ġme",
"an"
],
[
"b",
"o"
],
[
"Ġcontro",
"l"
],
[
"éĩĩ",
"ç͍"
],
[
"ric",
"ult"
],
[
"Ġprogra",
"mm"
],
[
"Ġto",
"wards"
],
[
"th",
"ing"
],
[
"ä¸į",
"è¦ģ"
],
[
"Ġth",
"ough"
],
[
"å½",
"©"
],
[
"Ġc",
"ertain"
],
[
"Ġw",
"ild"
],
[
"ä»",
"Ĭ"
],
[
"Ġcons",
"ervation"
],
[
"çŁ¥",
"éģĵ"
],
[
"Ġreal",
"ly"
],
[
"çļĦ",
"åľ°"
],
[
"i",
"o"
],
[
"é¥",
"°"
],
[
"Ġf",
"ul"
],
[
"çݯ",
"ä¿Ŀ"
],
[
"Ġexplo",
"re"
],
[
"çļĦæ",
"¸"
],
[
"Ġdivers",
"e"
],
[
"åĬł",
"强"
],
[
"çļ",
"®"
],
[
"Ġemot",
"ions"
],
[
"Ġav",
"oid"
],
[
"'",
"ll"
],
[
"çļĦæ",
"ī"
],
[
"åį",
"¡"
],
[
"Ġpl",
"atform"
],
[
"an",
"ces"
],
[
"Ġsit",
"u"
],
[
"ä»",
"ĺ"
],
[
"ä½į",
"ç½®"
],
[
"or",
"ing"
],
[
"çĽ",
"IJ"
],
[
"ä¸",
"ĩ"
],
[
"Ġde",
"v"
],
[
"n",
"ov"
],
[
"as",
"h"
],
[
"Ġtw",
"o"
],
[
"å®",
"ł"
],
[
"b",
"on"
],
[
"èµ",
"°"
],
[
"åĪĹ",
"表"
],
[
"Ġc",
"y"
],
[
"èį",
"IJ"
],
[
"ĠS",
"ome"
],
[
"Ġexpl",
"ain"
],
[
"Ġa",
"ware"
],
[
"社",
"交"
],
[
"d",
"ay"
],
[
"åı",
"Į"
],
[
"æ²",
"ŁéĢļ"
],
[
"æ°",
"§"
],
[
"å¼Ģ",
"åıij"
],
[
"åħ¬åı¸",
"çļĦ"
],
[
"Ġa",
"ir"
],
[
"åĩ",
"»"
],
[
"ar",
"ing"
],
[
"éĥ½",
"æĺ¯"
],
[
"Ġlevel",
"s"
],
[
"od",
"s"
],
[
"Ġste",
"ps"
],
[
"Ġc",
"ap"
],
[
"æ´",
"ŀ"
],
[
"é©",
"¬"
],
[
"Ġret",
"urn"
],
[
"Ġm",
"et"
],
[
"çĶŁ",
"æĢģ"
],
[
"丰",
"å¯Į"
],
[
"æŁ",
"ĵ"
],
[
"æīĢ",
"以"
],
[
"é¡",
"»"
],
[
"Ġ",
"er"
],
[
"Ġf",
"ra"
],
[
"3",
"0"
],
[
"è",
"ĵ"
],
[
"âĢ",
"Ķ"
],
[
"Ġ",
"å½ĵ"
],
[
"a",
"h"
],
[
"ä¿",
"ĥ"
],
[
"Ġlike",
"ly"
],
[
"ĠĠĠĠĠĠĠĠ",
"ĠĠĠĠĠĠĠĠ"
],
[
"åĪ",
"Ŀ"
],
[
"Ġcreat",
"ing"
],
[
"Ġf",
"arm"
],
[
"Ġb",
"al"
],
[
"Ġl",
"ives"
],
[
"å®ĥ",
"çļĦ"
],
[
"Ġab",
"ility"
],
[
"ä¸Ĭ",
"çļĦ"
],
[
"Ġsent",
"ence"
],
[
"åĤ",
"¨"
],
[
"Ġr",
"out"
],
[
"Ġprovid",
"es"
],
[
"Ġag",
"ain"
],
[
"å®ł",
"çī©"
],
[
"éĢ",
"IJ"
],
[
"Ġyear",
"s"
],
[
"èŀ",
"į"
],
[
"Ġphys",
"ical"
],
[
"P",
"ython"
],
[
"ĠE",
"x"
],
[
"it",
"ing"
],
[
"è°ĥ",
"æķ´"
],
[
"ç½ij",
"绾"
],
[
"æħ",
"¢"
],
[
"空",
"éĹ´"
],
[
"åĽ",
"°"
],
[
"è±",
"Ĩ"
],
[
"æĽ´å¤ļ",
"çļĦ"
],
[
"ĠA",
"r"
],
[
"Ġmain",
"tain"
],
[
"å®ŀ",
"éĻħ"
],
[
"Ġtra",
"vel"
],
[
"Ġs",
"at"
],
[
"p",
"ro"
],
[
"ç͵",
"åŃIJ"
],
[
"æ±",
"½"
],
[
"e",
"x"
],
[
"åģ",
"ĩ"
],
[
"æIJ",
"Ń"
],
[
"éļı",
"çĿĢ"
],
[
"è¿ĺ",
"æľī"
],
[
"ç¤",
"¼"
],
[
"al",
"e"
],
[
"Ġcons",
"um"
],
[
"Ċ",
"Ġ"
],
[
"n",
"cy"
],
[
"Ġquest",
"ions"
],
[
"f",
"ort"
],
[
"m",
"aking"
],
[
"Ġdes",
"c"
],
[
"1",
"5"
],
[
"Ġinvol",
"ves"
],
[
"Ġst",
"ress"
],
[
"åŃĹ",
"符"
],
[
"he",
"re"
],
[
"Ġimpact",
"s"
],
[
"Ġex",
"ercis"
],
[
"åĿ",
"ļ"
],
[
"led",
"ge"
],
[
"ç§ij",
"æĬĢ"
],
[
"oc",
"i"
],
[
"Ġeffective",
"ly"
],
[
"æ¶Ī",
"è´¹"
],
[
"Ġconc",
"lusion"
],
[
"éĺ",
"ħ"
],
[
"Ġst",
"re"
],
[
"iss",
"ions"
],
[
"æ·",
"»"
],
[
"I",
"t"
],
[
"éĿ",
"Ļ"
],
[
"Ġv",
"irtual"
],
[
"è¡",
"£"
],
[
"Ġachie",
"ve"
],
[
"our",
"ce"
],
[
"è¿",
"ŀ"
],
[
"ac",
"ks"
],
[
"表",
"æł¼"
],
[
"Ġimport",
"ance"
],
[
"èĩª",
"æĪij"
],
[
"The",
"se"
],
[
"n",
"um"
],
[
"çļĦæ",
"ł"
],
[
"Ġrelations",
"hips"
],
[
"Ġwork",
"ers"
],
[
"g",
"ical"
],
[
"or",
"por"
],
[
"ers",
"on"
],
[
"åij",
"¢"
],
[
"nd",
"s"
],
[
"æİ¨",
"èįIJ"
],
[
"oh",
"n"
],
[
"å¿ħ",
"é¡»"
],
[
"容",
"æĺĵ"
],
[
"ĠG",
"o"
],
[
"Ġt",
"ell"
],
[
"ĠR",
"es"
],
[
"on",
"om"
],
[
"Ġbe",
"c"
],
[
"æ³",
"Ľ"
],
[
"p",
"os"
],
[
"Ġmo",
"ve"
],
[
"Ġst",
"ory"
],
[
"æŃ",
"¢"
],
[
"Ġprior",
"it"
],
[
"Ġindust",
"ries"
],
[
"è",
"ľ"
],
[
"Ġposs",
"ible"
],
[
"ĠM",
"an"
],
[
"Ġexp",
"ress"
],
[
"ab",
"ilities"
],
[
"Ġint",
"egr"
],
[
"代",
"表"
],
[
"Ġrespon",
"d"
],
[
"åĪĨ",
"éĴŁ"
],
[
"æľº",
"ä¼ļ"
],
[
"Ġth",
"ings"
],
[
"交",
"æµģ"
],
[
"Ġm",
"eth"
],
[
"ur",
"ther"
],
[
"Ġw",
"ide"
],
[
"èij",
"Ĺ"
],
[
"æĪij",
"çļĦ"
],
[
"ĸçķ",
"¥"
],
[
"id",
"es"
],
[
"eth",
"ing"
],
[
"ĠWh",
"ile"
],
[
"p",
"an"
],
[
"çŃ",
"ĸçķ¥"
],
[
"Ġc",
"ent"
],
[
"Ġp",
"lease"
],
[
"olo",
"gy"
],
[
"ura",
"cy"
],
[
"å¾",
"ª"
],
[
"w",
"ard"
],
[
"n",
"ce"
],
[
"Ġthe",
"n"
],
[
"çª",
"ģ"
],
[
"å¥",
"ĩ"
],
[
"Ġb",
"lo"
],
[
"a",
"i"
],
[
"æŀ",
"Ĺ"
],
[
"ç®Ĺ",
"æ³ķ"
],
[
"ç»",
"¼"
],
[
"Ġpr",
"int"
],
[
"ac",
"es"
],
[
"l",
"u"
],
[
"ª",
"æĸ½"
],
[
"p",
"re"
],
[
"çļĦæĦ",
"ı"
],
[
"Ġs",
"ol"
],
[
"Ġover",
"all"
],
[
"h",
"old"
],
[
"Ġ",
"es"
],
[
"çļĦ",
"ä¸Ģ"
],
[
"éģ",
"ĩ"
],
[
"Ġpop",
"ul"
],
[
"å°ı",
"说"
],
[
"æ³",
"¢"
],
[
"åį",
"ģ"
],
[
"ä¹Ł",
"åı¯ä»¥"
],
[
"é£Ł",
"åĵģ"
],
[
"Ġcont",
"ent"
],
[
"å°",
"Ħ"
],
[
"Ġrequ",
"ires"
],
[
"æ£Ģ",
"æŁ¥"
],
[
"ĊĠĠĠĠĠĠĠĠ",
"ĠĠĠ"
],
[
"Ġgrou",
"ps"
],
[
"Ġf",
"air"
],
[
"Ġb",
"l"
],
[
"å®ŀ",
"éªĮ"
],
[
"æĮī",
"çħ§"
],
[
"os",
"p"
],
[
"st",
"r"
],
[
"ä¸į",
"èĥ½"
],
[
"Ġh",
"arm"
],
[
"Ġpro",
"du"
],
[
"çļĦæĬ",
"Ģ"
],
[
"ç",
"ĩ"
],
[
"t",
"le"
],
[
"Ġanim",
"als"
],
[
"è§Ĵ",
"èī²"
],
[
"le",
"v"
],
[
"æ¸",
"IJ"
],
[
"å¤į",
"æĿĤ"
],
[
"Ġde",
"pend"
],
[
"æĮ",
"ijæĪĺ"
],
[
"åĮħ",
"åIJ«"
],
[
"Ġhelp",
"s"
],
[
"Ġop",
"en"
],
[
"Ġn",
"et"
],
[
"ĠĠĠĠ",
"Ġ"
],
[
"Ġstr",
"ong"
],
[
"Ġj",
"our"
],
[
"广",
"æ³Ľ"
],
[
"æķ´",
"个"
],
[
"Ġe",
"lect"
],
[
"Ġrespon",
"se"
],
[
"åįķ",
"è¯į"
],
[
"æľ",
"ĭ"
],
[
"Ġ",
"<"
],
[
"åĮĸ",
"åѦ"
],
[
"éĴ",
"Ī"
],
[
"Ġqu",
"ick"
],
[
"ual",
"ly"
],
[
"Ġsom",
"ething"
],
[
"Ġtra",
"ck"
],
[
"度",
"åĴĮ"
],
[
"eren",
"ces"
],
[
"æł",
"ij"
],
[
"Ġacc",
"uracy"
],
[
"Ġex",
"c"
],
[
"é£",
"ŀ"
],
[
"Ġfiel",
"d"
],
[
"寻",
"æī¾"
],
[
"éħ",
"¸"
],
[
"Ġh",
"ope"
],
[
"ç",
"ij"
],
[
"Ġin",
"nov"
],
[
"ç»",
"ª"
],
[
"al",
"k"
],
[
"Ġtyp",
"es"
],
[
"Ġd",
"id"
],
[
"åĬ",
"ª"
],
[
"Ġc",
"all"
],
[
"è¯",
"Ĺ"
],
[
"Ġear",
"ly"
],
[
"ĠO",
"ne"
],
[
"a",
"pp"
],
[
"Ġcomm",
"on"
],
[
"æľĢ",
"ç»Ī"
],
[
"Ġche",
"ck"
],
[
"Ġs",
"ym"
],
[
"çĤ",
"Ĵ"
],
[
"æĬĢ",
"èĥ½"
],
[
"Ġen",
"h"
],
[
"Ġag",
"ricult"
],
[
"Ġim",
"m"
],
[
"ç»",
"ĩ"
],
[
"满",
"è¶³"
],
[
"Ġs",
"chool"
],
[
"b",
"al"
],
[
"Ġfollow",
"ing"
],
[
"b",
"ased"
],
[
"Ġwe",
"bs"
],
[
"Ġcult",
"ure"
],
[
"ĠC",
"om"
],
[
"w",
"ay"
],
[
"ä¸Ģ",
"å®ļ"
],
[
"åķĨ",
"åĵģ"
],
[
"ud",
"e"
],
[
"çļĦ",
"åıijå±ķ"
],
[
"çĶŁ",
"产"
],
[
"os",
"ystem"
],
[
"Ġpl",
"ant"
],
[
"åı",
"¶"
],
[
"åIJ",
"ĥ"
],
[
"ä»ĸ",
"çļĦ"
],
[
"d",
"er"
],
[
"è¯",
"¢"
],
[
"å®¶",
"åħ·"
],
[
"Ġf",
"ree"
],
[
"ç§",
"»"
],
[
"æİ",
"Į"
],
[
"Ġb",
"ody"
],
[
"Ġp",
"resent"
],
[
"Ġpartic",
"ularly"
],
[
"Ġchild",
"ren"
],
[
"Ġstud",
"ent"
],
[
")",
"."
],
[
"çī¹",
"å¾ģ"
],
[
"è",
"Ķ"
],
[
"éĺħ",
"读"
],
[
"æķĪ",
"çİĩ"
],
[
"Ġprogra",
"m"
],
[
"éħ",
"±"
],
[
"åıĺ",
"å¾Ĺ"
],
[
"i",
"x"
],
[
"Ġcom",
"e"
],
[
"çļĦæ",
"²"
],
[
"ĠT",
"e"
],
[
"ĠT",
"o"
],
[
"åħ±",
"åIJĮ"
],
[
"Ġemploy",
"ees"
],
[
"说",
"æĺİ"
],
[
"Ġhe",
"art"
],
[
"Ġm",
"ot"
],
[
"æľĭ",
"åıĭ"
],
[
"er",
"ic"
],
[
"è¯",
"ij"
],
[
"Ġcur",
"rent"
],
[
"æĪIJ",
"æľ¬"
],
[
"Ġto",
"o"
],
[
"çİ©",
"å®¶"
],
[
"åĪĽ",
"æĸ°"
],
[
"Ġec",
"osystem"
],
[
"常",
"è§ģ"
],
[
"ä¸Ģ",
"æŃ¥"
],
[
"Ġp",
"res"
],
[
"Ġmult",
"i"
],
[
"åijĬ",
"è¯ī"
],
[
"ä¸",
"¥"
],
[
"Ġm",
"it"
],
[
"Ġact",
"ion"
],
[
"çĨ",
"Ł"
],
[
"Ġhab",
"it"
],
[
"åı£",
"æĦŁ"
],
[
"ç®",
"±"
],
[
"Ġus",
"es"
],
[
"å¢ŀ",
"强"
],
[
"ç»Ļ",
"åĩº"
],
[
"Ġ",
"9"
],
[
"Ġde",
"p"
],
[
"Ġeconom",
"ic"
],
[
"æĢ§",
"çļĦ"
],
[
"1",
"8"
],
[
"åĨ",
"°"
],
[
"Ġhelp",
"ed"
],
[
"åIJ¸",
"å¼ķ"
],
[
"çİ",
"ĭ"
],
[
"Ġdiagn",
"os"
],
[
"å",
"ł"
],
[
"èģĶ",
"ç³»"
],
[
"ç¾",
"¤"
],
[
"ç»ĥ",
"ä¹ł"
],
[
"æĪIJ",
"éķ¿"
],
[
"Ġpo",
"int"
],
[
"å®ļ",
"æľŁ"
],
[
"åij",
"¼"
],
[
"èį",
"¯"
],
[
"æĿ",
"¯"
],
[
"æ¤",
"Ĵ"
],
[
"æķĪ",
"æŀľ"
],
[
"Ġspec",
"ial"
],
[
"æ·",
"·"
],
[
"åĩł",
"个"
],
[
"aus",
"e"
],
[
"é",
"Ĩ"
],
[
"æ¯Ķ",
"èµĽ"
],
[
"è·",
"Ŀ"
],
[
"W",
"hat"
],
[
"Ġt",
"imes"
],
[
"ic",
"les"
],
[
"Ġ",
"*"
],
[
"ç´",
"§"
],
[
"å¦Ĥæŀľ",
"ä½ł"
],
[
"çĭ¬",
"çī¹"
],
[
"çģ",
"µ"
],
[
"ç¨",
"İ"
],
[
"Ġcar",
"bon"
],
[
"Ġbi",
"as"
],
[
"åĬ©",
"äºİ"
],
[
"Ġcon",
"st"
],
[
"èĩª",
"çͱ"
],
[
"æĿ¥",
"说"
],
[
"å°±",
"æĺ¯"
],
[
"åį",
"°"
],
[
"Ġme",
"et"
],
[
"è§Ħ",
"åĪĴ"
],
[
"çļĦç",
"¾"
],
[
"èIJ¥",
"åħ»"
],
[
"at",
"ors"
],
[
"稳",
"å®ļ"
],
[
"od",
"e"
],
[
"çħ",
"®"
],
[
"Ġass",
"oci"
],
[
"å¿",
"Ĺ"
],
[
"è¡Į",
"æĺŁ"
],
[
"æĿ",
"İ"
],
[
"Ġrev",
"iew"
],
[
"åĩ",
"Ģ"
],
[
"ĠR",
"o"
],
[
"Ġknow",
"ledge"
],
[
"以",
"便"
],
[
"æµĭ",
"è¯ķ"
],
[
"åIJĪ",
"éĢĤ"
],
[
"s",
"c"
],
[
"å½¢",
"å¼ı"
],
[
"Ġfriend",
"s"
],
[
"Ġnat",
"ure"
],
[
"Ġcrit",
"ical"
],
[
"æ´",
"ĭ"
],
[
"Ġa",
"fter"
],
[
"er",
"ve"
],
[
"Ġre",
"ce"
],
[
"çļĦæ",
"Ń"
],
[
"æ±½",
"车"
],
[
"çķ",
"Į"
],
[
"Ġlo",
"ss"
],
[
"Ġapp",
"lications"
],
[
"å¤ļ",
"ç§į"
],
[
"éĶ",
"ħ"
],
[
"ä¸",
"²"
],
[
"Ġins",
"p"
],
[
"--",
"-"
],
[
"ĠS",
"h"
],
[
"Ġv",
"ol"
],
[
"l",
"ut"
],
[
"o",
"ks"
],
[
"se",
"qu"
],
[
"Ġb",
"ir"
],
[
"åIJĪ",
"çIJĨ"
],
[
"Ġne",
"cess"
],
[
"æĪij",
"æĥ³"
],
[
"çŃī",
"æĸ¹éĿ¢"
],
[
"é¼",
"ĵ"
],
[
"Ġso",
"ft"
],
[
"Ġl",
"ive"
],
[
"å°ı",
"æĺİ"
],
[
"ĠI",
"nd"
],
[
"Ġbr",
"ing"
],
[
"æĺ¯",
"æĮĩ"
],
[
"Ġso",
"il"
],
[
"il",
"ar"
],
[
"ä¸",
"ľ"
],
[
"æĿ¡",
"ä»¶"
],
[
"Ġt",
"ri"
],
[
"äº",
"®"
],
[
"Ġm",
"om"
],
[
"æı",
"¡"
],
[
"ä¼",
"°"
],
[
"ŀ",
"äºī"
],
[
"çĽ",
"ij"
],
[
"èĤ",
"¤"
],
[
"è´¢",
"åĬ¡"
],
[
"æ·»",
"åĬł"
],
[
"饮",
"é£Ł"
],
[
"Ġallow",
"ing"
],
[
"åº",
"ķ"
],
[
"Ġr",
"ight"
],
[
"Ġexp",
"ert"
],
[
"Ġsu",
"pp"
],
[
"Ġin",
"it"
],
[
"çļĦæ",
"µ"
],
[
"ar",
"get"
],
[
"Ġexp",
"ect"
],
[
"Ġ1",
"9"
],
[
"Ġmeas",
"ures"
],
[
"olut",
"ions"
],
[
"j",
"ust"
],
[
"ar",
"c"
],
[
"å°",
"ļ"
],
[
"Ġpract",
"ice"
],
[
"æľī",
"åĬ©äºİ"
],
[
"大",
"éĩı"
],
[
"'",
","
],
[
"im",
"ent"
],
[
"Ġcontin",
"ue"
],
[
"Ġdisc",
"uss"
],
[
"1",
"00"
],
[
"éļ",
"ľ"
],
[
"çļĦæĦ",
"Ł"
],
[
"Ġref",
"lect"
],
[
"it",
"ation"
],
[
"åį",
"«"
],
[
"äºĨ",
"ä¸Ģ"
],
[
"ne",
"y"
],
[
"ĠL",
"e"
],
[
"is",
"ed"
],
[
"è¶",
"ĭ"
],
[
"äºĨ",
"ä¸Ģ个"
],
[
"Ġincre",
"asing"
],
[
"çļĦæ",
"Į"
],
[
"Ġst",
"ru"
],
[
"æĢ»",
"ç»ĵ"
],
[
"e",
"ly"
],
[
"å®",
"ĩ"
],
[
"Ġaut",
"hor"
],
[
"表",
"éĿ¢"
],
[
"Ġ",
"x"
],
[
"æķħ",
"äºĭ"
],
[
"em",
"ic"
],
[
"Ġrep",
"resent"
],
[
"g",
"er"
],
[
"Ġincre",
"ased"
],
[
"on",
"es"
],
[
"ain",
"s"
],
[
"Ġtrain",
"ed"
],
[
"Ġf",
"ish"
],
[
"Ġst",
"ate"
],
[
"åĨ",
"·"
],
[
"çĶŁ",
"éķ¿"
],
[
"Ġre",
"new"
],
[
"ord",
"ing"
],
[
"åĮ",
"Ĺ"
],
[
"æİ",
"ªæĸ½"
],
[
"å¹³",
"è¡¡"
],
[
"Ġsuccess",
"ful"
],
[
"ä¸ĭ",
"éĿ¢"
],
[
"Ġactiv",
"ity"
],
[
"èĮ",
"¶"
],
[
"éĢĤ",
"åºĶ"
],
[
"èĦ",
"ij"
],
[
"æİ¢",
"ç´¢"
],
[
"ff",
"ic"
],
[
"ç»Ħ",
"æĪIJ"
],
[
"at",
"ives"
],
[
"äº",
"ļ"
],
[
"Ġsc",
"en"
],
[
"æ²",
"Ļ"
],
[
"g",
"ress"
],
[
"使",
"å¾Ĺ"
],
[
"æī",
"¿"
],
[
"Ġdisc",
"rim"
],
[
"Ġassist",
"ants"
],
[
"Ġex",
"ist"
],
[
"çķ",
"Ļ"
],
[
"Ġsp",
"ace"
],
[
"æľĢ",
"è¿ij"
],
[
"Ġide",
"as"
],
[
"éĩĩ",
"åıĸ"
],
[
"l",
"ight"
],
[
"注",
"éĩį"
],
[
"çļĦæĹ¶",
"éĹ´"
],
[
"è¿",
"İ"
],
[
"Ġcom",
"b"
],
[
"éĢĤ",
"å½ĵ"
],
[
"Ġyour",
"self"
],
[
"rit",
"e"
],
[
"as",
"on"
],
[
"åĮ",
"Ģ"
],
[
"åı¯ä»¥",
"使ç͍"
],
[
"åħħ",
"满"
],
[
"Ġval",
"ues"
],
[
"æ",
"½"
],
[
"Ġbi",
"ases"
],
[
"ä¿ĥ",
"è¿Ľ"
],
[
"åľº",
"æĻ¯"
],
[
"ro",
"ss"
],
[
"åį³",
"åı¯"
],
[
"Ġc",
"ru"
],
[
"Ġnum",
"ber"
],
[
"Ġty",
"pe"
],
[
"r",
"ast"
],
[
"åĩĨ",
"ç¡®"
],
[
"Th",
"is"
],
[
"Ġp",
"ast"
],
[
"çģ",
"¯"
],
[
"å®ļ",
"ä¹ī"
],
[
"Ġs",
"olutions"
],
[
"Ġt",
"er"
],
[
"ä¿Ŀ",
"è¯ģ"
],
[
"èĶ",
"¬"
],
[
"å¹",
"¸"
],
[
"åī",
"§"
],
[
"åħ´",
"è¶£"
],
[
"å",
"ª"
],
[
"ent",
"ion"
],
[
"av",
"or"
],
[
"Ġsc",
"ient"
],
[
"åĬª",
"åĬĽ"
],
[
"Ġprovid",
"ers"
],
[
"Ġpolic",
"ies"
],
[
"al",
"u"
],
[
"ĠI",
"m"
],
[
"Ġallow",
"s"
],
[
"Ġintellig",
"ence"
],
[
"çļĦ",
"æĸ¹æ³ķ"
],
[
"è¿Ļ",
"æĺ¯"
],
[
"Ġ",
"`"
],
[
"Ġem",
"issions"
],
[
"Ġ",
"å°Ĩ"
],
[
"Ġmean",
"ing"
],
[
"Ġst",
"yle"
],
[
"åİŁ",
"åĽł"
],
[
"Ġstru",
"gg"
],
[
"çļĦç¾",
"İ"
],
[
"if",
"ul"
],
[
"dit",
"ion"
],
[
"éĥ½",
"æľī"
],
[
"空",
"æ°Ķ"
],
[
"å®ĥ们",
"çļĦ"
],
[
"ä¼ĺ",
"åĮĸ"
],
[
"Ġinf",
"lu"
],
[
"åŁº",
"äºİ"
],
[
"Ġdetail",
"s"
],
[
"Ġtranspare",
"ncy"
],
[
"Ġm",
"ess"
],
[
"ĠC",
"l"
],
[
"Ġg",
"ame"
],
[
"p",
"ri"
],
[
"è¶ĭ",
"åĬ¿"
],
[
"å½",
"Ĵ"
],
[
"ç¿»",
"è¯ij"
],
[
"æķ",
"£"
],
[
"B",
"y"
],
[
"é",
"Ń"
],
[
"ĠAm",
"eric"
],
[
"Ġproduct",
"ion"
],
[
"Ġinc",
"orpor"
],
[
"æĻ",
"ļ"
],
[
"Ġinvol",
"ve"
],
[
"Ġh",
"ot"
],
[
"æĻ",
"®"
],
[
"b",
"y"
],
[
"Ġf",
"low"
],
[
"Ġem",
"erg"
],
[
"åº",
"§"
],
[
"Ġide",
"a"
],
[
"åİĭ",
"åĬĽ"
],
[
"éĿ",
"Ĵ"
],
[
"om",
"s"
],
[
"èģĮ",
"ä¸ļ"
],
[
"Ġre",
"port"
],
[
"Ġp",
"ap"
],
[
"Ġthe",
"rap"
],
[
"Ġs",
"al"
],
[
"åıĤ",
"ä¸İ"
],
[
"æĸĩ",
"åѦ"
],
[
"æIJŃ",
"éħį"
],
[
"o",
"ot"
],
[
")",
","
],
[
"Ġc",
"r"
],
[
"Ġprocess",
"es"
],
[
"g",
"in"
],
[
"å¹³",
"åı°"
],
[
"å¯",
"Ł"
],
[
"Ġpromot",
"ing"
],
[
"æļ",
"ĸ"
],
[
"ake",
"hold"
],
[
"ç»",
"§"
],
[
"iv",
"er"
],
[
"æ",
"¦Ĥ"
],
[
"Ġmodel",
"s"
],
[
"Ġd",
"ra"
],
[
"è",
"ĸ"
],
[
"Ġgrou",
"p"
],
[
"è¶³",
"å¤Ł"
],
[
"Ġg",
"reen"
],
[
"Ġhealth",
"y"
],
[
"Ġcom",
"fort"
],
[
"Ġad",
"ditional"
],
[
"ä¸Ģ",
"次"
],
[
"é¤IJ",
"åİħ"
],
[
"Ġmaterial",
"s"
],
[
"Ġman",
"age"
],
[
"çļĦæ",
"¯"
],
[
"ä¼",
"¤"
],
[
"åıĬ",
"æĹ¶"
],
[
"Ġg",
"lo"
],
[
"Ġst",
"at"
],
[
"å¿«",
"éĢŁ"
],
[
"Ġmonitor",
"ing"
],
[
"ail",
"y"
],
[
"ra",
"nd"
],
[
"o",
"ice"
],
[
"res",
"h"
],
[
"ç»Ħ",
"ç»ĩ"
],
[
"Ġund",
"er"
],
[
"Ġnecess",
"ary"
],
[
"Ġhelp",
"ful"
],
[
"ĠC",
"ol"
],
[
"é»ij",
"æ´ŀ"
],
[
"åģļ",
"åĩº"
],
[
"Ġcour",
"se"
],
[
"Ġm",
"at"
],
[
"Ġle",
"g"
],
[
"Ġf",
"ace"
],
[
"ä»",
"¤"
],
[
"èī¯",
"好çļĦ"
],
[
"oc",
"k"
],
[
"åĮ»",
"çĸĹ"
],
[
"çĽ",
"ĸ"
],
[
"id",
"ence"
],
[
"Ġassoci",
"ated"
],
[
"Ġpro",
"gress"
],
[
"åľ",
"Ĩ"
],
[
"Ġevery",
"one"
],
[
"ç¼",
"ĵ"
],
[
"ĠEn",
"g"
],
[
"w",
"ord"
],
[
"èĵ",
"Ŀ"
],
[
"天",
"æ°Ķ"
],
[
"Ġact",
"ions"
],
[
"em",
"s"
],
[
"ĠP",
"l"
],
[
"å®",
"Ļ"
],
[
"us",
"h"
],
[
"é¡",
"¾"
],
[
"Ġcost",
"s"
],
[
"at",
"or"
],
[
"ç©",
"¿"
],
[
"Ġamount",
"s"
],
[
"èͬ",
"èıľ"
],
[
".",
"."
],
[
"Ġman",
"ner"
],
[
"Ġcon",
"sequ"
],
[
"æ°Ķ",
"åĢĻ"
],
[
"Ġins",
"ights"
],
[
"be",
"ing"
],
[
"at",
"ory"
],
[
"en",
"er"
],
[
"le",
"x"
],
[
"Ġme",
"ans"
],
[
"Ġcollabor",
"ation"
],
[
"Ġpers",
"pect"
],
[
"or",
"m"
],
[
"pri",
"ate"
],
[
"å°Ĭ",
"éĩį"
],
[
"Ġt",
"arget"
],
[
"è®°",
"å½ķ"
],
[
"åĢ",
"Ĵ"
],
[
"Ġrenew",
"able"
],
[
"æĦ",
"¿"
],
[
"èĥ½",
"æºIJ"
],
[
"Ġin",
"put"
],
[
"å®ĩ",
"å®Ļ"
],
[
"a",
"pe"
],
[
"Ġad",
"just"
],
[
"er",
"ies"
],
[
"Ġd",
"ire"
],
[
"ä¾",
"Ŀ"
],
[
"ust",
"r"
],
[
"f",
"ect"
],
[
"Ġbeaut",
"iful"
],
[
"Ġd",
"ue"
],
[
"re",
"ci"
],
[
"çĮ",
"®"
],
[
"èĥĮ",
"æĻ¯"
],
[
"èĤ",
"¡"
],
[
"Ġd",
"am"
],
[
"i",
"k"
],
[
"Ġadv",
"anced"
],
[
"缸",
"对"
],
[
"åIJį",
"ç§°"
],
[
"Ġsh",
"ort"
],
[
"Ġob",
"ject"
],
[
"è¿Ļ",
"éĩĮ"
],
[
"éĢł",
"æĪIJ"
],
[
"èIJ¥",
"éĶĢ"
],
[
"çļĦæĥħ",
"æĦŁ"
],
[
"ç¥",
"¨"
],
[
"Ġcount",
"ries"
],
[
"in",
"ing"
],
[
"ist",
"ic"
],
[
"Ġpl",
"ans"
],
[
"è´£",
"ä»»"
],
[
"Ġst",
"akehold"
],
[
"t",
"he"
],
[
"Ġass",
"ess"
],
[
"æĢĿ",
"èĢĥ"
],
[
"e",
"ch"
],
[
"æĪIJ",
"åijĺ"
],
[
"2",
"1"
],
[
"Ġd",
"aily"
],
[
"Ġcomp",
"ut"
],
[
"çļĦæĥħ",
"åĨµ"
],
[
"æıIJ",
"åĩº"
],
[
"Ġ",
"âĢľ"
],
[
"åª",
"Ĵ"
],
[
"ä¸Ń",
"å¿ĥ"
],
[
"is",
"hed"
],
[
"ĠS",
"e"
],
[
"onom",
"ous"
],
[
"er",
"n"
],
[
"ç»´",
"æĬ¤"
],
[
"am",
"es"
],
[
"Ġpriorit",
"ize"
],
[
"çº",
"¸"
],
[
"èĤ",
"¥"
],
[
"Ġtem",
"per"
],
[
"æ¸ħ",
"æ´ģ"
],
[
"us",
"e"
],
[
"æ±",
"¡"
],
[
"Ġmin",
"im"
],
[
"æĺ¯",
"åľ¨"
],
[
"大",
"å°ı"
],
[
"åĵª",
"äºĽ"
],
[
"Ġapp",
"reci"
],
[
"ren",
"g"
],
[
"Ġregul",
"ations"
],
[
"Ġ",
"Z"
],
[
"éĶĻ",
"误"
],
[
"r",
"ans"
],
[
"èĢĮ",
"ä¸Ķ"
],
[
"èĪ",
"¬"
],
[
"èij",
"±"
],
[
"è",
"Ĩ"
],
[
"æ°´",
"å¹³"
],
[
"è´Ń",
"çī©"
],
[
"åŃĹ符",
"串"
],
[
"对",
"æĸ¹"
],
[
"Ġh",
"im"
],
[
"Ġconsequ",
"ences"
],
[
"å·",
"´"
],
[
"é¼ĵ",
"åĬ±"
],
[
"Ġf",
"il"
],
[
"人",
"åijĺ"
],
[
"è·Ŀ",
"离"
],
[
"ĠW",
"hen"
],
[
"çļĦæ°",
"´"
],
[
"çī©",
"çIJĨ"
],
[
"åIJĮæĹ¶",
"ä¹Ł"
],
[
"åľ¨",
"è¿Ļ个"
],
[
"åħ¶",
"次"
],
[
",",
"\""
],
[
"æ¶",
"²"
],
[
"çĶ",
"·"
],
[
"iv",
"al"
],
[
"åı¯ä»¥",
"让"
],
[
"æĥ",
"¯"
],
[
"Ġadv",
"ance"
],
[
"Ġve",
"h"
],
[
"å¦Ĥæŀľ",
"æĤ¨"
],
[
"Ġest",
"ab"
],
[
"ri",
"pt"
],
[
"ç«",
"¯"
],
[
"ä¸į",
"ä¼ļ"
],
[
"Ġtranspare",
"nt"
],
[
"æķ°",
"éĩı"
],
[
"çĽ",
"ĺ"
],
[
"Ġspe",
"ak"
],
[
"Ġp",
"ark"
],
[
"Ġstakehold",
"ers"
],
[
"é",
"º"
],
[
"Ġev",
"ent"
],
[
"çļĦæķ°",
"æį®"
],
[
"èĩª",
"åĬ¨"
],
[
"ç»Ĩ",
"èĬĤ"
],
[
"è¯Ħ",
"ä¼°"
],
[
"æ¶",
"¦"
],
[
"Ġpref",
"erences"
],
[
"Ġve",
"get"
],
[
"æį",
"Ł"
],
[
"e",
"qu"
],
[
"Ġg",
"l"
],
[
"Ġp",
"ain"
],
[
"o",
"gra"
],
[
"Ġtra",
"ffic"
],
[
"Ġo",
"ce"
],
[
"ä¹",
"ĺ"
],
[
"e",
"xt"
],
[
"âĢĿ",
"ï¼Į"
],
[
"Ġan",
"other"
],
[
"å¤ļ",
"å°ij"
],
[
"Ġagain",
"st"
],
[
"ç»ı",
"åİĨ"
],
[
"计ç®Ĺ",
"æľº"
],
[
"èĢ",
"IJ"
],
[
"软",
"ä»¶"
],
[
"ĠP",
"re"
],
[
"Ġpl",
"ants"
],
[
"缸",
"äºĴ"
],
[
"é¢",
"ij"
],
[
"\\",
"_"
],
[
"Ġs",
"ame"
],
[
"ru",
"g"
],
[
"Ġval",
"u"
],
[
"Ġo",
"cc"
],
[
"çļĦç",
"¤"
],
[
"Ġsustain",
"ability"
],
[
"ĠS",
"he"
],
[
"d",
"e"
],
[
"ot",
"e"
],
[
"Ġd",
"ig"
],
[
"N",
"A"
],
[
"Ġcru",
"cial"
],
[
"æī",
"§"
],
[
"å±",
"Ģ"
],
[
"æĭ",
"Ł"
],
[
"æĭ",
"Į"
],
[
"Ġn",
"on"
],
[
"Ġeng",
"aging"
],
[
"Ġinter",
"n"
],
[
"L",
"P"
],
[
"温",
"度"
],
[
"æł",
"¸"
],
[
"æĬ¥",
"åijĬ"
],
[
"æĿ¥",
"è¶Ĭ"
],
[
"h",
"ood"
],
[
"ä¸ī",
"个"
],
[
"å¦Ĥ",
"ä¸ĭ"
],
[
"çī©",
"ä½ĵ"
],
[
"for",
"ce"
],
[
"Ġneed",
"ed"
],
[
"Ġim",
"ages"
],
[
"Ġbuild",
"ing"
],
[
"ici",
"ous"
],
[
"Ġ",
"æĪij"
],
[
"è¶Ĭ",
"æĿ¥è¶Ĭ"
],
[
"æĶ¾",
"åħ¥"
],
[
"g",
"o"
],
[
"éĻį",
"ä½İ"
],
[
"å½ĵ",
"åľ°"
],
[
"æ¶Īè´¹",
"èĢħ"
],
[
"ç",
"£"
],
[
"ivers",
"ity"
],
[
"é¢Ħ",
"ç®Ĺ"
],
[
"ic",
"le"
],
[
"æ··",
"åIJĪ"
],
[
"Ġpartic",
"ip"
],
[
"Ġdis",
"hes"
],
[
"Ġthrough",
"out"
],
[
"Ġwith",
"in"
],
[
"åı",
"³"
],
[
"é«ĺ",
"çļĦ"
],
[
"Ġph",
"ot"
],
[
"Ġtr",
"ust"
],
[
"æĦı",
"è¯Ĩ"
],
[
"以",
"ç¡®ä¿Ŀ"
],
[
"çĬ¶",
"æĢģ"
],
[
"Ġautom",
"ation"
],
[
"1",
"1"
],
[
"Ġpo",
"st"
],
[
"æīĭ",
"æľº"
],
[
"wor",
"ks"
],
[
"éĢ",
"ı"
],
[
"åº",
"ĵ"
],
[
"Ġw",
"ind"
],
[
"Ġ=",
"="
],
[
"Ġprocess",
"ing"
],
[
"èĮĥ",
"åĽ´"
],
[
"æĦı",
"ä¹ī"
],
[
"追",
"æ±Ĥ"
],
[
"Ã",
"©"
],
[
"å¾",
"Ħ"
],
[
"éĿ",
"ł"
],
[
"ä¸",
"ĸ"
],
[
"èĻ",
"½"
],
[
"ç«",
"ŀäºī"
],
[
"Ġappro",
"priate"
],
[
"æĽ´",
"好çļĦ"
],
[
"Ġcharact",
"er"
],
[
"c",
"l"
],
[
"ç§",
"ĺ"
],
[
"it",
"ude"
],
[
"Ġte",
"ac"
],
[
"le",
"ep"
],
[
"ĠDe",
"velop"
],
[
"in",
"ce"
],
[
"å·",
"¦"
],
[
"g",
"round"
],
[
"è¡Į",
"ä¸ļ"
],
[
"éĴĪ",
"对"
],
[
"å¿ħ",
"è¦ģ"
],
[
"Ġdet",
"erm"
],
[
"--------",
"--------"
],
[
"Ġst",
"reng"
],
[
"d",
"o"
],
[
"Ġchalleng",
"ing"
],
[
"or",
"k"
],
[
"Ġan",
"x"
],
[
"èī²",
"çļĦ"
],
[
"Ġh",
"ard"
],
[
"æĺİ",
"ç¡®"
],
[
"åĪĨ",
"享"
],
[
"æĶ¹",
"åıĺ"
],
[
"ä½",
"³"
],
[
"åıª",
"æľī"
],
[
"å±ķ",
"示"
],
[
"Ġcam",
"p"
],
[
"çº",
"³"
],
[
"a",
"j"
],
[
"et",
"ic"
],
[
"u",
"ment"
],
[
"ä½ł",
"åı¯ä»¥"
],
[
"Ġpol",
"lut"
],
[
"Ġh",
"ig"
],
[
"pp",
"ing"
],
[
"e",
"ad"
],
[
"çĦ¶",
"èĢĮ"
],
[
"第",
"äºĮ"
],
[
"é¸",
"Ł"
],
[
"çī©",
"åĵģ"
],
[
"ä¸",
"¾"
],
[
"Ġencoura",
"ge"
],
[
"pe",
"cial"
],
[
"Ġac",
"ross"
],
[
"el",
"ves"
],
[
"äºĭ",
"ä»¶"
],
[
"c",
"le"
],
[
"æ",
"©"
],
[
"åªĴ",
"ä½ĵ"
],
[
"n",
"ers"
],
[
"Ġc",
"al"
],
[
"èϽ",
"çĦ¶"
],
[
"åĽ",
"º"
],
[
"ä¹ł",
"æĥ¯"
],
[
"Ġsaf",
"e"
],
[
"èĥ½",
"éĩı"
],
[
"ist",
"ics"
],
[
"ä¹ĭ",
"åīį"
],
[
"Ġiss",
"ue"
],
[
"å¤ļ",
"个"
],
[
"åĨ³",
"çŃĸ"
],
[
"è¾¾",
"åΰ"
],
[
"æĹ",
"©"
],
[
"ä¸į",
"åı¯"
],
[
"ä¸Ģ",
"缴"
],
[
"å·",
"¨"
],
[
"æĦŁ",
"è°¢"
],
[
"ĠN",
"ew"
],
[
"ä¸Ģ",
"段"
],
[
"Ġmach",
"ines"
],
[
"å°Ĩ",
"åħ¶"
],
[
"ç»§",
"ç»Ń"
],
[
"Ġwor",
"d"
],
[
"çī¹",
"åĪ«"
],
[
"Ġagricult",
"ure"
],
[
"æĢ",
"İ"
],
[
"éĢIJ",
"æ¸IJ"
],
[
"éĵ",
"¾"
],
[
"è¯",
"¾"
],
[
"Ġk",
"ind"
],
[
"å¢",
"Ļ"
],
[
"è°¢",
"è°¢"
],
[
"Ġalgorith",
"m"
],
[
"è£ħ",
"饰"
],
[
"Ġal",
"ong"
],
[
"Ġeas",
"y"
],
[
"äº",
"ij"
],
[
"è§£åĨ³",
"æĸ¹æ¡Ī"
],
[
"Ġaware",
"ness"
],
[
"'",
"ve"
],
[
"æĸ¹",
"åIJij"
],
[
"Ġne",
"ver"
],
[
"Ġquick",
"ly"
],
[
"Ġres",
"pect"
],
[
"çļĦæ",
"Ļ"
],
[
"Ġam",
"ong"
],
[
"Ġaccount",
"ability"
],
[
"Ġl",
"aw"
],
[
"en",
"ing"
],
[
"Ġdef",
"in"
],
[
"Ġsur",
"round"
],
[
"éĵ",
"ģ"
],
[
"Ġpower",
"ful"
],
[
"A",
"n"
],
[
"Ġcaus",
"e"
],
[
"æ",
"¥"
],
[
"æİĮ",
"æı¡"
],
[
"è¿ĺ",
"æĺ¯"
],
[
"Ġcreat",
"ive"
],
[
"è¡",
"Ģ"
],
[
"Ġloc",
"ated"
],
[
"un",
"ning"
],
[
"åľ°",
"åĮº"
],
[
"éĿ¢",
"积"
],
[
"éĽ",
"¨"
],
[
"Ġne",
"ar"
],
[
"Ġinit",
"i"
],
[
"ress",
"ion"
],
[
"ä¸ĭ",
"æĿ¥"
],
[
"2",
"5"
],
[
"é©",
"¶"
],
[
"¾",
"çĹħ"
],
[
"ab",
"les"
],
[
"æľī",
"è¶£"
],
[
"循",
"çݯ"
],
[
"çŃĶ",
"æ¡Ī"
],
[
"çł",
"´"
],
[
"ic",
"ation"
],
[
"éĻ",
"¢"
],
[
"æ²»",
"çĸĹ"
],
[
"Ġad",
"dition"
],
[
"äºĭ",
"æĥħ"
],
[
"Ġbec",
"ause"
],
[
"åı",
"Ī"
],
[
"èĤ",
"Į"
],
[
"çº",
"ª"
],
[
"s",
"ide"
],
[
"æĭ",
"ħ"
],
[
"æ¹",
"¿"
],
[
"åį",
"Ĭ"
],
[
"é¡",
"º"
],
[
"ĠA",
"nd"
],
[
"Ġrestaur",
"ant"
],
[
"Ġv",
"ide"
],
[
"Ġproble",
"m"
],
[
"az",
"ing"
],
[
"Ġmem",
"bers"
],
[
"Ġn",
"ut"
],
[
"Ġc",
"ou"
],
[
"æµ",
"ª"
],
[
"Ġ",
"è¿Ļ"
],
[
"Ġhelp",
"ing"
],
[
"ĠI",
"s"
],
[
"æıIJ",
"åįĩ"
],
[
"ĠĠĠĠ",
"ĠĠ"
],
[
"Ġsh",
"o"
],
[
"Ġre",
"lev"
],
[
"Ġar",
"g"
],
[
"Ġbal",
"ance"
],
[
"ill",
"ed"
],
[
"æĺ¯",
"ä»Ģä¹Ī"
],
[
"åĬĽ",
"éĩı"
],
[
"ire",
"d"
],
[
"å¤",
"ľ"
],
[
"åı¯",
"æĮģç»Ń"
],
[
"Ġper",
"fect"
],
[
"*",
"*"
],
[
"ific",
"ation"
],
[
"æ¶",
"ī"
],
[
"Ġwild",
"life"
],
[
"an",
"e"
],
[
"Ġrel",
"ated"
],
[
"室",
"åĨħ"
],
[
"åº",
"ľ"
],
[
"享",
"åıĹ"
],
[
"our",
"s"
],
[
"è·",
"ij"
],
[
"åķĨ",
"ä¸ļ"
],
[
"ach",
"ing"
],
[
"Ġsu",
"n"
],
[
"Ġrecogn",
"ition"
],
[
"el",
"t"
],
[
"Ġor",
"der"
],
[
"å¹³",
"åĿĩ"
],
[
"g",
"ing"
],
[
"ä¸",
"´"
],
[
"çĤ",
"¼"
],
[
"Ġgo",
"ing"
],
[
"åij¼",
"åIJ¸"
],
[
"Ġsoft",
"ware"
],
[
"Ġre",
"mot"
],
[
"èijĹ",
"åIJį"
],
[
"幸",
"ç¦ı"
],
[
"Ġenh",
"ance"
],
[
"èĻ",
"ļ"
],
[
"Ġn",
"ow"
],
[
"Ġth",
"reat"
],
[
"Ġd",
"est"
],
[
"åĿĩ",
"åĮĢ"
],
[
"Ġac",
"ad"
],
[
"åºĶ",
"对"
],
[
"çľĭ",
"åΰ"
],
[
"c",
"ast"
],
[
"è¾",
"Ĩ"
],
[
"ific",
"ial"
],
[
"Ġ",
"very"
],
[
"o",
"ok"
],
[
"åĮº",
"åŁŁ"
],
[
"¹",
"ģ"
],
[
"æĪ¿",
"éĹ´"
],
[
"æıIJä¾Ľ",
"äºĨ"
],
[
"Ġmot",
"iv"
],
[
"Ġaccess",
"ible"
],
[
"åĨ³",
"å®ļ"
],
[
"Ġh",
"y"
],
[
"å®",
"Ī"
],
[
"Ġf",
"lo"
],
[
"u",
"g"
],
[
"Ġinform",
"ed"
],
[
"åĵģ",
"è´¨"
],
[
"çļĦç",
"Ł"
],
[
"av",
"es"
],
[
"ar",
"r"
],
[
"ĠW",
"ith"
],
[
"le",
"t"
],
[
"è§Ĥ",
"çĤ¹"
],
[
"en",
"ge"
],
[
"è¡Į",
"åĬ¨"
],
[
"f",
"riend"
],
[
"ç³",
"ķ"
],
[
"Ġf",
"urther"
],
[
"ĠE",
"ns"
],
[
"ç§",
"ģ"
],
[
"Ġad",
"o"
],
[
"Ġcle",
"an"
],
[
"缸",
"åºĶ"
],
[
"Ġf",
"re"
],
[
"pecial",
"ly"
],
[
"è",
"Ĺ"
],
[
"Ġc",
"apt"
],
[
"çļĦç",
"ľ"
],
[
"Ġsome",
"one"
],
[
"Ġc",
"ell"
],
[
"æĶ¾",
"åľ¨"
],
[
"欢",
"è¿İ"
],
[
"Ġ",
"âĢ"
],
[
"Ġdev",
"ices"
],
[
"çļĦ",
"æĸ¹å¼ı"
],
[
"Ġjob",
"s"
],
[
"au",
"gh"
],
[
"n",
"ot"
],
[
"æľī",
"äºĽ"
],
[
"åħ¬",
"åħ±"
],
[
"g",
"est"
],
[
"çļĦ",
"çĶŁæ´»"
],
[
"çľ",
"¼"
],
[
"çļĦ",
"ä¿¡æģ¯"
],
[
"ĠC",
"ons"
],
[
"æİĴ",
"åºı"
],
[
"Ġbenef",
"it"
],
[
"re",
"ct"
],
[
"å¤",
"ı"
],
[
"un",
"te"
],
[
"符",
"åIJĪ"
],
[
"ä¸Ģ",
"ä½į"
],
[
"åĨħ",
"éĥ¨"
],
[
"Ġlook",
"ing"
],
[
"d",
"ing"
],
[
"æĬ",
"ĺ"
],
[
"è¾",
"ij"
],
[
"è¿Ļ个",
"éĹ®é¢ĺ"
],
[
"Ġes",
"pecially"
],
[
"çľ",
"ł"
],
[
"âĢĿ",
"ãĢĤ"
],
[
"å¥",
"ı"
],
[
"ra",
"y"
],
[
"è¿ĺ",
"åı¯ä»¥"
],
[
"åĪĽ",
"ä½ľ"
],
[
"com",
"ing"
],
[
"Ġmulti",
"ple"
],
[
"éļ",
"IJ"
],
[
"æ³",
"¡"
],
[
"æłĩ",
"åĩĨ"
],
[
"Ġm",
"il"
],
[
"éľĢè¦ģ",
"注æĦı"
],
[
"Ġanx",
"iety"
],
[
"æĶ¹",
"è¿Ľ"
],
[
"å±",
"ĭ"
],
[
"污",
"æŁĵ"
],
[
"ç¼ĸ",
"ç¨ĭ"
],
[
"è´¹",
"ç͍"
],
[
"Ġev",
"alu"
],
[
"imate",
"ly"
],
[
"Ġlit",
"er"
],
[
"ogra",
"ph"
],
[
"Ġse",
"arch"
],
[
"1",
"6"
],
[
"en",
"ced"
],
[
"Ġmeth",
"ods"
],
[
"çĥ",
"Ī"
],
[
"模",
"å¼ı"
],
[
"çĬ¶",
"åĨµ"
],
[
"æĶ¹",
"åĸĦ"
],
[
"å¤ļ",
"æł·"
],
[
"c",
"er"
],
[
"å¥",
"ĸ"
],
[
"Ġsat",
"is"
],
[
"Ġwebs",
"ite"
],
[
"åĬ",
"ŀ"
],
[
"åģ¥",
"身"
],
[
"Ġglo",
"bal"
],
[
"Ġas",
"k"
],
[
"Ġplatform",
"s"
],
[
"Ġdise",
"ases"
],
[
"çݰ",
"象"
],
[
"t",
"ics"
],
[
"æ±",
"ģ"
],
[
"åΤ",
"æĸŃ"
],
[
"Ġcon",
"vers"
],
[
"Ġrelations",
"hip"
],
[
"设",
"ç½®"
],
[
"æ³ķ",
"å¾ĭ"
],
[
"Ġmind",
"ful"
],
[
"é¢Ħ",
"æµĭ"
],
[
"o",
"very"
],
[
"åģ",
"ľ"
],
[
"ç͵",
"è§Ĩ"
],
[
"è§Ħ",
"åĪĻ"
],
[
"ak",
"en"
],
[
"Ġimplement",
"ing"
],
[
"is",
"ing"
],
[
"åıĤ",
"åĬł"
],
[
"æĥħ",
"绪"
],
[
"Ġprovid",
"ed"
],
[
"æ·±",
"åħ¥"
],
[
"Ġprogramm",
"ed"
],
[
"Ġrelev",
"ant"
],
[
"çļĦç",
"ĥ"
],
[
"çĸ",
"¾çĹħ"
],
[
"åĮ»",
"çĶŁ"
],
[
"åĪĽ",
"建"
],
[
"Ġgener",
"ate"
],
[
"æĶ¶",
"åħ¥"
],
[
"ä¼",
"ij"
],
[
"iz",
"es"
],
[
"Ġtrans",
"form"
],
[
"éģ",
"µ"
],
[
"ast",
"ic"
],
[
"åij",
"Ī"
],
[
"æ¯ı",
"个人"
],
[
"è¿",
"Ķ"
],
[
"i",
"et"
],
[
"Ġv",
"oice"
],
[
"éĢ",
"Ķ"
],
[
"æĶ¾",
"æĿ¾"
],
[
"åį",
"´"
],
[
"èĥ",
"ľ"
],
[
"Ġst",
"ructure"
],
[
"æĹ¶",
"å°ļ"
],
[
"Ġ",
"Q"
],
[
"Ġel",
"se"
],
[
"du",
"c"
],
[
"Ġem",
"p"
],
[
"èģ",
"ļ"
],
[
"è´",
"§"
],
[
"ac",
"hes"
],
[
"ç§",
"Ģ"
],
[
"an",
"ks"
],
[
"Ġn",
"ight"
],
[
"Ġprofessional",
"s"
],
[
"Ġb",
"as"
],
[
"è´",
"µ"
],
[
"e",
"c"
],
[
"Ġdivers",
"ity"
],
[
"it",
"es"
],
[
"d",
"r"
],
[
"åĽ°",
"éļ¾"
],
[
"ĥ",
"åľ"
],
[
"åŀ",
"ĥåľ"
],
[
"åŀĥåľ",
"¾"
],
[
"Ġd",
"rug"
],
[
"ç¢",
"³"
],
[
"Ġn",
"ame"
],
[
"åĮĸ",
"çļĦ"
],
[
"a",
"id"
],
[
"æľĢ",
"大"
],
[
"æij",
"Ħ"
],
[
"ç®Ģåįķ",
"çļĦ"
],
[
"Ġw",
"arm"
],
[
"Ġd",
"one"
],
[
"Ġfun",
"ction"
],
[
"as",
"c"
],
[
"强",
"è°ĥ"
],
[
"Ġdem",
"and"
],
[
"Ġvis",
"ual"
],
[
"Ġup",
"d"
],
[
"æŃ£",
"åľ¨"
],
[
"Ġsim",
"ilar"
],
[
"éĢ",
"Ĵ"
],
[
"æ¯",
"Ľ"
],
[
"éĶ",
"»"
],
[
"ent",
"ly"
],
[
"Ġvalu",
"able"
],
[
"Ġdis",
"aster"
],
[
"ä¸Ģ",
"èά"
],
[
"æ´",
"²"
],
[
"ĠR",
"eg"
],
[
"Ġdiscrim",
"ination"
],
[
"åĨĻ",
"ä¸Ģç¯ĩ"
],
[
"Ġgovern",
"ment"
],
[
"Ġ",
"好çļĦ"
],
[
"5",
"00"
],
[
"ly",
"ing"
],
[
"Ġpre",
"v"
],
[
"Ġpre",
"pare"
],
[
"Ġproble",
"ms"
],
[
"è·",
"³"
],
[
"Ġpro",
"m"
],
[
"åĨ",
"²"
],
[
"å®ī",
"è£ħ"
],
[
"éĶ»",
"çĤ¼"
],
[
"æµ",
"ĵ"
],
[
"è",
"¹"
],
[
"åºĶç͍",
"ç¨ĭåºı"
],
[
"n",
"g"
],
[
"Ġcomp",
"et"
],
[
"åĪĨ",
"åĪ«"
],
[
"olo",
"gical"
],
[
"å®",
"¡"
],
[
"Ġtrans",
"l"
],
[
"Ġdire",
"ct"
],
[
"åī",
"Ĥ"
],
[
"Ġsuggest",
"ions"
],
[
"Ġpap",
"er"
],
[
"Ġrecogn",
"ize"
],
[
"t",
"on"
],
[
"Ġmit",
"igate"
],
[
"讨",
"论"
],
[
"äºĴ",
"åĬ¨"
],
[
"ĠE",
"ar"
],
[
"Ġam",
"azing"
],
[
"c",
"re"
],
[
"é¦",
"Ī"
],
[
"Ġinvol",
"ved"
],
[
"f",
"ace"
],
[
"æľī",
"åħ³"
],
[
")",
")"
],
[
"Ġex",
"ce"
],
[
"Ġproduct",
"ivity"
],
[
"è",
"Ń"
],
[
"é¦",
"Ĩ"
],
[
"Ġsound",
"s"
],
[
"Ġidentify",
"ing"
],
[
"]",
","
],
[
"é¾",
"Ļ"
],
[
"Ġf",
"it"
],
[
"Ġcontribut",
"e"
],
[
"th",
"s"
],
[
"friend",
"ly"
],
[
"e",
"le"
],
[
"if",
"ied"
],
[
"iven",
"ess"
],
[
"ite",
"ly"
],
[
"Ġ",
"X"
],
[
"Ġl",
"ed"
],
[
"åĿ",
"ı"
],
[
"Ġhist",
"or"
],
[
"Ġd",
"at"
],
[
"Ġjour",
"ney"
],
[
"Ġ",
"}"
],
[
"Ġse",
"lect"
],
[
"æ¼",
"«"
],
[
"Ġcon",
"duct"
],
[
"è¿Ľ",
"ä¸ĢæŃ¥"
],
[
"ç»Ļ",
"æĪij"
],
[
"Ġl",
"if"
],
[
"è£ħ",
"ä¿®"
],
[
"为",
"ä»Ģä¹Ī"
],
[
"äº",
"¬"
],
[
"Ġn",
"av"
],
[
"Ġwho",
"le"
],
[
"ç",
"¹ģ"
],
[
"åĨ",
"ľ"
],
[
"æĶ",
"»"
],
[
"Ġb",
"reat"
],
[
"Ġm",
"iss"
],
[
"é¾",
"Ħ"
],
[
"t",
"t"
],
[
"s",
"w"
],
[
"Ġb",
"ar"
],
[
"请",
"éĹ®"
],
[
"èģĶ",
"ç½ij"
],
[
"Ġatt",
"ract"
],
[
"æĤ¨",
"åı¯ä»¥"
],
[
"O",
"ne"
],
[
"åħħ",
"åĪĨ"
],
[
"r",
"ing"
],
[
"Ġå½ĵ",
"çĦ¶"
],
[
"re",
"am"
],
[
"Ġev",
"ol"
],
[
"Ġs",
"n"
],
[
"ĠE",
"m"
],
[
"m",
"osp"
],
[
"Ġcho",
"ose"
],
[
"v",
"iew"
],
[
"Ġar",
"r"
],
[
"Ġs",
"leep"
],
[
"end",
"ed"
],
[
"æŀ",
"¶"
],
[
"Ġveh",
"icles"
],
[
"Ġf",
"resh"
],
[
"Ġorganiz",
"ation"
],
[
"è¿Ļ",
"段"
],
[
"æ±",
"¤"
],
[
"ĠI",
"nt"
],
[
"Ġcont",
"ext"
],
[
"åı¦",
"å¤ĸ"
],
[
"Ġoce",
"an"
],
[
"æĦŁ",
"åıĹ"
],
[
"Ġpollut",
"ion"
],
[
"ur",
"b"
],
[
"æī§",
"è¡Į"
],
[
"erson",
"al"
],
[
"ĠHe",
"alth"
],
[
"ä¼ĺ",
"çĤ¹"
],
[
"Ġatt",
"ention"
],
[
"æľī",
"çĿĢ"
],
[
"é£Ł",
"æĿIJ"
],
[
"Ġer",
"r"
],
[
"çļĦæĿ",
"¥"
],
[
"çļĦç",
"Ī"
],
[
"èŃ",
"¦"
],
[
"è·",
"Ł"
],
[
"æĹħ",
"è¡Į"
],
[
"èĴ",
"ľ"
],
[
"çļĦæĢ",
"Ŀ"
],
[
"Ġchat",
"bot"
],
[
"çļĦ",
"éľĢæ±Ĥ"
],
[
"çķ",
"¥"
],
[
"Ġfeel",
"ing"
],
[
"Ġimplement",
"ed"
],
[
"社",
"åĮº"
],
[
"çļĦ",
"建议"
],
[
"æIJ",
"ħ"
],
[
"éĹ",
"»"
],
[
"åıį",
"é¦Ī"
],
[
"缴",
"æİ¥"
],
[
"æĺ",
"¥"
],
[
"it",
"able"
],
[
"æĪij",
"ä¼ļ"
],
[
"åį",
"±"
],
[
"èī¯",
"好"
],
[
"Ġl",
"iving"
],
[
"åıĺ",
"éĩı"
],
[
"ĠB",
"ut"
],
[
"Ġcomple",
"te"
],
[
"Ġtre",
"nds"
],
[
"Ġm",
"akes"
],
[
"ä»Ĭ",
"天"
],
[
"Ġdist",
"ribut"
],
[
"Ġcomm",
"it"
],
[
"Ġat",
"mosp"
],
[
"ä¼",
"´"
],
[
"Ġsens",
"ors"
],
[
"Ġs",
"w"
],
[
"æĹł",
"论"
],
[
"om",
"en"
],
[
"æĶ¿",
"åºľ"
],
[
"Ġchall",
"enge"
],
[
"Ġt",
"urn"
],
[
"çIJĨ",
"论"
],
[
"p",
"ar"
],
[
"Ġwrit",
"e"
],
[
"ç»ı",
"åħ¸"
],
[
"em",
"ember"
],
[
"é¥",
"Ń"
],
[
"æĸ¹",
"便"
],
[
"Ġc",
"u"
],
[
"Ġval",
"ue"
],
[
"Ġf",
"und"
],
[
"p",
"ose"
],
[
"è°ĥ",
"æŁ¥"
],
[
"çĿ",
"¡"
],
[
"Ġcommunic",
"ate"
],
[
"Ġdise",
"ase"
],
[
"Ġrese",
"arc"
],
[
"Ġl",
"ack"
],
[
"arn",
"ing"
],
[
"ĠP",
"ark"
],
[
"çĦ",
"¦"
],
[
"é«ĺ",
"度"
],
[
"Ġr",
"ather"
],
[
"å®",
"£"
],
[
"çĪ",
"¶"
],
[
"éĺ",
"¶"
],
[
"è®",
"¢"
],
[
"çĥ",
"§"
],
[
"Ġhig",
"her"
],
[
"Ġsumm",
"ary"
],
[
"ĠA",
"ut"
],
[
"çļĦæ",
"³"
],
[
"Ġe",
"le"
],
[
"is",
"ms"
],
[
"Ġrel",
"i"
],
[
"ä¹Ł",
"ä¼ļ"
],
[
"f",
"ra"
],
[
"åijĬè¯ī",
"æĪij"
],
[
"æĬ",
"½"
],
[
"Ġsitu",
"ations"
],
[
"Ġmar",
"ine"
],
[
"æĥ³",
"è¦ģ"
],
[
"in",
"ci"
],
[
"in",
"al"
],
[
"Ġg",
"ain"
],
[
"Ġdiffere",
"nce"
],
[
"æľºåύ",
"人"
],
[
"æµģ",
"ç¨ĭ"
],
[
"ĠC",
"hat"
],
[
"ç½ij",
"ç«Ļ"
],
[
"æľ",
"«"
],
[
"Ġcol",
"or"
],
[
"Ġas",
"pect"
],
[
"ç½",
"Ĺ"
],
[
"ĠE",
"duc"
],
[
"Ġde",
"ploy"
],
[
"Ġbeaut",
"y"
],
[
"æĤ",
"£"
],
[
"ruct",
"ion"
],
[
"it",
"ut"
],
[
"æĿ",
"Ł"
],
[
"让",
"æĪij们"
],
[
"éķ¿",
"度"
],
[
"ul",
"es"
],
[
"æ¶ī",
"åıĬ"
],
[
"Ġdig",
"ital"
],
[
"Ġexist",
"ing"
],
[
"ĠO",
"r"
],
[
"\\_",
"\\_"
],
[
"Ġback",
"ground"
],
[
"çĹ",
"ĩ"
],
[
"æ¯ı",
"天"
],
[
"p",
"ython"
],
[
"Ġfarm",
"ers"
],
[
"Ġcontin",
"u"
],
[
"\"",
":"
],
[
"Ġg",
"iven"
],
[
"å°ı",
"æĹ¶"
],
[
"Ġmom",
"ent"
],
[
"2",
"00"
],
[
"J",
"ohn"
],
[
"éĿ¢",
"对"
],
[
"Ġint",
"ro"
],
[
"Ġtherap",
"y"
],
[
"è¿Ķ",
"åĽŀ"
],
[
"å¹¶",
"åľ¨"
],
[
"Ġ",
"z"
],
[
"Ġaff",
"ord"
],
[
"ä¸",
"Ŀ"
],
[
"å®",
"½"
],
[
"Ġ",
"Ã"
],
[
"ĠN",
"ational"
],
[
"èĥ",
"¡"
],
[
"Ġexercis",
"e"
],
[
"æIJħ",
"æĭĮ"
],
[
"æĶ¯",
"ä»ĺ"
],
[
"éĺ³",
"åħī"
],
[
"è¯",
"ļ"
],
[
"Ġs",
"ect"
],
[
"ĠS",
"u"
],
[
"å¢ŀ",
"éķ¿"
],
[
"ç¾İ",
"丽"
],
[
"Ġw",
"a"
],
[
"以ä¸ĭæĺ¯",
"ä¸ĢäºĽ"
],
[
"èĽĭ",
"ç³ķ"
],
[
"Ġ",
"ill"
],
[
"æ¸ħ",
"æĻ"
],
[
"et",
"ry"
],
[
"æ¢",
"¦"
],
[
"ç¾İ",
"åĽ½"
],
[
"ä»",
"į"
],
[
"one",
"y"
],
[
"Ġecosystem",
"s"
],
[
"æĮĩ",
"导"
],
[
"d",
"ef"
],
[
"9",
"9"
],
[
"æŁ",
"Ķ"
],
[
"pp",
"ed"
],
[
"Ġlim",
"it"
],
[
"çİ",
"ī"
],
[
"Ġacad",
"emic"
],
[
"Ġrestaur",
"ants"
],
[
"Ġhe",
"ad"
],
[
"ä¿¡",
"ä»»"
],
[
"ast",
"ers"
],
[
"å²",
"ģ"
],
[
"ak",
"ers"
],
[
"1",
"4"
],
[
"A",
"s"
],
[
"æł",
"¡"
],
[
"é«ĺ",
"æķĪ"
],
[
"ph",
"as"
],
[
"y",
"n"
],
[
"ç¨ĭ",
"度"
],
[
"è¾",
"£"
],
[
"ä¸Ĭ",
"éĿ¢"
],
[
"å®¶",
"å±ħ"
],
[
"ter",
"m"
],
[
"ç¾İ",
"é£Ł"
],
[
"Ġo",
"vers"
],
[
"å®",
"ĺ"
],
[
"Ġind",
"ic"
],
[
"ĠY",
"our"
],
[
"S",
"t"
],
[
"å½¢",
"象"
],
[
"è´",
"¡"
],
[
"åº",
"Ĭ"
],
[
"ĠS",
"c"
],
[
"ag",
"ra"
],
[
"羣",
"æŃ£"
],
[
"o",
"int"
],
[
"id",
"s"
],
[
"are",
"nt"
],
[
"éĵ",
"¶"
],
[
"èģ",
"Ĭ"
],
[
"Ġreg",
"ular"
],
[
"ä¼ĺ",
"ç§Ģ"
],
[
"Ġcol",
"le"
],
[
"çĸ",
"ij"
],
[
"Ġsub",
"ject"
],
[
"Ġgreat",
"er"
],
[
"Ġst",
"ore"
],
[
"åŁ¹",
"è®Ń"
],
[
"Ġim",
"ag"
],
[
"Ġan",
"sw"
],
[
"ä½",
"Ļ"
],
[
"Ġsp",
"ot"
],
[
"åĪĨ",
"åŃIJ"
],
[
"Ġaud",
"ience"
],
[
"p",
"et"
],
[
"Ġv",
"ers"
],
[
"Ġtra",
"il"
],
[
"åĭ",
"ĩ"
],
[
"er",
"ous"
],
[
"Ġguid",
"ance"
],
[
"Ġspe",
"ech"
],
[
"åĵ",
"²"
],
[
"æĺ¯",
"çͱ"
],
[
"è´¡",
"çĮ®"
],
[
"åIJĪéĢĤ",
"çļĦ"
],
[
"设",
"æĸ½"
],
[
"ä»ĸ",
"人"
],
[
"ens",
"ive"
],
[
"åĢ",
"¾"
],
[
"al",
"ing"
],
[
"Ġproject",
"s"
],
[
"å",
"³"
],
[
"Ġt",
"akes"
],
[
"ç»",
"©"
],
[
"T",
"hat"
],
[
"Ġb",
"ro"
],
[
"iv",
"ed"
],
[
"Ġ",
"&"
],
[
"åĿ",
"IJ"
],
[
"place",
"ment"
],
[
"è¿ŀ",
"æİ¥"
],
[
"çļĦç¤",
"¾"
],
[
"ĠT",
"ra"
],
[
"Ġrel",
"ax"
],
[
"u",
"fact"
],
[
"éģ",
"į"
],
[
"Ġsur",
"v"
],
[
"åı£",
"åij³"
],
[
"Ġcreat",
"ivity"
],
[
"o",
"f"
],
[
"å¨",
"ģ"
],
[
"çļĦç",
"ł"
],
[
"Ġbreat",
"h"
],
[
"Ġpl",
"aces"
],
[
"Ġdesc",
"rib"
],
[
"èĭ±",
"è¯Ń"
],
[
"Ġdam",
"age"
],
[
"or",
"ation"
],
[
"为",
"æĤ¨"
],
[
"if",
"t"
],
[
"Ġc",
"ase"
],
[
"å¹´",
"é¾Ħ"
],
[
"Ġp",
"ress"
],
[
"çĶ",
"ľ"
],
[
"éĩ",
"İ"
],
[
"æĹħ",
"游"
],
[
"Ġt",
"aken"
],
[
"in",
"ed"
],
[
"Ġcon",
"cept"
],
[
"æĴ",
"Ń"
],
[
"Ġinterest",
"ing"
],
[
"è·",
"µ"
],
[
"Ġse",
"a"
],
[
"6",
"0"
],
[
"Ġf",
"oot"
],
[
"ĠN",
"ame"
],
[
"Ġresearc",
"hers"
],
[
"éĢ",
"ģ"
],
[
"Ġwe",
"e"
],
[
")",
";"
],
[
"çļĦ",
"åħ³éĶ®"
],
[
"ä¼",
"½"
],
[
"ele",
"br"
],
[
"å¡",
"ij"
],
[
"W",
"e"
],
[
"ç»ı",
"常"
],
[
"Ġpopul",
"ations"
],
[
"åħ¬",
"å¼ı"
],
[
"or",
"n"
],
[
"çĩ",
"ĥ"
],
[
"人",
"çĶŁ"
],
[
"1",
"7"
],
[
"æİ¥",
"åıĹ"
],
[
"Ġloc",
"ation"
],
[
"Ġin",
"equ"
],
[
"Ġinter",
"vent"
],
[
"Ġinterest",
"ed"
],
[
"Ġdefin",
"itely"
],
[
"Ġassist",
"ance"
],
[
"è¿Ļ",
"ä¸Ģ"
],
[
"åIJĪ",
"åIJĮ"
],
[
"ä¼ĺ",
"åĬ¿"
],
[
"çļĦ",
"å·¥ä½ľ"
],
[
"Ġ1",
"2"
],
[
"Ġmo",
"v"
],
[
"åģ",
"ı"
],
[
"åŃĺ",
"åĤ¨"
],
[
"us",
"ive"
],
[
"æĹ",
"ı"
],
[
"ï¼ī",
"ï¼Į"
],
[
"Ġg",
"as"
],
[
"Ġinterest",
"s"
],
[
"æ¸ħæĻ",
"°"
],
[
"Ġg",
"ard"
],
[
"çĸ",
"«"
],
[
"Ġs",
"ay"
],
[
"å¤",
"«"
],
[
"g",
"es"
],
[
"èIJ",
"¨"
],
[
"ä¸ļ",
"åĬ¡"
],
[
"个",
"æĢ§"
],
[
"åIJ",
"¯"
],
[
"Ġeng",
"agement"
],
[
"Ġb",
"ig"
],
[
"éľĢè¦ģ",
"èĢĥèĻij"
],
[
"Ġpr",
"inci"
],
[
"åij¨",
"åĽ´"
],
[
"Ġopportun",
"ity"
],
[
"çģ",
"¾"
],
[
"èĹ",
"ı"
],
[
"re",
"l"
],
[
"缺",
"çĤ¹"
],
[
"Ġhapp",
"y"
],
[
"åĴĮ",
"åħ¶ä»ĸ"
],
[
"av",
"a"
],
[
"Ġestab",
"lish"
],
[
"鸡",
"èĽĭ"
],
[
"i",
"king"
],
[
"ĠT",
"rans"
],
[
"rast",
"ructure"
],
[
"fore",
"st"
],
[
"èİ·",
"åıĸ"
],
[
"èĦ",
"ļ"
],
[
"in",
"ally"
],
[
"èµ",
"ı"
],
[
"Ġdel",
"icious"
],
[
"Ġresult",
"s"
],
[
"è§Ĥ",
"å¯Ł"
],
[
"å®ŀ",
"è·µ"
],
[
"Ġl",
"ast"
],
[
"Ġpol",
"it"
],
[
"æĢ§",
"èĥ½"
],
[
"F",
"or"
],
[
"b",
"i"
],
[
"缸",
"ä¿¡"
],
[
"ff",
"ee"
],
[
"Ġph",
"r"
],
[
"Ġfore",
"st"
],
[
"ell",
"ing"
],
[
"æµģ",
"è¡Į"
],
[
"at",
"ic"
],
[
"大",
"å®¶"
],
[
"ĠIn",
"st"
],
[
"æķ°",
"åѦ"
],
[
"æī",
"©"
],
[
"å®Į",
"åħ¨"
],
[
"å¼ķ",
"èµ·"
],
[
"es",
"e"
],
[
"转",
"æį¢"
],
[
"Ġaffect",
"ed"
],
[
"Ġrobot",
"ics"
],
[
"综",
"ä¸Ĭ"
],
[
"Ġpro",
"p"
],
[
"让",
"人"
],
[
"æ²",
"³"
],
[
"ä¸Ń",
"æľĢ"
],
[
"Ġaut",
"onomous"
],
[
"Ġha",
"ving"
],
[
"Ġtri",
"p"
],
[
"ur",
"y"
],
[
"Ġbi",
"ased"
],
[
"Ġconsider",
"ations"
],
[
"Ġpartic",
"ular"
],
[
"åį",
"ł"
],
[
"æİ¨",
"广"
],
[
"Ġiniti",
"atives"
],
[
"ial",
"s"
],
[
"åij³",
"éģĵ"
],
[
"Ġtreat",
"ments"
],
[
"Ġem",
"phas"
],
[
"çĭ¬çī¹",
"çļĦ"
],
[
"Ġl",
"ay"
],
[
"æĶ¿",
"çŃĸ"
],
[
"æĢİ",
"ä¹Ī"
],
[
"ron",
"ic"
],
[
"pl",
"ay"
],
[
"Ġco",
"ok"
],
[
"è¿Ľ",
"åħ¥"
],
[
"è½",
"®"
],
[
"Ġvol",
"unte"
],
[
"Ġra",
"in"
],
[
"ĠM",
"on"
],
[
"Ġconsum",
"ption"
],
[
"èĽĭ",
"çϽ"
],
[
"ĠS",
"oc"
],
[
"å£",
"¤"
],
[
"Ġrout",
"ine"
],
[
"Ġimpro",
"ved"
],
[
"T",
"o"
],
[
"人",
"çī©"
],
[
"读",
"èĢħ"
],
[
"Ġgo",
"al"
],
[
"广",
"åijĬ"
],
[
"éķ¿",
"æľŁ"
],
[
"Ġe",
"y"
],
[
"H",
"e"
],
[
"Ġout",
"do"
],
[
"Ġcu",
"is"
],
[
"Ġa",
"way"
],
[
"Ġbo",
"oks"
],
[
"Ġtop",
"ic"
],
[
"大",
"åĪ©"
],
[
"h",
"ouse"
],
[
"Ġon",
"es"
],
[
"ç§",
"Ł"
],
[
"'",
":"
],
[
"æĪ¿",
"å±ĭ"
],
[
"ç§»",
"åĬ¨"
],
[
"Ġdis",
"asters"
],
[
"est",
"s"
],
[
"ill",
"ing"
],
[
"绿",
"èī²"
],
[
"åĵ²",
"åѦ"
],
[
"æĪIJ",
"åĪĨ"
],
[
"Ġocc",
"ur"
],
[
"ľ",
"ä¼½"
],
[
"åľŁ",
"壤"
],
[
"çļĦ",
"主è¦ģ"
],
[
"çݰ",
"å®ŀ"
],
[
"Ġanim",
"al"
],
[
"é¢Ĩ",
"导"
],
[
"Ġview",
"s"
],
[
"éĤ",
"®"
],
[
"æ°§",
"åĮĸ"
],
[
"ath",
"y"
],
[
"éģĵ",
"å¾·"
],
[
"社交",
"åªĴä½ĵ"
],
[
"ĠP",
"ersonal"
],
[
"Ľ",
"åĽ´"
],
[
"Ġpur",
"ch"
],
[
"Ġcount",
"ry"
],
[
"Ġrem",
"ind"
],
[
"å¯",
"¸"
],
[
"Ġr",
"ights"
],
[
"çļĦ",
"çݯå¢ĥ"
],
[
"ĠP",
"r"
],
[
"Ġl",
"ine"
],
[
"ib",
"r"
],
[
"é©",
"¾"
],
[
"Ġm",
"aj"
],
[
"Ġover",
"come"
],
[
"Ġne",
"xt"
],
[
"æīĢ",
"è¿°"
],
[
"è§Ħ",
"å®ļ"
],
[
"Ġinteract",
"ions"
],
[
"Ġconf",
"lic"
],
[
"Ġwh",
"y"
],
[
"ç³»",
"åĪĹ"
],
[
"å°",
"¼"
],
[
"ib",
"ly"
],
[
"çīĽ",
"奶"
],
[
"Ġrespons",
"es"
],
[
"s",
"es"
],
[
"åѦ",
"ä¼ļ"
],
[
"b",
"ol"
],
[
"Ġstand",
"ards"
],
[
"ul",
"ner"
],
[
"对è¯Ŀ",
"åĨħ容"
],
[
"l",
"ished"
],
[
"çļĦæĢ",
"§"
],
[
"çĶŁæĢģ",
"ç³»ç»Ł"
],
[
"an",
"n"
],
[
"æĥħåĨµ",
"ä¸ĭ"
],
[
"寻",
"æ±Ĥ"
],
[
"Ġh",
"old"
],
[
"d",
"en"
],
[
"åį",
"ĥ"
],
[
"Ġment",
"ion"
],
[
"ĠMan",
"y"
],
[
"缴",
"åΰ"
],
[
"éģ",
"Ĺ"
],
[
"he",
"l"
],
[
"Ġbelie",
"ve"
],
[
"ar",
"ies"
],
[
"æľī",
"ä¸Ģ个"
],
[
"1",
"3"
],
[
"Ġatmosp",
"here"
],
[
"Ġm",
"or"
],
[
"æĹ¥",
"æľŁ"
],
[
"ä¹",
"ħ"
],
[
"ä½ł",
"好"
],
[
"Ġaddress",
"ing"
],
[
"ĠâĢ",
"ĵ"
],
[
"çļĦåľ°",
"æĸ¹"
],
[
"m",
"ing"
],
[
"Ġcan",
"not"
],
[
"Ġman",
"ufact"
],
[
"Ġp",
"ie"
],
[
"ic",
"ing"
],
[
"Ġstud",
"ies"
],
[
"ç¾İ",
"åij³"
],
[
"ĠAmeric",
"an"
],
[
"ĠN",
"LP"
],
[
"Ġacc",
"ording"
],
[
"ms",
"elves"
],
[
"èĦ",
"Ĥ"
],
[
"èĩª",
"ä¿¡"
],
[
"æīĢ",
"éľĢ"
],
[
"Ġthe",
"mselves"
],
[
"Ġremot",
"e"
],
[
"åŁ¹",
"åħ»"
],
[
"å®ī",
"æİĴ"
],
[
"ä½ł",
"éľĢè¦ģ"
],
[
"Ġreg",
"ard"
],
[
"ir",
"ing"
],
[
"è¯Ĩ",
"åĪ«"
],
[
"Ġart",
"icle"
],
[
"æģ",
"Ĵ"
],
[
"æĢ»",
"çļĦæĿ¥"
],
[
"Ġal",
"ign"
],
[
"æ±",
"ł"
],
[
"ten",
"ance"
],
[
"fact",
"ion"
],
[
"åĬ¨",
"ä½ľ"
],
[
"çļĦç",
"©"
],
[
"ç¼",
"©"
],
[
"æĢ",
"¥"
],
[
"Ġ1",
"00"
],
[
"Ġtest",
"ing"
],
[
"åŃĹ",
"æ¯į"
],
[
"å¹´",
"è½»"
],
[
"åζ",
"éĢł"
],
[
"Ġs",
"we"
],
[
"å°",
"º"
],
[
"he",
"ns"
],
[
"æ°´",
"æŀľ"
],
[
"Ġinf",
"rastructure"
],
[
"èī²",
"彩"
],
[
"æĢ»çļĦæĿ¥",
"说"
],
[
"æľī",
"ä»Ģä¹Ī"
],
[
"te",
"xt"
],
[
"车",
"è¾Ĩ"
],
[
"Ġp",
"ay"
],
[
"ro",
"p"
],
[
"Ċ",
"ĠĠ"
],
[
"Ġcaus",
"ed"
],
[
"Ġcor",
"rect"
],
[
"Ġ",
"ì"
],
[
"èĥ",
"ŀ"
],
[
"ĠM",
"ed"
],
[
"ç²¾",
"ç¥ŀ"
],
[
"æ°ĶåĢĻ",
"åıĺåĮĸ"
],
[
"ĠR",
"ed"
],
[
"äºĴ",
"èģĶç½ij"
],
[
"Ġeng",
"age"
],
[
"åĪĨ",
"为"
],
[
"ĠD",
"ata"
],
[
"Ġful",
"l"
],
[
"en",
"c"
],
[
"éĩį",
"æĸ°"
],
[
"æŃ£ç¡®",
"çļĦ"
],
[
"çļĦæ°",
"Ķ"
],
[
"åıĮ",
"æĸ¹"
],
[
"Ġcom",
"es"
],
[
"åı¤",
"代"
],
[
"æŁIJ",
"äºĽ"
],
[
"åijĪ",
"çݰ"
],
[
"Ġto",
"day"
],
[
"ag",
"ed"
],
[
"æĪij",
"åı¯ä»¥"
],
[
"æĹ¥",
"常"
],
[
"æ»",
"ij"
],
[
"Ġcl",
"in"
],
[
"Ġ",
"\\"
],
[
"Ġo",
"bs"
],
[
"Ġart",
"ificial"
],
[
"Ġexce",
"ll"
],
[
"çļĦç",
"¬"
],
[
"all",
"s"
],
[
"Ġprodu",
"ce"
],
[
"ĠD",
"es"
],
[
"os",
"s"
],
[
"è¹",
"Ī"
],
[
"Ġdra",
"w"
],
[
"Ġlet",
"ter"
],
[
"Ġadv",
"ice"
],
[
"Ġhigh",
"ly"
],
[
"çĬ",
"¯"
],
[
"综ä¸Ĭ",
"æīĢè¿°"
],
[
"满",
"æĦı"
],
[
"Ġprinci",
"ples"
],
[
"èĮ",
"Ħ"
],
[
"Ġfeel",
"ings"
],
[
"çļĦæ",
"´"
],
[
"Ġh",
"om"
],
[
"Ġf",
"ail"
],
[
"Ġcro",
"p"
],
[
"å§",
"ľ"
],
[
"Ġquest",
"ion"
],
[
"Ġdis",
"abilities"
],
[
"èĪŀ",
"è¹Ī"
],
[
"Ġimp",
"lications"
],
[
"r",
"al"
],
[
"Ġs",
"ing"
],
[
"4",
"0"
],
[
"Ġfam",
"il"
],
[
"Ġgovern",
"ments"
],
[
"Ġrec",
"ord"
],
[
"å½¢",
"çĬ¶"
],
[
"Ġbe",
"gin"
],
[
"is",
"es"
],
[
"çļĦæĥ",
"³"
],
[
"ach",
"ine"
],
[
"è°",
"±"
],
[
"Ġv",
"ulner"
],
[
"Ġpro",
"per"
],
[
"Ġovers",
"ight"
],
[
"è´Ł",
"éĿ¢"
],
[
"Ġem",
"ail"
],
[
"Ġnew",
"s"
],
[
"Ġexpl",
"oring"
],
[
"Ġf",
"avor"
],
[
"æ¥",
"¼"
],
[
"å®",
"ľ"
],
[
"Ġun",
"ivers"
],
[
"å·®",
"å¼Ĥ"
],
[
"ï¼ī",
"ãĢĤ"
],
[
"è§£åĨ³",
"éĹ®é¢ĺ"
],
[
"Ġfam",
"ous"
],
[
"g",
"n"
],
[
"Ġmess",
"age"
],
[
"at",
"itude"
],
[
"Ġc",
"ra"
],
[
"Ġco",
"ver"
],
[
"æ·±",
"åĪ»"
],
[
"åı¯ä»¥",
"éĢīæĭ©"
],
[
"çĶŁæ´»",
"ä¸Ń"
],
[
"ç§į",
"ç±»"
],
[
"Ġsm",
"art"
],
[
"on",
"str"
],
[
"ve",
"y"
],
[
"çĶ",
"²"
],
[
"Ġreg",
"ularly"
],
[
"ĠS",
"m"
],
[
"æĦŁ",
"è§ī"
],
[
"Ġthough",
"t"
],
[
"Ġex",
"h"
],
[
"c",
"ure"
],
[
"ç»",
"ĺ"
],
[
"认",
"è¯Ĩ"
],
[
"Ġo",
"ld"
],
[
"æĦ",
"ī"
],
[
"ç§°",
"为"
],
[
"Ġfiel",
"ds"
],
[
"Ġcons",
"ist"
],
[
"ã",
"ģ"
],
[
"ç»Ĩ",
"èĥŀ"
],
[
"Ġh",
"ours"
],
[
"8",
"0"
],
[
"al",
"king"
],
[
"è§ī",
"å¾Ĺ"
],
[
"ç»",
"Ŀ"
],
[
"ä½ł",
"们"
],
[
"ĠEng",
"lish"
],
[
"Ġsignificant",
"ly"
],
[
"Ġs",
"ource"
],
[
"Ġan",
"t"
],
[
"Ġeducation",
"al"
],
[
"Ġtas",
"k"
],
[
"Ġhand",
"le"
],
[
"æIJ",
"ľ"
],
[
"ĠS",
"p"
],
[
"Ġcall",
"ed"
],
[
"Ġter",
"ms"
],
[
"æ²",
"ī"
],
[
"Ġw",
"in"
],
[
"duct",
"ion"
],
[
"Ġmod",
"ern"
],
[
"Ġcuis",
"ine"
],
[
"å¥",
"Ĺ"
],
[
"è§",
"¦"
],
[
"olut",
"ely"
],
[
"ç«",
"¥"
],
[
"p",
"ite"
],
[
"Ġf",
"elt"
],
[
"Ġcomp",
"re"
],
[
"Ġw",
"ond"
],
[
"è¿IJ",
"è¡Į"
],
[
"Ġres",
"il"
],
[
"缸",
"ä¼¼"
],
[
"éĩij",
"èŀį"
],
[
"çα",
"æĥħ"
],
[
"ç¬",
"Ķ"
],
[
"èĪ",
"ª"
],
[
"è°",
"Ī"
],
[
"åĬĽ",
"çļĦ"
],
[
"æľī",
"æīĢ"
],
[
"æ½",
"ľ"
],
[
"ul",
"ate"
],
[
"Ġdetect",
"ion"
],
[
"宣",
"ä¼ł"
],
[
"Ġmat",
"ter"
],
[
"éĩı",
"åŃIJ"
],
[
"W",
"rite"
],
[
"ç»ĵ",
"åIJĪ"
],
[
"ç»ı",
"è¿ĩ"
],
[
"Ġdevelop",
"ers"
],
[
"è",
"ª"
],
[
"Ġ",
"---"
],
[
"人",
"éĻħ"
],
[
"çŃ",
"¾"
],
[
"ï¼ļ",
"âĢľ"
],
[
"Ġinnov",
"ative"
],
[
"ãĢĤ",
"âĢĿ"
],
[
"å½",
"¼"
],
[
"é¥",
"¼"
],
[
"è¿ĩ",
"度"
],
[
"Ġplan",
"et"
],
[
"åħ",
"°"
],
[
"å¸",
"ģ"
],
[
"æķ",
"¬"
],
[
"Ġleg",
"al"
],
[
"Ġlo",
"t"
],
[
"æĪIJ为",
"äºĨ"
],
[
"i",
"ate"
],
[
"Ġm",
"is"
],
[
"åģĩ",
"设"
],
[
"çļĦ",
"æĸĩ竳"
],
[
"ĠCom",
"pan"
],
[
"Ġd",
"oc"
],
[
"Ġcare",
"ful"
],
[
"Ġe",
"ver"
],
[
"æĪij们",
"å°Ĩ"
],
[
"ä¾ĭ",
"åŃIJ"
],
[
"ä¹",
"³"
],
[
"ä½ľ",
"èĢħ"
],
[
"åIJ",
"§"
],
[
"æļ",
"´"
],
[
"Ġrem",
"ember"
],
[
"缮",
"çļĦ"
],
[
"Ġp",
"ut"
],
[
"常è§ģ",
"çļĦ"
],
[
"Ġf",
"est"
],
[
"建",
"设"
],
[
"å®ŀ",
"ç͍"
],
[
"Ġact",
"ive"
],
[
"çª",
"Ĺ"
],
[
"ou",
"th"
],
[
"åİŁ",
"çIJĨ"
],
[
"Ġtry",
"ing"
],
[
"è¿",
"·"
],
[
"缸",
"åIJĮ"
],
[
"éħĴ",
"åºĹ"
],
[
"An",
"other"
],
[
"æľĢ",
"ä½³"
],
[
"Ġanaly",
"tics"
],
[
"Ġper",
"pet"
],
[
"ip",
"ment"
],
[
"Ġ",
"å¦Ĥæŀľ"
],
[
"è§Ĥ",
"ä¼Ĺ"
],
[
"Ġc",
"elebr"
],
[
"Ġhe",
"av"
],
[
"Ġmed",
"itation"
],
[
"大",
"æ°Ķ"
],
[
"A",
"nd"
],
[
"ä¸į",
"éĶĻ"
],
[
"Ġwhe",
"ther"
],
[
"s",
"et"
],
[
"Ġdem",
"onstr"
],
[
"ä¸Ģ",
"款"
],
[
"æĶ¶",
"éĽĨ"
],
[
"éĻIJ",
"åζ"
],
[
"Ġ",
"ing"
],
[
"Ġrev",
"olution"
],
[
"çľ",
"ģ"
],
[
"Ġsc",
"ience"
],
[
"缮",
"åīį"
],
[
"Ġthink",
"ing"
],
[
"±",
"ä¹IJ"
],
[
"课",
"ç¨ĭ"
],
[
"Ġp",
"ack"
],
[
"Ġim",
"age"
],
[
"lo",
"c"
],
[
"Ġst",
"ories"
],
[
"uc",
"k"
],
[
"Ġsatis",
"faction"
],
[
"Ġcollect",
"ion"
],
[
"h",
"o"
],
[
"èµ",
"ŀ"
],
[
"éĿ¢",
"临"
],
[
"Ġl",
"a"
],
[
"Ġsym",
"bol"
],
[
"Ġem",
"b"
],
[
"Ġhabit",
"ats"
],
[
"Ġlow",
"er"
],
[
"Ġcontin",
"ues"
],
[
"éľ",
"ĩ"
],
[
"åĵ",
"Ī"
],
[
"ĠT",
"ake"
],
[
"Ġenviron",
"ments"
],
[
"Ġth",
"ree"
],
[
"Ġen",
"c"
],
[
"ĠA",
"cc"
],
[
"æĦı",
"åij³"
],
[
"åİ",
"¨"
],
[
"ch",
"an"
],
[
"ĠH",
"um"
],
[
"Ġtr",
"ue"
],
[
"åĪĩ",
"æĪIJ"
],
[
"s",
"ing"
],
[
"âĢĶ",
"âĢĶ"
],
[
"åĩº",
"æĿ¥"
],
[
"Ġreg",
"ion"
],
[
"Ġinter",
"pre"
],
[
"Ġdiagnos",
"is"
],
[
"é",
"ŀ"
],
[
"Ġdo",
"ing"
],
[
"Ġr",
"un"
],
[
"Ġco",
"ffee"
],
[
"Ġmaj",
"or"
],
[
"Ġmindful",
"ness"
],
[
"Ġafford",
"able"
],
[
"çĻ",
"¾"
],
[
"Ġdetail",
"ed"
],
[
"éĿŀ常",
"éĩįè¦ģçļĦ"
],
[
"çļĦæ²",
"ŁéĢļ"
],
[
"çļĦæķ",
"ħ"
],
[
"åĢĴ",
"åħ¥"
],
[
"Ġthem",
"es"
],
[
"Ġnet",
"work"
],
[
"ï¼ī",
"ï¼ļ"
],
[
"ĠUn",
"ited"
],
[
"çļĦæĮ",
"ĩ"
],
[
"ort",
"s"
],
[
"åį«",
"çĶŁ"
],
[
"Ġplan",
"ning"
],
[
"æĥ",
"ł"
],
[
"åī",
"ª"
],
[
"ĠPro",
"v"
],
[
"çļĦ",
"åºĶç͍"
],
[
"Ġp",
"eri"
],
[
"Ġaccount",
"able"
],
[
"çī",
"Ļ"
],
[
"çļĦç",
"ģ"
],
[
"Ġcho",
"ice"
],
[
"ĠC",
"omm"
],
[
"id",
"ents"
],
[
"çļĦ",
"å®īåħ¨"
],
[
"å¹¶",
"ä¸į"
],
[
"太éĺ³",
"ç³»"
],
[
"Ġrece",
"ive"
],
[
"Ġclo",
"se"
],
[
"çļĦæĹ¶",
"åĢĻ"
],
[
"Ġchang",
"ing"
],
[
"ä»·å̼",
"è§Ĥ"
],
[
"Ġperpet",
"u"
],
[
"Ġse",
"ason"
],
[
"Ġm",
"en"
],
[
"Ġlearn",
"ed"
],
[
"Ġsitu",
"ation"
],
[
"Ġre",
"place"
],
[
"he",
"ad"
],
[
"让",
"æĪij"
],
[
"åľ¨",
"ä¸Ģèµ·"
],
[
"çļĦç©",
"º"
],
[
"éľ",
"²"
],
[
"Ġen",
"ough"
],
[
"å±ķ",
"çݰ"
],
[
"Ġlead",
"ers"
],
[
"an",
"cing"
],
[
"Ġtemper",
"ature"
],
[
"åı",
"«"
],
[
"Ġ3",
"0"
],
[
"æĦıåij³",
"çĿĢ"
],
[
"æ±",
"ĩ"
],
[
"ĠGo",
"vern"
],
[
"Ġfocus",
"ed"
],
[
"u",
"ro"
],
[
"Ġsim",
"ple"
],
[
"Ġh",
"iking"
],
[
"æ¯",
"Ĵ"
],
[
"Ġcompre",
"hens"
],
[
"äº",
"Ī"
],
[
"Ġcreat",
"ed"
],
[
"con",
"d"
],
[
"é¡",
"µ"
],
[
"ĠW",
"or"
],
[
"è¯ģ",
"æį®"
],
[
"Ġwork",
"place"
],
[
"Ġcharact",
"ers"
],
[
"çļĦ",
"设计"
],
[
"Ġme",
"chan"
],
[
"ĠD",
"is"
],
[
"ç¥ŀ",
"ç§ĺ"
],
[
"å·",
"ŀ"
],
[
"ĠO",
"n"
],
[
"<",
"/"
],
[
"ç§į",
"æ¤į"
],
[
"Ġpat",
"h"
],
[
"Ġlim",
"ited"
],
[
"Ġsol",
"ar"
],
[
"çļĦæ",
"ı"
],
[
"2",
"2"
],
[
"Ġappreci",
"ate"
],
[
"å¿«",
"ä¹IJ"
],
[
"æĦŁ",
"åıĹåΰ"
],
[
"èĢ",
"Ĺ"
],
[
"m",
"ed"
],
[
"ic",
"ine"
],
[
"Ġnot",
"e"
],
[
"å½ĵ",
"åīį"
],
[
"æĪij们",
"åºĶ该"
],
[
"Ġse",
"en"
],
[
"ä¸Ģ",
"åIJį"
],
[
"å°½",
"åı¯èĥ½"
],
[
"è¿IJ",
"ç®Ĺ"
],
[
"è§Ĵ",
"度"
],
[
"Ġequ",
"ipment"
],
[
"Ġsp",
"read"
],
[
"è",
"¸"
],
[
"è®",
"¿"
],
[
"åı¥",
"è¯Ŀ"
],
[
"æĮ",
"¥"
],
[
"Ġpur",
"pose"
],
[
"请",
"ä½ł"
],
[
"Y",
"our"
],
[
"ari",
"an"
],
[
"ä»",
"ª"
],
[
"Ġperspect",
"ives"
],
[
"åĩº",
"äºĨ"
],
[
"å©ļ",
"礼"
],
[
"Ġexcell",
"ent"
],
[
"ĠEns",
"uring"
],
[
"Ġre",
"ach"
],
[
"éĺ¶",
"段"
],
[
"ä¿Ŀ",
"éļľ"
],
[
"Ġemp",
"athy"
],
[
"ĠM",
"y"
],
[
"çij",
"ľä¼½"
],
[
"Ġ",
"ver"
],
[
"ab",
"el"
],
[
"ĠPre",
"dict"
],
[
"Ġmain",
"tenance"
],
[
"è¯Ħ",
"ä»·"
],
[
"Ġ",
"ult"
],
[
"åĴ",
"¨"
],
[
"o",
"x"
],
[
"åĴ¨",
"询"
],
[
"Ġshare",
"d"
],
[
"in",
"a"
],
[
"l",
"ist"
],
[
"Ġoutdo",
"or"
],
[
"Ġthough",
"ts"
],
[
"in",
"ating"
],
[
"éĴ",
"±"
],
[
"Ġfra",
"me"
],
[
"éĺ",
"¿"
],
[
"åĪ©",
"润"
],
[
"çļĦæİ",
"¨"
],
[
"åį",
"ļ"
],
[
"Ġrec",
"ent"
],
[
"Ġal",
"tern"
],
[
"are",
"d"
],
[
"=",
"="
],
[
"Ġro",
"ad"
],
[
"äºĭ",
"项"
],
[
"g",
"ed"
],
[
"y",
"nt"
],
[
"Ġspe",
"nd"
],
[
"ç½",
"ª"
],
[
"åıĸ",
"å¾Ĺ"
],
[
"é",
"¹"
],
[
"l",
"i"
],
[
"æĹ¶",
"æľŁ"
],
[
"严",
"éĩį"
],
[
"å¿",
"Ĩ"
],
[
"å©",
"´"
],
[
"æİ¥",
"ä¸ĭæĿ¥"
],
[
"ĠEar",
"th"
],
[
"ĠChat",
"bots"
],
[
"Ġset",
"ting"
],
[
"ç¥",
"Ŀ"
],
[
"éĶĢåĶ®",
"é¢Ŀ"
],
[
"ä¼",
"¦"
],
[
"Ġread",
"ing"
],
[
"æİ¢",
"讨"
],
[
"a",
"ign"
],
[
"éŀ",
"ĭ"
],
[
"Ġyou",
"ng"
],
[
"Ġcare",
"er"
],
[
"Ġteac",
"hers"
],
[
"çļĦ",
"è´¨éĩı"
],
[
"å±ŀ",
"äºİ"
],
[
"Ġeas",
"ier"
],
[
"Ġscient",
"ific"
],
[
"ç¾İ",
"åħĥ"
],
[
"Ġsp",
"ir"
],
[
"åĬ",
"³"
],
[
"çļĦæĶ",
"¯"
],
[
"r",
"ist"
],
[
"èµĦ",
"产"
],
[
"çĶŁ",
"åŃĺ"
],
[
"èĩ³",
"å°ij"
],
[
"å§",
"¿"
],
[
"Ġvide",
"o"
],
[
"Ġa",
"im"
],
[
"å®Ŀ",
"å®Ŀ"
],
[
"çζ",
"æ¯į"
],
[
"________",
"________"
],
[
"al",
"ities"
],
[
"Ġb",
"ud"
],
[
"Ġstre",
"et"
],
[
"Ġ",
"æĺ¯"
],
[
"æĸ¹",
"ç¨ĭ"
],
[
"ä¸ĸ",
"纪"
],
[
"c",
"hes"
],
[
"ear",
"ch"
],
[
"æĴ",
"°"
],
[
"Ġeng",
"ine"
],
[
"Ġdis",
"placement"
],
[
"ĠRo",
"bots"
],
[
"erv",
"ised"
],
[
"é¡",
"¶"
],
[
"ou",
"d"
],
[
"Ġw",
"alk"
],
[
"Ġemerg",
"ency"
],
[
"èģ",
"ĺ"
],
[
"n",
"al"
],
[
"Ġdat",
"as"
],
[
"åĢ",
"º"
],
[
"åIJİ",
"çļĦ"
],
[
"å¾Ī",
"好"
],
[
"Ġmy",
"self"
],
[
"çļĦæī",
"ĭ"
],
[
"Ġus",
"age"
],
[
"Ġsh",
"own"
],
[
"æ®",
"Ĭ"
],
[
"Ġtyp",
"ically"
],
[
"u",
"ly"
],
[
"æĸ°",
"éĹ»"
],
[
"æĽ",
"¿"
],
[
"Ġor",
"ig"
],
[
"è½»",
"æĿ¾"
],
[
"æĺ¾",
"示"
],
[
"Ġado",
"pt"
],
[
"èĤ¡",
"票"
],
[
"Ġp",
"arent"
],
[
"a",
"ps"
],
[
"æĢĿ",
"æĥ³"
],
[
"Ġmarket",
"ing"
],
[
"èĻ",
"«"
],
[
"éĥ¨",
"éŨ"
],
[
"çļĦæķ",
"Ī"
],
[
"Ġcomfort",
"able"
],
[
"åŃ¦ä¹ł",
"åĴĮ"
],
[
"Ġfore",
"cast"
],
[
"ict",
"ion"
],
[
"Ġget",
"ting"
],
[
"Ġtre",
"es"
],
[
"av",
"ing"
],
[
"çļĦ",
"åŁºç¡Ģ"
],
[
"read",
"y"
],
[
"æĸ°",
"é²ľ"
],
[
"go",
"ing"
],
[
"¹",
"é¥"
],
[
"Ġev",
"idence"
],
[
"¹é¥",
"ª"
],
[
"ç§",
"ĭ"
],
[
"æľī",
"å¾Īå¤ļ"
],
[
"éĿ¢",
"è¯ķ"
],
[
"éģĩ",
"åΰ"
],
[
"ç»Ļ",
"å®ļ"
],
[
"ir",
"c"
],
[
"åı¯ä»¥",
"æł¹æį®"
],
[
"驾",
"é©¶"
],
[
"å·§",
"åħĭ"
],
[
"Ġst",
"unning"
],
[
"çļĦæ",
"¦Ĥ"
],
[
"æ¡",
"Į"
],
[
"ĠJ",
"ohn"
],
[
"ul",
"ation"
],
[
"åıĤ",
"èĢĥ"
],
[
"Ġf",
"lex"
],
[
"çĦ¦",
"èĻij"
],
[
"ym",
"akers"
],
[
"Ġfor",
"ms"
],
[
"s",
"h"
],
[
"v",
"al"
],
[
"ĠS",
"o"
],
[
"c",
"o"
],
[
"æİ¨",
"åĬ¨"
],
[
"èħ",
"¿"
],
[
"çī¹",
"æ®Ĭ"
],
[
"Ġen",
"ab"
],
[
"å°Ĩ",
"ä¼ļ"
],
[
"æĶ¯",
"åĩº"
],
[
"åĿļ",
"æĮģ"
],
[
"红",
"èī²"
],
[
"Ġopt",
"ion"
],
[
"Ġstart",
"ed"
],
[
"r",
"ation"
],
[
"Ġpo",
"etry"
],
[
"Ġp",
"ort"
],
[
"g",
"en"
],
[
"èª",
"ī"
],
[
"Ġdel",
"iv"
],
[
"çĶ",
"ļ"
],
[
"éĢ",
"»"
],
[
"éĢī",
"项"
],
[
"Ġg",
"round"
],
[
"å½¼",
"æŃ¤"
],
[
"an",
"a"
],
[
"çļĦæĹ",
"¥"
],
[
"åľ¨",
"线"
],
[
"Ġse",
"cure"
],
[
"Ġ",
"æł¹æį®"
],
[
"饮",
"æĸĻ"
],
[
"Ġgr",
"atitude"
],
[
"第",
"ä¸ī"
],
[
"Ġs",
"ong"
],
[
"Ġpoint",
"s"
],
[
"Ġal",
"ready"
],
[
"çļĦçĪ",
"±"
],
[
"ĠTe",
"chn"
],
[
"Ġreal",
"ity"
],
[
"çı",
"Ń"
],
[
"Ġs",
"ince"
],
[
"Ġpopul",
"ation"
],
[
"y",
"ond"
],
[
"b",
"or"
],
[
"ĠSoc",
"ial"
],
[
"æıIJ",
"åıĸ"
],
[
"å·¥",
"ç¨ĭ"
],
[
"a",
"ff"
],
[
"交",
"æĺĵ"
],
[
"Ġwor",
"th"
],
[
"å¡",
"«"
],
[
"å¨",
"±ä¹IJ"
],
[
"Ġdo",
"g"
],
[
"ĠAr",
"t"
],
[
"ç¡",
"¬"
],
[
"æµ·",
"æ´ĭ"
],
[
"åĨ",
"Ĵ"
],
[
"çī",
"Ī"
],
[
"Ġprogramm",
"ing"
],
[
"ĠAs",
"s"
],
[
"ĠM",
"achine"
],
[
"å̼",
"å¾Ĺ"
],
[
"请",
"è¾ĵåħ¥"
],
[
"声",
"éŁ³"
],
[
"Ġexercis",
"es"
],
[
"åħī",
"线"
],
[
"æ³ķ",
"åĴĮ"
],
[
"Ġfeat",
"ure"
],
[
"e",
"ff"
],
[
"è¿Ľ",
"æŃ¥"
],
[
"女",
"æĢ§"
],
[
"Ġefficient",
"ly"
],
[
"çļĦæĬĢ",
"æľ¯"
],
[
"Ġgen",
"etic"
],
[
"令",
"人"
],
[
"è´",
"¦"
],
[
"çļĦ",
"产åĵģ"
],
[
"åİ",
"ļ"
],
[
"åĴĮ",
"æĸĩåĮĸ"
],
[
"éĻ",
"Ħ"
],
[
"Ġmo",
"b"
],
[
"综",
"åIJĪ"
],
[
"t",
"ers"
],
[
"æľī",
"ä¸Ģ"
],
[
"å¦",
"Ĩ"
],
[
"åį",
"Ī"
],
[
"Ġout",
"side"
],
[
"Ġprop",
"ert"
],
[
"éĤ®",
"ä»¶"
],
[
"主",
"ä¹ī"
],
[
"Ġpolic",
"y"
],
[
"èĩª",
"身"
],
[
"Ġnav",
"igate"
],
[
"Ġst",
"y"
],
[
"ç͵",
"èĦij"
],
[
"Ġab",
"ilities"
],
[
"Ġfac",
"ed"
],
[
"çļĦç",
"¼"
],
[
"çļĦ",
"å°ı"
],
[
"è",
"ķ"
],
[
"Ġt",
"one"
],
[
"ig",
"ation"
],
[
"åıĤ",
"æķ°"
],
[
"èĽĭçϽ",
"è´¨"
],
[
"ä½",
"Ľ"
],
[
"çĶļ",
"èĩ³"
],
[
"Ġsk",
"in"
],
[
"èĴ",
"¸"
],
[
"æĭ",
"Ľ"
],
[
"éŃ",
"Ķ"
],
[
"ash",
"ion"
],
[
"Ġing",
"red"
],
[
"æĹ",
"ĭ"
],
[
"Ġcamp",
"aign"
],
[
"Ġm",
"ount"
],
[
"Ġcons",
"id"
],
[
"Ġmus",
"e"
],
[
"n",
"ter"
],
[
"w",
"ater"
],
[
"ä¼ļ",
"è®®"
],
[
"Ġprotect",
"ion"
],
[
"ä¿Ŀ",
"éĻ©"
],
[
"Ġcro",
"ps"
],
[
"og",
"le"
],
[
"éļı",
"æĹ¶"
],
[
"æļ",
"Ĺ"
],
[
"i",
"um"
],
[
"ä¹",
"ı"
],
[
"Ġdi",
"et"
],
[
"l",
"ies"
],
[
"ç͍",
"æĿ¥"
],
[
"ĠEn",
"coura"
],
[
"æĬ",
"Ĺ"
],
[
"ap",
"an"
],
[
"éĺ²",
"æŃ¢"
],
[
"W",
"ow"
],
[
"çļĦ",
"åŁºæľ¬"
],
[
"å¹³",
"æĸ¹"
],
[
"Ġst",
"ep"
],
[
"åı¯",
"éĿł"
],
[
"表",
"æĺİ"
],
[
"Ġpredict",
"ions"
],
[
"Ġsym",
"pt"
],
[
"Ġdiagnos",
"es"
],
[
"åħ¬",
"åĽŃ"
],
[
"Ġsupp",
"ly"
],
[
"Ġprev",
"ious"
],
[
"ç»Ħ",
"åIJĪ"
],
[
".",
","
],
[
"çļĦ",
"è¿ĩç¨ĭ"
],
[
"æķ",
"ı"
],
[
"s",
"u"
],
[
"ar",
"is"
],
[
"çķ",
"ħ"
],
[
"oc",
"ol"
],
[
"æIJľ",
"ç´¢"
],
[
"it",
"le"
],
[
"éĨ",
"Ĵ"
],
[
"顾",
"客"
],
[
"éĢ»",
"è¾ij"
],
[
"éĿŀ常",
"éĩįè¦ģ"
],
[
"ĠB",
"i"
],
[
"å·¦",
"åı³"
],
[
"am",
"m"
],
[
"Ġevery",
"thing"
],
[
"æĺ",
"ł"
],
[
"Ġincre",
"d"
],
[
"Ġpe",
"ace"
],
[
"èľ",
"ľ"
],
[
"Ġmuse",
"um"
],
[
"çĭ¬",
"ç«ĭ"
],
[
"Ġcomprehens",
"ive"
],
[
"Ġr",
"ates"
],
[
"/",
"/"
],
[
"Ġra",
"d"
],
[
"åĦ¿",
"ç«¥"
],
[
"çī¹",
"èī²"
],
[
"ĠPredict",
"ive"
],
[
"å¼ķ",
"åĬĽ"
],
[
"l",
"er"
],
[
"å°",
"¤"
],
[
"ic",
"ro"
],
[
"è¡",
"¥"
],
[
"Ġdeterm",
"ine"
],
[
"çļĦ",
"åĨħ容"
],
[
"Ġcom",
"pl"
],
[
"Ġgreen",
"house"
],
[
"èħ",
"IJ"
],
[
"Ġhigh",
"light"
],
[
"Ġpart",
"ners"
],
[
"Ġdo",
"ct"
],
[
"çļĦ",
"使ç͍"
],
[
"æŃĮ",
"æĽ²"
],
[
"æĮĩ",
"åįĹ"
],
[
"ĠA",
"f"
],
[
"æľº",
"æŀĦ"
],
[
"éĢ",
"Ģ"
],
[
"Ġpoem",
"s"
],
[
"å¿ĥ",
"åĴĮ"
],
[
"Ġatt",
"end"
],
[
"çļĦæ¸",
"¸"
],
[
"Ġs",
"ide"
],
[
"al",
"es"
],
[
"Ġmention",
"ed"
],
[
"ĠA",
"bs"
],
[
"Ġhistor",
"ical"
],
[
"Ġle",
"ft"
],
[
"以ä¸ĭ",
"åĩłä¸ª"
],
[
"åıĹ",
"欢è¿İ"
],
[
"èıľ",
"åĵģ"
],
[
"Ġrem",
"ain"
],
[
"æ",
"ĩ"
],
[
"Ġtour",
"s"
],
[
"ł",
"éģĵ"
],
[
"Ġerr",
"ors"
],
[
"æľº",
"åζ"
],
[
"æ",
"¦"
],
[
"æĤ£",
"èĢħ"
],
[
"m",
"ore"
],
[
"Ġexpert",
"s"
],
[
"çļĦçł",
"Ķç©¶"
],
[
"ç»ĵ",
"æĿŁ"
],
[
"Ġwrit",
"ten"
],
[
"çł",
"Ķ"
],
[
"Ġe",
"t"
],
[
"in",
"put"
],
[
"æ°Ķ",
"ä½ĵ"
],
[
"è",
"ļ"
],
[
"æĥ",
"Ĭ"
],
[
"Ġa",
"ge"
],
[
"éĩį",
"å¤į"
],
[
"å¼",
"¹"
],
[
"åŃ",
"¤"
],
[
"Ġsympt",
"oms"
],
[
"Ġbelie",
"f"
],
[
"'",
"d"
],
[
"i",
"ol"
],
[
"Ġ1",
"8"
],
[
"åħħ",
"è¶³"
],
[
"çı",
"į"
],
[
"force",
"ment"
],
[
"æĸ",
"Ĺ"
],
[
"ª",
"èĮĦ"
],
[
"Ġ1",
"5"
],
[
"ä¸Ģ个",
"人"
],
[
"Ġapp",
"lic"
],
[
"è´",
"¥"
],
[
"ä½į",
"äºİ"
],
[
"éϤ",
"äºĨ"
],
[
"=",
"\""
],
[
"ä¸ī",
"è§Ĵ"
],
[
"æĢĿ",
"ç»´"
],
[
"åį",
"·"
],
[
"Ġf",
"ru"
],
[
"ĠCol",
"labor"
],
[
"Ġpr",
"im"
],
[
"Ġrequire",
"d"
],
[
"Ġw",
"atch"
],
[
"è°ĥ",
"åij³"
],
[
"ç»ĵ",
"论"
],
[
"on",
"y"
],
[
"Ġgu",
"ide"
],
[
"Ġm",
"ax"
],
[
"ĠC",
"ould"
],
[
"Ġadv",
"ent"
],
[
"ĠO",
"verall"
],
[
"çļĦæĬ",
"ķ"
],
[
"Ġexp",
"er"
],
[
"å",
"ĺ"
],
[
"ic",
"ial"
],
[
"ost",
"er"
],
[
"çļĦ",
"é¢ľèī²"
],
[
"Ġoper",
"ations"
],
[
"éĥ",
"ģ"
],
[
"Ġm",
"oney"
],
[
"le",
"y"
],
[
"c",
"ling"
],
[
"Ġo",
"il"
],
[
"çļ®",
"èĤ¤"
],
[
"Ġg",
"e"
],
[
"Ġb",
"at"
],
[
"ĠP",
"h"
],
[
"Ġsc",
"he"
],
[
"Ġelect",
"ric"
],
[
"v",
"est"
],
[
"Ġch",
"ain"
],
[
"Ġcap",
"abilities"
],
[
"ir",
"d"
],
[
"è¯ģ",
"æĺİ"
],
[
"æľĢ",
"好"
],
[
"iv",
"il"
],
[
"Ġdepend",
"ing"
],
[
"Ġs",
"ave"
],
[
"Ġpract",
"ical"
],
[
"Ġcult",
"ures"
],
[
"缸åºĶ",
"çļĦ"
],
[
"s",
"y"
],
[
"çļĦç",
"²"
],
[
"Ġbeh",
"ind"
],
[
"æĹ¶éĹ´",
"åĴĮ"
],
[
"å¹",
"ħ"
],
[
"ĠA",
"g"
],
[
"Ġeffect",
"iveness"
],
[
"A",
"d"
],
[
"ĠO",
"f"
],
[
"Ġany",
"thing"
],
[
"å·§åħĭ",
"åĬĽ"
],
[
"Ġm",
"ist"
],
[
"Ġlangu",
"ages"
],
[
"ĠM",
"ake"
],
[
"å",
"«"
],
[
"æ£",
"®"
],
[
"ĠCon",
"t"
],
[
"ĠAbs",
"olutely"
],
[
"Ġinvest",
"ment"
],
[
"m",
"at"
],
[
"çļĦæķħ",
"äºĭ"
],
[
"æ¬",
"§"
],
[
"Ġspe",
"ed"
],
[
"çļĦæ¸",
"©"
],
[
"Ġc",
"ities"
],
[
"åĨĻ",
"ä½ľ"
],
[
"Th",
"anks"
],
[
"Ġd",
"ed"
],
[
"åĪĨ",
"éħį"
],
[
"Ġd",
"ark"
],
[
"Ġsupport",
"ing"
],
[
"å¹",
"ķ"
],
[
"ĠK",
"e"
],
[
"éĽ",
"¶"
],
[
"Ġsh",
"aring"
],
[
"Ġh",
"ouse"
],
[
"认",
"çŁ¥"
],
[
"Ġsurround",
"ing"
],
[
"Ġredu",
"ced"
],
[
"Ġf",
"u"
],
[
"Ġst",
"or"
],
[
"Ġab",
"s"
],
[
"T",
"om"
],
[
"c",
"ent"
],
[
"ĠEduc",
"ation"
],
[
"Ġth",
"r"
],
[
"ot",
"t"
],
[
"ĠTh",
"at"
],
[
"Ġhe",
"ar"
],
[
"un",
"g"
],
[
"Ġbe",
"yond"
],
[
"ĠC",
"o"
],
[
"ro",
"om"
],
[
"è¯Ĺ",
"æŃĮ"
],
[
"re",
"me"
],
[
"Ġlit",
"tle"
],
[
"Ġg",
"ames"
],
[
"ä¹ĭ",
"åIJİ"
],
[
"éĥ½",
"ä¼ļ"
],
[
"è¯Ń",
"éŁ³"
],
[
"ç¬",
"ij"
],
[
"çī¹",
"å®ļ"
],
[
"第",
"ä¸Ģ"
],
[
"Ġdep",
"ression"
],
[
"Ġinnov",
"ation"
],
[
"ĠF",
"r"
],
[
"Ġcomput",
"er"
],
[
"c",
"an"
],
[
"å³",
"°"
],
[
"ç¼ĸåĨĻ",
"ä¸Ģ个"
],
[
"Ġintern",
"ational"
],
[
"Ġcan",
"cer"
],
[
"åѦ",
"èĢħ"
],
[
"Ġdisc",
"over"
],
[
"he",
"t"
],
[
"Ġcomp",
"os"
],
[
"Ġrec",
"y"
],
[
"Ġ2",
"00"
],
[
"åIJ«",
"æľī"
],
[
"çĹ",
"Ľ"
],
[
"ç¼ĵ",
"è§£"
],
[
"Ġfre",
"qu"
],
[
"çĶ",
"³"
],
[
"ĠM",
"ar"
],
[
"çļĦ",
"éĢīæĭ©"
],
[
"Ġun",
"t"
],
[
"Ġreg",
"ions"
],
[
"Ġop",
"in"
],
[
"ĠGovern",
"ments"
],
[
"æ¶",
"Ĥ"
],
[
"åĨħ",
"å¿ĥ"
],
[
"ä¸Ĭ",
"æľĢ"
],
[
"ä»į",
"çĦ¶"
],
[
"l",
"ier"
],
[
"æ³",
"³"
],
[
"äºĴ",
"缸"
],
[
"ĠSt",
"ud"
],
[
"az",
"on"
],
[
"Ġar",
"ch"
],
[
"Ġche",
"m"
],
[
"çļĦ",
"èĥ½åĬĽ"
],
[
"çļĦ",
"ä¸Ģ个"
],
[
"Ġa",
"p"
],
[
"Ġre",
"d"
],
[
"Ġw",
"omen"
],
[
"Ġpro",
"te"
],
[
"Ġfind",
"ing"
],
[
"å§",
"»"
],
[
"éĢĤå½ĵ",
"çļĦ"
],
[
"Ġfor",
"ward"
],
[
"对",
"象"
],
[
"Ġwa",
"it"
],
[
"Ġconsid",
"ered"
],
[
"du",
"le"
],
[
"b",
"acks"
],
[
"Ġclin",
"ical"
],
[
"åħ·",
"å¤ĩ"
],
[
"éº",
"¦"
],
[
"Ġon",
"going"
],
[
"åĨ",
"Ľ"
],
[
"Ġf",
"ar"
],
[
"åĴĮ",
"è°"
],
[
"XX",
"X"
],
[
"Ġpolit",
"ical"
],
[
"Ġcam",
"er"
],
[
"çļĦ",
"è¡Į为"
],
[
"æĦı",
"大åĪ©"
],
[
"Ġapp",
"s"
],
[
"åĩı",
"è½»"
],
[
"Ġread",
"ers"
],
[
"å©ļ",
"å§»"
],
[
"æ°",
"¸"
],
[
"o",
"res"
],
[
"åħ¨",
"éĿ¢"
],
[
"ĠAf",
"ric"
],
[
"Ġfavor",
"ite"
],
[
"Ġm",
"ill"
],
[
"Ġd",
"ang"
],
[
"ĠSt",
"ates"
],
[
"åĢ",
"Ł"
],
[
"å¯",
"¿"
],
[
"Ġl",
"at"
],
[
"è¿ĩ",
"åİ»"
],
[
"Ġtr",
"uly"
],
[
"åĽŀçŃĶ",
"éĹ®é¢ĺ"
],
[
"Ġco",
"gn"
],
[
"ä»",
"°"
],
[
"ĠJ",
"apan"
],
[
"iz",
"z"
],
[
"çļĦæĿ",
"IJ"
],
[
"x",
"x"
],
[
"é¢ĺ",
"缮"
],
[
"ri",
"ption"
],
[
"éĤ£",
"äºĽ"
],
[
"Ġbud",
"get"
],
[
"Ġv",
"ast"
],
[
"éļIJ",
"ç§ģ"
],
[
"Ġpolic",
"ymakers"
],
[
"è¿ĺ",
"éľĢè¦ģ"
],
[
"å¹¶",
"æıIJä¾Ľ"
],
[
"Ġswe",
"et"
],
[
"Ġgener",
"al"
],
[
"æ»",
"¤"
],
[
"Ġbir",
"ds"
],
[
"Ġpl",
"astic"
],
[
"Ċ",
"ĉ"
],
[
"åĪ",
"º"
],
[
"ment",
"al"
],
[
"Ġincl",
"usive"
],
[
"Ġtop",
"ics"
],
[
"Ġs",
"low"
],
[
"ä½ł",
"èĥ½"
],
[
"è¶³å¤Ł",
"çļĦ"
],
[
"è§Ĩ",
"è§ī"
],
[
"w",
"w"
],
[
"Ġ",
"使ç͍"
],
[
"æī",
"¹"
],
[
"æ¦Ĥ",
"念"
],
[
"é£Ł",
"ç͍"
],
[
"èĢ",
"³"
],
[
"c",
"ks"
],
[
"Ġfra",
"ud"
],
[
"Ġingred",
"ients"
],
[
"Ġf",
"asc"
],
[
"åĮĹ",
"京"
],
[
"Ġf",
"r"
],
[
"Ġmanufact",
"uring"
],
[
"Ġ",
"ä½ľä¸º"
],
[
"Ġbe",
"ach"
],
[
"é¡",
"¿"
],
[
"eri",
"ous"
],
[
"å¤ĸ",
"è§Ĥ"
],
[
"é¢Ħ",
"éĺ²"
],
[
"æĿ¥",
"èĩª"
],
[
"èĤĮ",
"èĤī"
],
[
"Ġd",
"ays"
],
[
"Ġass",
"ign"
],
[
"Ġadv",
"ant"
],
[
"Ġteam",
"s"
],
[
"é¢",
"Ĺ"
],
[
"now",
"n"
],
[
"ĠP",
"o"
],
[
"}",
"{"
],
[
"Ġmin",
"ut"
],
[
"it",
"ions"
],
[
"Ġeas",
"ily"
],
[
"ĠB",
"l"
],
[
"n",
"ame"
],
[
"åѦ",
"æł¡"
],
[
"Ġrespons",
"ibility"
],
[
"åıij",
"æĮ¥"
],
[
"Ġsens",
"itive"
],
[
"çŃī",
"äºİ"
],
[
"ci",
"ous"
],
[
"Ġs",
"ou"
],
[
"å±",
"ı"
],
[
"Ġr",
"ich"
],
[
"å½ĵ",
"çĦ¶"
],
[
"m",
"an"
],
[
"Ġinterpre",
"t"
],
[
"2",
"4"
],
[
"Ġshow",
"s"
],
[
"èģĮ",
"åľº"
],
[
"Ġf",
"all"
],
[
"è½",
"½"
],
[
"丰å¯Į",
"çļĦ"
],
[
"(",
"'"
],
[
"ä¿®",
"æĶ¹"
],
[
"æĽ´",
"æį¢"
],
[
"A",
"l"
],
[
"åı¯èĥ½",
"æĺ¯"
],
[
"Ġr",
"ate"
],
[
"Ġprotect",
"ing"
],
[
"f",
"it"
],
[
"Ġ5",
"0"
],
[
"Ġmove",
"ment"
],
[
"è§",
"Ī"
],
[
"Ġemploy",
"ee"
],
[
"Ġdis",
"ord"
],
[
"åĪĽ",
"æĦı"
],
[
"产åĵģ",
"çļĦ"
],
[
"æľ",
"Ŀ"
],
[
"ĊĠĠĠĠĠĠĠĠ",
"ĠĠĠĠĠĠĠ"
],
[
"Ġpre",
"d"
],
[
"Ġoffer",
"ing"
],
[
"åįģ",
"åĪĨ"
],
[
"èĢĮ",
"ä¸įæĺ¯"
],
[
"Th",
"ank"
],
[
"æĽ",
"¾"
],
[
"Ġele",
"ments"
],
[
"ç²",
"Ĵ"
],
[
"Ġcour",
"ses"
],
[
"Ġintegr",
"ated"
],
[
"ĠC",
"ar"
],
[
"agra",
"ph"
],
[
"åŁº",
"åĽł"
],
[
"Ġinst",
"ead"
],
[
"èĦ",
"±"
],
[
"åı¦",
"ä¸Ģ个"
],
[
"å¯Ĩ",
"çłģ"
],
[
"Ġallow",
"ed"
],
[
"éĿ¢",
"åĮħ"
],
[
"çķ",
"ªèĮĦ"
],
[
"åĴĮ",
"åıijå±ķ"
],
[
"å°",
"ģ"
],
[
"Ġconnect",
"ion"
],
[
"åľ¨",
"ä¸Ģ个"
],
[
"Ġuse",
"ful"
],
[
"è¯Ń",
"åı¥"
],
[
"åĪĨ",
"å¸ĥ"
],
[
"表",
"æ¼Ķ"
],
[
"æľī",
"æĹ¶"
],
[
"çļĦæĹ",
"ħ"
],
[
"çļĦæĢ",
"»"
],
[
"Ġf",
"ashion"
],
[
"èĭ",
"¦"
],
[
"è¦ģ",
"注æĦı"
],
[
"çĶŁ",
"ç´ł"
],
[
"Ġnut",
"ri"
],
[
"èĩª",
"è¡Į"
],
[
"çļĦç",
"ĭ"
],
[
"çIJĨè§£",
"åĴĮ"
],
[
"Ġc",
"at"
],
[
"æľºåύ",
"åŃ¦ä¹ł"
],
[
"Ġexh",
"ib"
],
[
"åĴĮ",
"æľįåĬ¡"
],
[
"fra",
"c"
],
[
"e",
"pend"
],
[
"Ġimpact",
"ed"
],
[
"Ġ",
"ut"
],
[
"æķ°",
"ç»Ħ"
],
[
"ĠWor",
"ld"
],
[
"Ġansw",
"er"
],
[
"ers",
"e"
],
[
"éª",
"¨"
],
[
"Ġart",
"ists"
],
[
"åŃ©åŃIJ",
"çļĦ"
],
[
"ä»",
"Ķ"
],
[
"çĻ",
"»"
],
[
"ĠA",
"re"
],
[
"Ġco",
"ol"
],
[
"Ġcogn",
"itive"
],
[
"åIJĦ",
"个"
],
[
"l",
"ike"
],
[
"å©´",
"åĦ¿"
],
[
"åĪĹ",
"åĩº"
],
[
"å¹",
"»"
],
[
"ron",
"t"
],
[
"å®¶",
"éķ¿"
],
[
"缺",
"ä¹ı"
],
[
"Ġcy",
"ber"
],
[
"il",
"t"
],
[
"Ġcapt",
"ure"
],
[
"å",
"Ĺ"
],
[
"åľ¨",
"äºİ"
],
[
"Ġthreat",
"s"
],
[
"åĴĮ",
"社ä¼ļ"
],
[
"Ġcell",
"s"
],
[
"æ¸ħ",
"åįķ"
],
[
"ĠV",
"is"
],
[
"æİ",
"ī"
],
[
"Ġh",
"ol"
],
[
"åŃIJ",
"çļĦ"
],
[
"C",
"h"
],
[
"è",
"Ŀ"
],
[
"Ġs",
"aid"
],
[
"Ġd",
"ream"
],
[
"un",
"ch"
],
[
"un",
"e"
],
[
"ĠD",
"on"
],
[
"å®¶",
"人"
],
[
"ç±",
"į"
],
[
"æĦŁ",
"åĴĮ"
],
[
"Ġexperi",
"enced"
],
[
"çļĦéĩįè¦ģ",
"æĢ§"
],
[
"å¼",
"ĥ"
],
[
"um",
"p"
],
[
"éĺ",
"IJ"
],
[
"Ġhabit",
"at"
],
[
"è¢",
"ĭ"
],
[
"Ġj",
"o"
],
[
"ç®Ģ",
"æ´ģ"
],
[
"Ġb",
"ur"
],
[
"Ġvisit",
"ors"
],
[
"éĽ",
"ħ"
],
[
"çļĦçŁ",
"¥"
],
[
"Ġent",
"ire"
],
[
"讲",
"è¿°"
],
[
"äºĨ",
"ä¸ĢäºĽ"
],
[
"åįı",
"ä½ľ"
],
[
"ĠB",
"us"
],
[
"å°",
"¾"
],
[
"çļĦæķ",
"Ļ"
],
[
"olo",
"g"
],
[
"Ġsign",
"s"
],
[
"Ġspeak",
"er"
],
[
"çļĦ",
"éŁ³ä¹IJ"
],
[
"Ġno",
"vel"
],
[
"å±ħ",
"æ°ij"
],
[
"çļĦ",
"åıĺåĮĸ"
],
[
"å°½",
"éĩı"
],
[
"Ġspir",
"it"
],
[
"å®Į",
"ç¾İ"
],
[
"è´",
"·"
],
[
"å¿ħè¦ģ",
"çļĦ"
],
[
"ie",
"f"
],
[
"示",
"ä¾ĭ"
],
[
"Ġd",
"iv"
],
[
"æķ´",
"æķ°"
],
[
"Ġeconom",
"y"
],
[
"Ġethical",
"ly"
],
[
"éĻ",
"Ī"
],
[
"Ġschool",
"s"
],
[
"Ġnet",
"works"
]
]
}
}
================================================
FILE: model/tokenizer_config.json
================================================
{
"add_bos_token": false,
"add_eos_token": false,
"add_prefix_space": false,
"added_tokens_decoder": {
"0": {
"content": "<|endoftext|>",
"lstrip": false,
"normalized": false,
"rstrip": false,
"single_word": false,
"special": true
},
"1": {
"content": "<|im_start|>",
"lstrip": false,
"normalized": false,
"rstrip": false,
"single_word": false,
"special": true
},
"2": {
"content": "<|im_end|>",
"lstrip": false,
"normalized": false,
"rstrip": false,
"single_word": false,
"special": true
}
},
"additional_special_tokens": [],
"bos_token": "<|im_start|>",
"clean_up_tokenization_spaces": false,
"eos_token": "<|im_end|>",
"legacy": true,
"model_max_length": 32768,
"pad_token": "<|endoftext|>",
"sp_model_kwargs": {},
"spaces_between_special_tokens": false,
"tokenizer_class": "PreTrainedTokenizerFast",
"unk_token": "<|endoftext|>",
"chat_template": "{%- if tools %}\n {{- '<|im_start|>system\\n' }}\n {%- if messages[0].role == 'system' %}\n {{- messages[0].content + '\\n\\n' }}\n {%- endif %}\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\" }}\n {%- for tool in tools %}\n {{- \"\\n\" }}\n {{- tool | tojson }}\n {%- endfor %}\n {{- \"\\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\" }}\n{%- else %}\n {%- if messages[0]['role'] == 'system' -%}\n {{- '<|im_start|>system\\n' + messages[0]['content'] + '<|im_end|>\\n' }}\n {%- else -%}\n {{- '<|im_start|>system\\nYou are a helpful assistant<|im_end|>\\n' }}\n {%- endif %}\n{%- endif %}\n{%- set ns = namespace(multi_step_tool=true, last_query_index=messages|length - 1) %}\n{%- for message in messages[::-1] %}\n {%- set index = (messages|length - 1) - loop.index0 %}\n {%- if ns.multi_step_tool and message.role == \"user\" and message.content is string and not(message.content.startswith('') and message.content.endswith(' ')) %}\n {%- set ns.multi_step_tool = false %}\n {%- set ns.last_query_index = index %}\n {%- endif %}\n{%- endfor %}\n{%- for message in messages %}\n {%- if message.content is string %}\n {%- set content = message.content %}\n {%- else %}\n {%- set content = '' %}\n {%- endif %}\n {%- if (message.role == \"user\") or (message.role == \"system\" and not loop.first) %}\n {{- '<|im_start|>' + message.role + '\\n' + content + '<|im_end|>' + '\\n' }}\n {%- elif message.role == \"assistant\" %}\n {{- '<|im_start|>' + message.role + '\\n' + content }}\n {%- if message.tool_calls %}\n {%- for tool_call in message.tool_calls %}\n {%- if (loop.first and content) or (not loop.first) %}\n {{- '\\n' }}\n {%- endif %}\n {%- if tool_call.function %}\n {%- set tool_call = tool_call.function %}\n {%- endif %}\n {{- '\\n{\"name\": \"' }}\n {{- tool_call.name }}\n {{- '\", \"arguments\": ' }}\n {%- if tool_call.arguments is string %}\n {{- tool_call.arguments }}\n {%- else %}\n {{- tool_call.arguments | tojson }}\n {%- endif %}\n {{- '}\\n ' }}\n {%- endfor %}\n {%- endif %}\n {{- '<|im_end|>\\n' }}\n {%- elif message.role == \"tool\" %}\n {%- if loop.first or (messages[loop.index0 - 1].role != \"tool\") %}\n {{- '<|im_start|>user' }}\n {%- endif %}\n {{- '\\n\\n' }}\n {{- content }}\n {{- '\\n ' }}\n {%- if loop.last or (messages[loop.index0 + 1].role != \"tool\") %}\n {{- '<|im_end|>\\n' }}\n {%- endif %}\n {%- endif %}\n{%- endfor %}\n{%- if add_generation_prompt %}\n {{- '<|im_start|>assistant\\n' }}\n {%- if enable_thinking is defined and enable_thinking is false %}\n {{- '\\n\\n \\n\\n' }}\n {%- endif %}\n{%- endif %}"
}
================================================
FILE: requirements.txt
================================================
datasets==3.6.0
datasketch==1.6.4
Flask==3.0.3
Flask_Cors==4.0.0
jieba==0.42.1
jsonlines==4.0.0
marshmallow==3.22.0
matplotlib==3.10.0
ngrok==1.4.0
nltk==3.8
numpy==1.26.4
openai==1.59.6
peft==0.7.1
psutil==5.9.8
pydantic==2.11.5
rich==13.7.1
scikit_learn==1.5.1
sentence_transformers==2.3.1
simhash==2.1.2
tiktoken==0.10.0
transformers==4.57.1
jinja2==3.1.2
jsonlines==4.0.0
trl==0.13.0
ujson==5.1.0
wandb==0.18.3
streamlit==1.50.0
einops==0.8.1
swanlab==0.6.8
torch==2.6.0
torchvision==0.21.0
================================================
FILE: scripts/chat_openai_api.py
================================================
from openai import OpenAI
client = OpenAI(
api_key="ollama",
base_url="http://127.0.0.1:8998/v1"
)
stream = True
conversation_history_origin = []
conversation_history = conversation_history_origin.copy()
history_messages_num = 0 # 必须设置为偶数(Q+A),为0则不携带历史对话
while True:
query = input('[Q]: ')
conversation_history.append({"role": "user", "content": query})
response = client.chat.completions.create(
model="minimind",
messages=conversation_history[-(history_messages_num or 1):],
stream=stream,
temperature=0.7,
max_tokens=2048,
top_p=0.9
)
if not stream:
assistant_res = response.choices[0].message.content
print('[A]: ', assistant_res)
else:
print('[A]: ', end='')
assistant_res = ''
for chunk in response:
print(chunk.choices[0].delta.content or "", end="")
assistant_res += chunk.choices[0].delta.content or ""
conversation_history.append({"role": "assistant", "content": assistant_res})
print('\n\n')
================================================
FILE: scripts/convert_model.py
================================================
import os
import sys
import json
__package__ = "scripts"
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
import torch
import warnings
from transformers import AutoTokenizer, AutoModelForCausalLM, LlamaConfig, LlamaForCausalLM
from model.model_minimind import MiniMindConfig, MiniMindForCausalLM
warnings.filterwarnings('ignore', category=UserWarning)
# MoE模型需使用此函数转换
def convert_torch2transformers_minimind(torch_path, transformers_path, dtype=torch.float16):
MiniMindConfig.register_for_auto_class()
MiniMindForCausalLM.register_for_auto_class("AutoModelForCausalLM")
lm_model = MiniMindForCausalLM(lm_config)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
state_dict = torch.load(torch_path, map_location=device)
lm_model.load_state_dict(state_dict, strict=False)
lm_model = lm_model.to(dtype) # 转换模型权重精度
model_params = sum(p.numel() for p in lm_model.parameters() if p.requires_grad)
print(f'模型参数: {model_params / 1e6} 百万 = {model_params / 1e9} B (Billion)')
lm_model.save_pretrained(transformers_path, safe_serialization=False)
tokenizer = AutoTokenizer.from_pretrained('../model/')
tokenizer.save_pretrained(transformers_path)
# 兼容transformers-5.0的写法
config_path = os.path.join(transformers_path, "tokenizer_config.json")
json.dump({**json.load(open(config_path, 'r', encoding='utf-8')), "tokenizer_class": "PreTrainedTokenizerFast", "extra_special_tokens": {}}, open(config_path, 'w', encoding='utf-8'), indent=2, ensure_ascii=False)
print(f"模型已保存为 Transformers-MiniMind 格式: {transformers_path}")
# LlamaForCausalLM结构兼容第三方生态
def convert_torch2transformers_llama(torch_path, transformers_path, dtype=torch.float16):
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
state_dict = torch.load(torch_path, map_location=device)
llama_config = LlamaConfig(
vocab_size=lm_config.vocab_size,
hidden_size=lm_config.hidden_size,
intermediate_size=64 * ((int(lm_config.hidden_size * 8 / 3) + 64 - 1) // 64),
num_hidden_layers=lm_config.num_hidden_layers,
num_attention_heads=lm_config.num_attention_heads,
num_key_value_heads=lm_config.num_key_value_heads,
max_position_embeddings=lm_config.max_position_embeddings,
rms_norm_eps=lm_config.rms_norm_eps,
rope_theta=lm_config.rope_theta,
tie_word_embeddings=True
)
llama_model = LlamaForCausalLM(llama_config)
llama_model.load_state_dict(state_dict, strict=False)
llama_model = llama_model.to(dtype) # 转换模型权重精度
llama_model.save_pretrained(transformers_path)
model_params = sum(p.numel() for p in llama_model.parameters() if p.requires_grad)
print(f'模型参数: {model_params / 1e6} 百万 = {model_params / 1e9} B (Billion)')
tokenizer = AutoTokenizer.from_pretrained('../model/')
tokenizer.save_pretrained(transformers_path)
# 兼容transformers-5.0的写法
config_path = os.path.join(transformers_path, "tokenizer_config.json")
json.dump({**json.load(open(config_path, 'r', encoding='utf-8')), "tokenizer_class": "PreTrainedTokenizerFast", "extra_special_tokens": {}}, open(config_path, 'w', encoding='utf-8'), indent=2, ensure_ascii=False)
print(f"模型已保存为 Transformers-Llama 格式: {transformers_path}")
def convert_transformers2torch(transformers_path, torch_path):
model = AutoModelForCausalLM.from_pretrained(transformers_path, trust_remote_code=True)
torch.save({k: v.cpu().half() for k, v in model.state_dict().items()}, torch_path)
print(f"模型已保存为 PyTorch 格式 (half精度): {torch_path}")
if __name__ == '__main__':
lm_config = MiniMindConfig(hidden_size=512, num_hidden_layers=8, max_seq_len=8192, use_moe=False)
torch_path = f"../out/full_sft_{lm_config.hidden_size}{'_moe' if lm_config.use_moe else ''}.pth"
transformers_path = '../MiniMind2-Small'
convert_torch2transformers_llama(torch_path, transformers_path)
# # convert transformers to torch model
# convert_transformers2torch(transformers_path, torch_path)
================================================
FILE: scripts/serve_openai_api.py
================================================
import argparse
import json
import os
import sys
__package__ = "scripts"
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
import time
import torch
import warnings
import uvicorn
from threading import Thread
from queue import Queue
from fastapi import FastAPI, HTTPException
from fastapi.responses import StreamingResponse
from pydantic import BaseModel
from transformers import AutoTokenizer, AutoModelForCausalLM, TextStreamer
from model.model_minimind import MiniMindConfig, MiniMindForCausalLM
from model.model_lora import apply_lora, load_lora
warnings.filterwarnings('ignore')
app = FastAPI()
def init_model(args):
tokenizer = AutoTokenizer.from_pretrained(args.load_from)
if 'model' in args.load_from:
moe_suffix = '_moe' if args.use_moe else ''
ckp = f'../{args.save_dir}/{args.weight}_{args.hidden_size}{moe_suffix}.pth'
model = MiniMindForCausalLM(MiniMindConfig(
hidden_size=args.hidden_size,
num_hidden_layers=args.num_hidden_layers,
max_seq_len=args.max_seq_len,
use_moe=bool(args.use_moe),
inference_rope_scaling=args.inference_rope_scaling
))
model.load_state_dict(torch.load(ckp, map_location=device), strict=True)
if args.lora_weight != 'None':
apply_lora(model)
load_lora(model, f'../{args.save_dir}/lora/{args.lora_weight}_{args.hidden_size}.pth')
else:
model = AutoModelForCausalLM.from_pretrained(args.load_from, trust_remote_code=True)
print(f'MiniMind模型参数量: {sum(p.numel() for p in model.parameters()) / 1e6:.2f} M(illion)')
return model.eval().to(device), tokenizer
class ChatRequest(BaseModel):
model: str
messages: list
temperature: float = 0.7
top_p: float = 0.92
max_tokens: int = 8192
stream: bool = False
tools: list = []
class CustomStreamer(TextStreamer):
def __init__(self, tokenizer, queue):
super().__init__(tokenizer, skip_prompt=True, skip_special_tokens=True)
self.queue = queue
self.tokenizer = tokenizer
def on_finalized_text(self, text: str, stream_end: bool = False):
self.queue.put(text)
if stream_end:
self.queue.put(None)
def generate_stream_response(messages, temperature, top_p, max_tokens):
try:
new_prompt = tokenizer.apply_chat_template(messages, tokenize=False, add_generation_prompt=True)[-max_tokens:]
inputs = tokenizer(new_prompt, return_tensors="pt", truncation=True).to(device)
queue = Queue()
streamer = CustomStreamer(tokenizer, queue)
def _generate():
model.generate(
inputs.input_ids,
max_new_tokens=max_tokens,
do_sample=True,
temperature=temperature,
top_p=top_p,
attention_mask=inputs.attention_mask,
pad_token_id=tokenizer.pad_token_id,
eos_token_id=tokenizer.eos_token_id,
streamer=streamer
)
Thread(target=_generate).start()
while True:
text = queue.get()
if text is None:
yield json.dumps({
"choices": [{
"delta": {},
"finish_reason": "stop"
}]
}, ensure_ascii=False)
break
yield json.dumps({
"choices": [{"delta": {"content": text}}]
}, ensure_ascii=False)
except Exception as e:
yield json.dumps({"error": str(e)})
@app.post("/v1/chat/completions")
async def chat_completions(request: ChatRequest):
try:
if request.stream:
return StreamingResponse(
(f"data: {chunk}\n\n" for chunk in generate_stream_response(
messages=request.messages,
temperature=request.temperature,
top_p=request.top_p,
max_tokens=request.max_tokens
)),
media_type="text/event-stream"
)
else:
new_prompt = tokenizer.apply_chat_template(
request.messages,
tokenize=False,
add_generation_prompt=True
)[-request.max_tokens:]
inputs = tokenizer(new_prompt, return_tensors="pt", truncation=True).to(device)
with torch.no_grad():
generated_ids = model.generate(
inputs["input_ids"],
max_length=inputs["input_ids"].shape[1] + request.max_tokens,
do_sample=True,
attention_mask=inputs["attention_mask"],
pad_token_id=tokenizer.pad_token_id,
eos_token_id=tokenizer.eos_token_id,
top_p=request.top_p,
temperature=request.temperature
)
answer = tokenizer.decode(generated_ids[0][inputs["input_ids"].shape[1]:], skip_special_tokens=True)
return {
"id": f"chatcmpl-{int(time.time())}",
"object": "chat.completion",
"created": int(time.time()),
"model": "minimind",
"choices": [
{
"index": 0,
"message": {"role": "assistant", "content": answer},
"finish_reason": "stop"
}
]
}
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="Server for MiniMind")
parser.add_argument('--load_from', default='../model', type=str, help="模型加载路径(model=原生torch权重,其他路径=transformers格式)")
parser.add_argument('--save_dir', default='out', type=str, help="模型权重目录")
parser.add_argument('--weight', default='full_sft', type=str, help="权重名称前缀(pretrain, full_sft, dpo, reason, ppo_actor, grpo, spo)")
parser.add_argument('--lora_weight', default='None', type=str, help="LoRA权重名称(None表示不使用,可选:lora_identity, lora_medical)")
parser.add_argument('--hidden_size', default=512, type=int, help="隐藏层维度(512=Small-26M, 640=MoE-145M, 768=Base-104M)")
parser.add_argument('--num_hidden_layers', default=8, type=int, help="隐藏层数量(Small/MoE=8, Base=16)")
parser.add_argument('--max_seq_len', default=8192, type=int, help="最大序列长度")
parser.add_argument('--use_moe', default=0, type=int, choices=[0, 1], help="是否使用MoE架构(0=否,1=是)")
parser.add_argument('--inference_rope_scaling', default=False, action='store_true', help="启用RoPE位置编码外推(4倍,仅解决位置编码问题)")
parser.add_argument('--device', default='cuda' if torch.cuda.is_available() else 'cpu', type=str, help="运行设备")
args = parser.parse_args()
device = args.device
model, tokenizer = init_model(args)
uvicorn.run(app, host="0.0.0.0", port=8998)
================================================
FILE: scripts/web_demo.py
================================================
import random
import re
from threading import Thread
import torch
import numpy as np
import streamlit as st
st.set_page_config(page_title="MiniMind", initial_sidebar_state="collapsed")
st.markdown("""
""", unsafe_allow_html=True)
system_prompt = []
device = "cuda" if torch.cuda.is_available() else "cpu"
def process_assistant_content(content):
if model_source == "API" and 'R1' not in api_model_name:
return content
if model_source != "API" and 'R1' not in MODEL_PATHS[selected_model][1]:
return content
if '' in content and ' ' in content:
content = re.sub(r'()(.*?)( )',
r'推理内容(展开) \2 ',
content,
flags=re.DOTALL)
if '' in content and ' ' not in content:
content = re.sub(r'(.*?)$',
r'推理中... \1 ',
content,
flags=re.DOTALL)
if '' not in content and ' ' in content:
content = re.sub(r'(.*?) ',
r'推理内容(展开) \1 ',
content,
flags=re.DOTALL)
return content
@st.cache_resource
def load_model_tokenizer(model_path):
model = AutoModelForCausalLM.from_pretrained(
model_path,
trust_remote_code=True
)
tokenizer = AutoTokenizer.from_pretrained(
model_path,
trust_remote_code=True
)
model = model.eval().to(device)
return model, tokenizer
def clear_chat_messages():
del st.session_state.messages
del st.session_state.chat_messages
def init_chat_messages():
if "messages" in st.session_state:
for i, message in enumerate(st.session_state.messages):
if message["role"] == "assistant":
with st.chat_message("assistant", avatar=image_url):
st.markdown(process_assistant_content(message["content"]), unsafe_allow_html=True)
if st.button("🗑", key=f"delete_{i}"):
st.session_state.messages.pop(i)
st.session_state.messages.pop(i - 1)
st.session_state.chat_messages.pop(i)
st.session_state.chat_messages.pop(i - 1)
st.rerun()
else:
st.markdown(
f'',
unsafe_allow_html=True)
else:
st.session_state.messages = []
st.session_state.chat_messages = []
return st.session_state.messages
def regenerate_answer(index):
st.session_state.messages.pop()
st.session_state.chat_messages.pop()
st.rerun()
def delete_conversation(index):
st.session_state.messages.pop(index)
st.session_state.messages.pop(index - 1)
st.session_state.chat_messages.pop(index)
st.session_state.chat_messages.pop(index - 1)
st.rerun()
st.sidebar.title("模型设定调整")
# st.sidebar.text("训练数据偏差,增加上下文记忆时\n多轮对话(较单轮)容易出现能力衰减")
st.session_state.history_chat_num = st.sidebar.slider("Number of Historical Dialogues", 0, 6, 0, step=2)
# st.session_state.history_chat_num = 0
st.session_state.max_new_tokens = st.sidebar.slider("Max Sequence Length", 256, 8192, 8192, step=1)
st.session_state.temperature = st.sidebar.slider("Temperature", 0.6, 1.2, 0.85, step=0.01)
model_source = st.sidebar.radio("选择模型来源", ["本地模型", "API"], index=0)
if model_source == "API":
api_url = st.sidebar.text_input("API URL", value="http://127.0.0.1:8000/v1")
api_model_id = st.sidebar.text_input("Model ID", value="minimind")
api_model_name = st.sidebar.text_input("Model Name", value="MiniMind2")
api_key = st.sidebar.text_input("API Key", value="none", type="password")
slogan = f"Hi, I'm {api_model_name}"
else:
MODEL_PATHS = {
"MiniMind2-R1 (0.1B)": ["../MiniMind2-R1", "MiniMind2-R1"],
"MiniMind2-Small-R1 (0.02B)": ["../MiniMind2-Small-R1", "MiniMind2-Small-R1"],
"MiniMind2 (0.1B)": ["../MiniMind2", "MiniMind2"],
"MiniMind2-MoE (0.15B)": ["../MiniMind2-MoE", "MiniMind2-MoE"],
"MiniMind2-Small (0.02B)": ["../MiniMind2-Small", "MiniMind2-Small"]
}
selected_model = st.sidebar.selectbox('Models', list(MODEL_PATHS.keys()), index=2) # 默认选择 MiniMind2
model_path = MODEL_PATHS[selected_model][0]
slogan = f"Hi, I'm {MODEL_PATHS[selected_model][1]}"
image_url = "https://www.modelscope.cn/api/v1/studio/gongjy/MiniMind/repo?Revision=master&FilePath=images%2Flogo2.png&View=true"
st.markdown(
f''
'
'
f'
'
f'
{slogan} '
'
'
'
内容完全由AI生成,请务必仔细甄别 Content AI-generated, please discern with care '
'
',
unsafe_allow_html=True
)
def setup_seed(seed):
random.seed(seed)
np.random.seed(seed)
torch.manual_seed(seed)
torch.cuda.manual_seed(seed)
torch.cuda.manual_seed_all(seed)
torch.backends.cudnn.deterministic = True
torch.backends.cudnn.benchmark = False
def main():
if model_source == "本地模型":
model, tokenizer = load_model_tokenizer(model_path)
else:
model, tokenizer = None, None
if "messages" not in st.session_state:
st.session_state.messages = []
st.session_state.chat_messages = []
messages = st.session_state.messages
for i, message in enumerate(messages):
if message["role"] == "assistant":
with st.chat_message("assistant", avatar=image_url):
st.markdown(process_assistant_content(message["content"]), unsafe_allow_html=True)
if st.button("×", key=f"delete_{i}"):
st.session_state.messages = st.session_state.messages[:i - 1]
st.session_state.chat_messages = st.session_state.chat_messages[:i - 1]
st.rerun()
else:
st.markdown(
f'',
unsafe_allow_html=True)
prompt = st.chat_input(key="input", placeholder="给 MiniMind 发送消息")
if hasattr(st.session_state, 'regenerate') and st.session_state.regenerate:
prompt = st.session_state.last_user_message
regenerate_index = st.session_state.regenerate_index
delattr(st.session_state, 'regenerate')
delattr(st.session_state, 'last_user_message')
delattr(st.session_state, 'regenerate_index')
if prompt:
st.markdown(
f'',
unsafe_allow_html=True)
messages.append({"role": "user", "content": prompt[-st.session_state.max_new_tokens:]})
st.session_state.chat_messages.append({"role": "user", "content": prompt[-st.session_state.max_new_tokens:]})
with st.chat_message("assistant", avatar=image_url):
placeholder = st.empty()
if model_source == "API":
try:
from openai import OpenAI
client = OpenAI(
api_key=api_key,
base_url=api_url
)
history_num = st.session_state.history_chat_num + 1 # +1 是为了包含当前的用户消息
conversation_history = system_prompt + st.session_state.chat_messages[-history_num:]
answer = ""
response = client.chat.completions.create(
model=api_model_id,
messages=conversation_history,
stream=True,
temperature=st.session_state.temperature
)
for chunk in response:
content = chunk.choices[0].delta.content or ""
answer += content
placeholder.markdown(process_assistant_content(answer), unsafe_allow_html=True)
except Exception as e:
answer = f"API调用出错: {str(e)}"
placeholder.markdown(answer, unsafe_allow_html=True)
else:
random_seed = random.randint(0, 2 ** 32 - 1)
setup_seed(random_seed)
st.session_state.chat_messages = system_prompt + st.session_state.chat_messages[
-(st.session_state.history_chat_num + 1):]
new_prompt = tokenizer.apply_chat_template(
st.session_state.chat_messages,
tokenize=False,
add_generation_prompt=True
)
inputs = tokenizer(
new_prompt,
return_tensors="pt",
truncation=True
).to(device)
streamer = TextIteratorStreamer(tokenizer, skip_prompt=True, skip_special_tokens=True)
generation_kwargs = {
"input_ids": inputs.input_ids,
"max_length": inputs.input_ids.shape[1] + st.session_state.max_new_tokens,
"num_return_sequences": 1,
"do_sample": True,
"attention_mask": inputs.attention_mask,
"pad_token_id": tokenizer.pad_token_id,
"eos_token_id": tokenizer.eos_token_id,
"temperature": st.session_state.temperature,
"top_p": 0.85,
"streamer": streamer,
}
Thread(target=model.generate, kwargs=generation_kwargs).start()
answer = ""
for new_text in streamer:
answer += new_text
placeholder.markdown(process_assistant_content(answer), unsafe_allow_html=True)
messages.append({"role": "assistant", "content": answer})
st.session_state.chat_messages.append({"role": "assistant", "content": answer})
with st.empty():
if st.button("×", key=f"delete_{len(messages) - 1}"):
st.session_state.messages = st.session_state.messages[:-2]
st.session_state.chat_messages = st.session_state.chat_messages[:-2]
st.rerun()
if __name__ == "__main__":
from transformers import AutoModelForCausalLM, AutoTokenizer, TextIteratorStreamer
main()
================================================
FILE: trainer/train_distillation.py
================================================
import os
import sys
__package__ = "trainer"
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
import argparse
import time
import warnings
import torch
import torch.nn.functional as F
import torch.distributed as dist
from contextlib import nullcontext
from torch import optim
from torch.nn.parallel import DistributedDataParallel
from torch.utils.data import DataLoader, DistributedSampler
from model.model_minimind import MiniMindConfig
from dataset.lm_dataset import SFTDataset
from trainer.trainer_utils import get_lr, Logger, is_main_process, lm_checkpoint, init_distributed_mode, setup_seed, init_model, SkipBatchSampler
warnings.filterwarnings('ignore')
def distillation_loss(student_logits, teacher_logits, temperature=1.0, reduction='batchmean'):
with torch.no_grad():
teacher_probs = F.softmax(teacher_logits / temperature, dim=-1).detach()
student_log_probs = F.log_softmax(student_logits / temperature, dim=-1)
kl = F.kl_div(
student_log_probs,
teacher_probs,
reduction=reduction
)
return (temperature ** 2) * kl
def train_epoch(epoch, loader, iters, teacher_model, lm_config_student, start_step=0, wandb=None, alpha=0.0, temperature=1.0):
start_time = time.time()
if teacher_model is not None:
teacher_model.eval()
teacher_model.requires_grad_(False)
for step, (input_ids, labels) in enumerate(loader, start=start_step + 1):
input_ids = input_ids.to(args.device)
labels = labels.to(args.device)
loss_mask = (labels[..., 1:] != -100).float()
lr = get_lr(epoch * iters + step, args.epochs * iters, args.learning_rate)
for param_group in optimizer.param_groups:
param_group['lr'] = lr
# 前向传播(学生模型)
with autocast_ctx:
res = model(input_ids)
student_logits = res.logits[..., :-1, :].contiguous()
# 教师模型前向传播(只在eval & no_grad)
if teacher_model is not None:
with torch.no_grad():
teacher_logits = teacher_model(input_ids).logits[..., :-1, :].contiguous()
vocab_size_student = student_logits.size(-1)
teacher_logits = teacher_logits[..., :vocab_size_student]
# ========== 计算损失 ==========
# 1) Ground-Truth CE Loss
shift_labels = labels[..., 1:].contiguous()
loss_mask_flat = loss_mask.view(-1)
ce_loss = F.cross_entropy(
student_logits.view(-1, student_logits.size(-1)),
shift_labels.view(-1),
ignore_index=-100,
reduction='none'
)
ce_loss_raw = torch.sum(ce_loss * loss_mask_flat) / (loss_mask_flat.sum() + 1e-8)
if lm_config_student.use_moe: ce_loss = ce_loss_raw + res.aux_loss
else: ce_loss = ce_loss_raw
# 2) Distillation Loss
if teacher_model is not None:
distill_loss = distillation_loss(
student_logits.view(-1, student_logits.size(-1))[loss_mask_flat == 1],
teacher_logits.view(-1, teacher_logits.size(-1))[loss_mask_flat == 1],
temperature=temperature
)
else:
distill_loss = torch.tensor(0.0, device=args.device)
# 3) 总损失 = alpha * CE + (1-alpha) * Distill
loss = (alpha * ce_loss + (1 - alpha) * distill_loss) / args.accumulation_steps
scaler.scale(loss).backward()
if (step + 1) % args.accumulation_steps == 0:
scaler.unscale_(optimizer)
torch.nn.utils.clip_grad_norm_(model.parameters(), args.grad_clip)
scaler.step(optimizer)
scaler.update()
optimizer.zero_grad(set_to_none=True)
if step % args.log_interval == 0 or step == iters - 1:
spend_time = time.time() - start_time
current_loss = loss.item() * args.accumulation_steps
current_ce_loss = ce_loss_raw.item()
current_aux_loss = res.aux_loss.item() if lm_config_student.use_moe else 0.0
current_lr = optimizer.param_groups[-1]['lr']
eta_min = spend_time / (step + 1) * iters // 60 - spend_time // 60
Logger(f'Epoch:[{epoch + 1}/{args.epochs}]({step}/{iters}), loss: {current_loss:.4f}, ce: {current_ce_loss:.4f}, aux_loss: {current_aux_loss:.4f}, distill: {distill_loss.item():.4f}, learning_rate: {current_lr:.8f}, epoch_time: {eta_min:.3f}min')
if wandb:
wandb.log({
"loss": current_loss,
"ce_loss": current_ce_loss,
"aux_loss": current_aux_loss,
"distill_loss": distill_loss.item() if teacher_model is not None else 0.0,
"learning_rate": current_lr,
"epoch_time": eta_min
})
if (step % args.save_interval == 0 or step == iters - 1) and is_main_process():
model.eval()
moe_suffix = '_moe' if lm_config_student.use_moe else ''
ckp = f'{args.save_dir}/{args.save_weight}_{lm_config_student.hidden_size}{moe_suffix}.pth'
raw_model = model.module if isinstance(model, DistributedDataParallel) else model
raw_model = getattr(raw_model, '_orig_mod', raw_model)
state_dict = raw_model.state_dict()
torch.save({k: v.half().cpu() for k, v in state_dict.items()}, ckp)
lm_checkpoint(lm_config_student, weight=args.save_weight, model=model, optimizer=optimizer, scaler=scaler, epoch=epoch, step=step, wandb=wandb, save_dir='../checkpoints')
model.train()
del state_dict
del input_ids, labels, loss_mask, res, student_logits, ce_loss, distill_loss, loss
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="MiniMind Knowledge Distillation")
parser.add_argument("--save_dir", type=str, default="../out", help="模型保存目录")
parser.add_argument('--save_weight', default='full_dist', type=str, help="保存权重的前缀名")
parser.add_argument("--epochs", type=int, default=6, help="训练轮数")
parser.add_argument("--batch_size", type=int, default=32, help="batch size")
parser.add_argument("--learning_rate", type=float, default=5e-6, help="初始学习率")
parser.add_argument("--device", type=str, default="cuda:0" if torch.cuda.is_available() else "cpu", help="训练设备")
parser.add_argument("--dtype", type=str, default="bfloat16", help="混合精度类型")
parser.add_argument("--num_workers", type=int, default=8, help="数据加载线程数")
parser.add_argument("--accumulation_steps", type=int, default=1, help="梯度累积步数")
parser.add_argument("--grad_clip", type=float, default=1.0, help="梯度裁剪阈值")
parser.add_argument("--log_interval", type=int, default=100, help="日志打印间隔")
parser.add_argument("--save_interval", type=int, default=100, help="模型保存间隔")
parser.add_argument("--max_seq_len", type=int, default=340, help="训练的最大截断长度(中文1token≈1.5~1.7字符)")
parser.add_argument("--data_path", type=str, default="../dataset/sft_mini_512.jsonl", help="训练数据路径")
parser.add_argument('--student_hidden_size', default=512, type=int, help="学生模型隐藏层维度")
parser.add_argument('--student_num_layers', default=8, type=int, help="学生模型隐藏层数量")
parser.add_argument('--teacher_hidden_size', default=768, type=int, help="教师模型隐藏层维度")
parser.add_argument('--teacher_num_layers', default=16, type=int, help="教师模型隐藏层数量")
parser.add_argument('--use_moe', default=0, type=int, choices=[0, 1], help="是否使用MoE架构(0=否,1=是)")
parser.add_argument('--from_student_weight', default='full_sft', type=str, help="学生模型基于哪个权重")
parser.add_argument('--from_teacher_weight', default='full_sft', type=str, help="教师模型基于哪个权重")
parser.add_argument('--from_resume', default=0, type=int, choices=[0, 1], help="是否自动检测&续训(0=否,1=是)")
parser.add_argument('--alpha', default=0.5, type=float, help="CE损失权重,总损失=alpha*CE+(1-alpha)*KL")
parser.add_argument('--temperature', default=1.5, type=float, help="蒸馏温度(推荐范围1.0-2.0)")
parser.add_argument("--use_wandb", action="store_true", help="是否使用wandb")
parser.add_argument("--wandb_project", type=str, default="MiniMind-Distillation", help="wandb项目名")
parser.add_argument("--use_compile", default=0, type=int, choices=[0, 1], help="是否使用torch.compile加速(0=否,1=是)")
args = parser.parse_args()
# ========== 1. 初始化环境和随机种子 ==========
local_rank = init_distributed_mode()
if dist.is_initialized(): args.device = f"cuda:{local_rank}"
setup_seed(42 + (dist.get_rank() if dist.is_initialized() else 0))
# ========== 2. 配置目录、模型参数、检查ckp ==========
os.makedirs(args.save_dir, exist_ok=True)
lm_config_student = MiniMindConfig(hidden_size=args.student_hidden_size, num_hidden_layers=args.student_num_layers, use_moe=bool(args.use_moe))
lm_config_teacher = MiniMindConfig(hidden_size=args.teacher_hidden_size, num_hidden_layers=args.teacher_num_layers, use_moe=bool(args.use_moe))
ckp_data = lm_checkpoint(lm_config_student, weight=args.save_weight, save_dir='../checkpoints') if args.from_resume==1 else None
# ========== 3. 设置混合精度 ==========
device_type = "cuda" if "cuda" in args.device else "cpu"
dtype = torch.bfloat16 if args.dtype == "bfloat16" else torch.float16
autocast_ctx = nullcontext() if device_type == "cpu" else torch.cuda.amp.autocast(dtype=dtype)
# ========== 4. 配wandb ==========
wandb = None
if args.use_wandb and is_main_process():
import swanlab as wandb
wandb_id = ckp_data.get('wandb_id') if ckp_data else None
resume = 'must' if wandb_id else None
wandb_run_name = f"MiniMind-Distill-S{args.student_hidden_size}T{args.teacher_hidden_size}-Epoch-{args.epochs}-BS-{args.batch_size}-LR-{args.learning_rate}"
wandb.init(project=args.wandb_project, name=wandb_run_name, id=wandb_id, resume=resume)
# ========== 5. 定义学生和教师模型 ==========
model, tokenizer = init_model(lm_config_student, args.from_student_weight, device=args.device)
if args.use_compile == 1:
model = torch.compile(model)
Logger('torch.compile enabled')
Logger(f'学生模型总参数量:{sum(p.numel() for p in model.parameters()) / 1e6:.3f} M')
teacher_model, _ = init_model(lm_config_teacher, args.from_teacher_weight, device=args.device)
teacher_model.eval()
teacher_model.requires_grad_(False)
Logger(f'教师模型总参数量:{sum(p.numel() for p in teacher_model.parameters()) / 1e6:.3f} M')
train_ds = SFTDataset(args.data_path, tokenizer, max_length=args.max_seq_len)
train_sampler = DistributedSampler(train_ds) if dist.is_initialized() else None
scaler = torch.cuda.amp.GradScaler(enabled=(args.dtype == 'float16'))
optimizer = optim.AdamW(model.parameters(), lr=args.learning_rate)
# ========== 6. 从ckp恢复状态 ==========
start_epoch, start_step = 0, 0
if ckp_data:
model.load_state_dict(ckp_data['model'])
optimizer.load_state_dict(ckp_data['optimizer'])
scaler.load_state_dict(ckp_data['scaler'])
start_epoch = ckp_data['epoch']
start_step = ckp_data.get('step', 0)
# ========== 7. DDP包模型 ==========
if dist.is_initialized():
model._ddp_params_and_buffers_to_ignore = {"freqs_cos", "freqs_sin"}
model = DistributedDataParallel(model, device_ids=[local_rank])
# ========== 8. 开始训练 ==========
for epoch in range(start_epoch, args.epochs):
train_sampler and train_sampler.set_epoch(epoch)
setup_seed(42 + epoch); indices = torch.randperm(len(train_ds)).tolist()
skip = start_step if (epoch == start_epoch and start_step > 0) else 0
batch_sampler = SkipBatchSampler(train_sampler or indices, args.batch_size, skip)
loader = DataLoader(train_ds, batch_sampler=batch_sampler, num_workers=args.num_workers, pin_memory=True)
if skip > 0:
Logger(f'Epoch [{epoch + 1}/{args.epochs}]: 跳过前{start_step}个step,从step {start_step + 1}开始')
train_epoch(epoch, loader, len(loader) + skip, teacher_model, lm_config_student, start_step, wandb, args.alpha, args.temperature)
else:
train_epoch(epoch, loader, len(loader), teacher_model, lm_config_student, 0, wandb, args.alpha, args.temperature)
# ========== 9. 清理分布进程 ==========
if dist.is_initialized(): dist.destroy_process_group()
================================================
FILE: trainer/train_dpo.py
================================================
import os
import sys
__package__ = "trainer"
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
import argparse
import time
import warnings
import torch
import torch.nn.functional as F
import torch.distributed as dist
from contextlib import nullcontext
from torch import optim
from torch.nn.parallel import DistributedDataParallel
from torch.utils.data import DataLoader, DistributedSampler
from model.model_minimind import MiniMindConfig
from dataset.lm_dataset import DPODataset
from trainer.trainer_utils import get_lr, Logger, is_main_process, lm_checkpoint, init_distributed_mode, setup_seed, init_model, SkipBatchSampler
warnings.filterwarnings('ignore')
def logits_to_log_probs(logits, labels):
# logits shape: (batch_size, seq_len, vocab_size)
# labels shape: (batch_size, seq_len)
# log_probs shape: (batch_size, seq_len)
log_probs = F.log_softmax(logits, dim=2)
log_probs_per_token = torch.gather(log_probs, dim=2, index=labels.unsqueeze(2)).squeeze(-1)
return log_probs_per_token
def dpo_loss(ref_log_probs, policy_log_probs, mask, beta):
# ref_log_probs 和 policy_log_probs 都是 shape: (batch_size, seq_len)
# https://github.com/jingyaogong/minimind/issues/298
seq_lengths = mask.sum(dim=1, keepdim=True).clamp_min(1e-8) # 防止零长度mask导致除零NaN
ref_log_probs = (ref_log_probs * mask).sum(dim=1) / seq_lengths.squeeze()
policy_log_probs = (policy_log_probs * mask).sum(dim=1) / seq_lengths.squeeze()
# 将 chosen 和 rejected 数据分开
batch_size = ref_log_probs.shape[0]
chosen_ref_log_probs = ref_log_probs[:batch_size // 2]
reject_ref_log_probs = ref_log_probs[batch_size // 2:]
chosen_policy_log_probs = policy_log_probs[:batch_size // 2]
reject_policy_log_probs = policy_log_probs[batch_size // 2:]
pi_logratios = chosen_policy_log_probs - reject_policy_log_probs
ref_logratios = chosen_ref_log_probs - reject_ref_log_probs
logits = pi_logratios - ref_logratios
loss = -F.logsigmoid(beta * logits)
return loss.mean()
def train_epoch(epoch, loader, iters, ref_model, lm_config, start_step=0, wandb=None, beta=0.1):
start_time = time.time()
for step, batch in enumerate(loader, start=start_step + 1):
x_chosen = batch['x_chosen'].to(args.device)
x_rejected = batch['x_rejected'].to(args.device)
y_chosen = batch['y_chosen'].to(args.device)
y_rejected = batch['y_rejected'].to(args.device)
mask_chosen = batch['mask_chosen'].to(args.device)
mask_rejected = batch['mask_rejected'].to(args.device)
x = torch.cat([x_chosen, x_rejected], dim=0)
y = torch.cat([y_chosen, y_rejected], dim=0)
mask = torch.cat([mask_chosen, mask_rejected], dim=0)
lr = get_lr(epoch * iters + step, args.epochs * iters, args.learning_rate)
for param_group in optimizer.param_groups:
param_group['lr'] = lr
with autocast_ctx:
with torch.no_grad():
ref_outputs = ref_model(x)
ref_logits = ref_outputs.logits
ref_log_probs = logits_to_log_probs(ref_logits, y)
outputs = model(x)
logits = outputs.logits
policy_log_probs = logits_to_log_probs(logits, y)
dpo_loss_val = dpo_loss(ref_log_probs, policy_log_probs, mask, beta=beta)
loss = dpo_loss_val + outputs.aux_loss
loss = loss / args.accumulation_steps
scaler.scale(loss).backward()
if (step + 1) % args.accumulation_steps == 0:
scaler.unscale_(optimizer)
torch.nn.utils.clip_grad_norm_(model.parameters(), args.grad_clip)
scaler.step(optimizer)
scaler.update()
optimizer.zero_grad(set_to_none=True)
if step % args.log_interval == 0 or step == iters - 1:
spend_time = time.time() - start_time
current_loss = loss.item() * args.accumulation_steps
current_dpo_loss = dpo_loss_val.item()
current_aux_loss = outputs.aux_loss.item()
current_lr = optimizer.param_groups[-1]['lr']
eta_min = spend_time / (step + 1) * iters // 60 - spend_time // 60
Logger(f'Epoch:[{epoch + 1}/{args.epochs}]({step}/{iters}), loss: {current_loss:.4f}, dpo_loss: {current_dpo_loss:.4f}, aux_loss: {current_aux_loss:.4f}, learning_rate: {current_lr:.8f}, epoch_time: {eta_min:.3f}min')
if wandb: wandb.log({"loss": current_loss, "dpo_loss": current_dpo_loss, "aux_loss": current_aux_loss, "learning_rate": current_lr, "epoch_time": eta_min})
if (step % args.save_interval == 0 or step == iters - 1) and is_main_process():
model.eval()
moe_suffix = '_moe' if lm_config.use_moe else ''
ckp = f'{args.save_dir}/{args.save_weight}_{lm_config.hidden_size}{moe_suffix}.pth'
raw_model = model.module if isinstance(model, DistributedDataParallel) else model
raw_model = getattr(raw_model, '_orig_mod', raw_model)
state_dict = raw_model.state_dict()
torch.save({k: v.half().cpu() for k, v in state_dict.items()}, ckp)
lm_checkpoint(lm_config, weight=args.save_weight, model=model, optimizer=optimizer, scaler=scaler, epoch=epoch, step=step, wandb=wandb, save_dir='../checkpoints')
model.train()
del state_dict
del x_chosen, x_rejected, y_chosen, y_rejected, mask_chosen, mask_rejected, x, y, mask
del ref_outputs, ref_logits, ref_log_probs, outputs, logits, policy_log_probs, loss
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="MiniMind DPO (Direct Preference Optimization)")
parser.add_argument("--save_dir", type=str, default="../out", help="模型保存目录")
parser.add_argument('--save_weight', default='dpo', type=str, help="保存权重的前缀名")
parser.add_argument("--epochs", type=int, default=1, help="训练轮数")
parser.add_argument("--batch_size", type=int, default=4, help="batch size")
parser.add_argument("--learning_rate", type=float, default=4e-8, help="初始学习率(建议<=5e-8避免遗忘)")
parser.add_argument("--device", type=str, default="cuda:0" if torch.cuda.is_available() else "cpu", help="训练设备")
parser.add_argument("--dtype", type=str, default="bfloat16", help="混合精度类型")
parser.add_argument("--num_workers", type=int, default=8, help="数据加载线程数")
parser.add_argument("--accumulation_steps", type=int, default=1, help="梯度累积步数")
parser.add_argument("--grad_clip", type=float, default=1.0, help="梯度裁剪阈值")
parser.add_argument("--log_interval", type=int, default=100, help="日志打印间隔")
parser.add_argument("--save_interval", type=int, default=100, help="模型保存间隔")
parser.add_argument('--hidden_size', default=512, type=int, help="隐藏层维度")
parser.add_argument('--num_hidden_layers', default=8, type=int, help="隐藏层数量")
parser.add_argument('--max_seq_len', default=1024, type=int, help="训练的最大截断长度(中文1token≈1.5~1.7字符)")
parser.add_argument('--use_moe', default=0, type=int, choices=[0, 1], help="是否使用MoE架构(0=否,1=是)")
parser.add_argument("--data_path", type=str, default="../dataset/dpo.jsonl", help="DPO训练数据路径")
parser.add_argument('--from_weight', default='full_sft', type=str, help="基于哪个权重训练")
parser.add_argument('--from_resume', default=0, type=int, choices=[0, 1], help="是否自动检测&续训(0=否,1=是)")
parser.add_argument('--beta', default=0.1, type=float, help="DPO中的beta参数")
parser.add_argument("--use_wandb", action="store_true", help="是否使用wandb")
parser.add_argument("--wandb_project", type=str, default="MiniMind-DPO", help="wandb项目名")
parser.add_argument("--use_compile", default=0, type=int, choices=[0, 1], help="是否使用torch.compile加速(0=否,1=是)")
args = parser.parse_args()
# ========== 1. 初始化环境和随机种子 ==========
local_rank = init_distributed_mode()
if dist.is_initialized(): args.device = f"cuda:{local_rank}"
setup_seed(42 + (dist.get_rank() if dist.is_initialized() else 0))
# ========== 2. 配置目录、模型参数、检查ckp ==========
os.makedirs(args.save_dir, exist_ok=True)
lm_config = MiniMindConfig(hidden_size=args.hidden_size, num_hidden_layers=args.num_hidden_layers, use_moe=bool(args.use_moe))
ckp_data = lm_checkpoint(lm_config, weight=args.save_weight, save_dir='../checkpoints') if args.from_resume==1 else None
# ========== 3. 设置混合精度 ==========
device_type = "cuda" if "cuda" in args.device else "cpu"
dtype = torch.bfloat16 if args.dtype == "bfloat16" else torch.float16
autocast_ctx = nullcontext() if device_type == "cpu" else torch.cuda.amp.autocast(dtype=dtype)
# ========== 4. 配wandb ==========
wandb = None
if args.use_wandb and is_main_process():
import swanlab as wandb
wandb_id = ckp_data.get('wandb_id') if ckp_data else None
resume = 'must' if wandb_id else None
wandb_run_name = f"MiniMind-DPO-Epoch-{args.epochs}-BatchSize-{args.batch_size}-LR-{args.learning_rate}"
wandb.init(project=args.wandb_project, name=wandb_run_name, id=wandb_id, resume=resume)
# ========== 5. 定义模型和参考模型 ==========
model, tokenizer = init_model(lm_config, args.from_weight, device=args.device)
if args.use_compile == 1:
model = torch.compile(model)
Logger('torch.compile enabled')
Logger(f'策略模型总参数量:{sum(p.numel() for p in model.parameters()) / 1e6:.3f} M')
# 初始化参考模型(ref_model冻结)
ref_model, _ = init_model(lm_config, args.from_weight, device=args.device)
ref_model.eval()
ref_model.requires_grad_(False)
Logger(f'参考模型总参数量:{sum(p.numel() for p in ref_model.parameters()) / 1e6:.3f} M')
train_ds = DPODataset(args.data_path, tokenizer, max_length=args.max_seq_len)
train_sampler = DistributedSampler(train_ds) if dist.is_initialized() else None
scaler = torch.cuda.amp.GradScaler(enabled=(args.dtype == 'float16'))
optimizer = optim.AdamW(model.parameters(), lr=args.learning_rate)
# ========== 6. 从ckp恢复状态 ==========
start_epoch, start_step = 0, 0
if ckp_data:
model.load_state_dict(ckp_data['model'])
optimizer.load_state_dict(ckp_data['optimizer'])
scaler.load_state_dict(ckp_data['scaler'])
start_epoch = ckp_data['epoch']
start_step = ckp_data.get('step', 0)
# ========== 7. DDP包模型 ==========
if dist.is_initialized():
model._ddp_params_and_buffers_to_ignore = {"freqs_cos", "freqs_sin"}
model = DistributedDataParallel(model, device_ids=[local_rank])
# ========== 8. 开始训练 ==========
for epoch in range(start_epoch, args.epochs):
train_sampler and train_sampler.set_epoch(epoch)
setup_seed(42 + epoch); indices = torch.randperm(len(train_ds)).tolist()
skip = start_step if (epoch == start_epoch and start_step > 0) else 0
batch_sampler = SkipBatchSampler(train_sampler or indices, args.batch_size, skip)
loader = DataLoader(train_ds, batch_sampler=batch_sampler, num_workers=args.num_workers, pin_memory=True)
if skip > 0:
Logger(f'Epoch [{epoch + 1}/{args.epochs}]: 跳过前{start_step}个step,从step {start_step + 1}开始')
train_epoch(epoch, loader, len(loader) + skip, ref_model, lm_config, start_step, wandb, args.beta)
else:
train_epoch(epoch, loader, len(loader), ref_model, lm_config, 0, wandb, args.beta)
# ========== 9. 清理分布进程 ==========
if dist.is_initialized(): dist.destroy_process_group()
================================================
FILE: trainer/train_full_sft.py
================================================
import os
import sys
__package__ = "trainer"
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
import argparse
import time
import warnings
import torch
import torch.distributed as dist
from contextlib import nullcontext
from torch import optim, nn
from torch.nn.parallel import DistributedDataParallel
from torch.utils.data import DataLoader, DistributedSampler
from model.model_minimind import MiniMindConfig
from dataset.lm_dataset import SFTDataset
from trainer.trainer_utils import get_lr, Logger, is_main_process, lm_checkpoint, init_distributed_mode, setup_seed, init_model, SkipBatchSampler
warnings.filterwarnings('ignore')
def train_epoch(epoch, loader, iters, start_step=0, wandb=None):
start_time = time.time()
for step, (input_ids, labels) in enumerate(loader, start=start_step + 1):
input_ids = input_ids.to(args.device)
labels = labels.to(args.device)
lr = get_lr(epoch * iters + step, args.epochs * iters, args.learning_rate)
for param_group in optimizer.param_groups:
param_group['lr'] = lr
with autocast_ctx:
res = model(input_ids, labels=labels)
loss = res.loss + res.aux_loss
loss = loss / args.accumulation_steps
scaler.scale(loss).backward()
if (step + 1) % args.accumulation_steps == 0:
scaler.unscale_(optimizer)
torch.nn.utils.clip_grad_norm_(model.parameters(), args.grad_clip)
scaler.step(optimizer)
scaler.update()
optimizer.zero_grad(set_to_none=True)
if step % args.log_interval == 0 or step == iters - 1:
spend_time = time.time() - start_time
current_loss = loss.item() * args.accumulation_steps
current_aux_loss = res.aux_loss.item() if res.aux_loss is not None else 0.0
current_logits_loss = current_loss - current_aux_loss
current_lr = optimizer.param_groups[-1]['lr']
eta_min = spend_time / (step + 1) * iters // 60 - spend_time // 60
Logger(f'Epoch:[{epoch + 1}/{args.epochs}]({step}/{iters}), loss: {current_loss:.4f}, logits_loss: {current_logits_loss:.4f}, aux_loss: {current_aux_loss:.4f}, lr: {current_lr:.8f}, epoch_time: {eta_min:.1f}min')
if wandb: wandb.log({"loss": current_loss, "logits_loss": current_logits_loss, "aux_loss": current_aux_loss, "learning_rate": current_lr, "epoch_time": eta_min})
if (step % args.save_interval == 0 or step == iters - 1) and is_main_process():
model.eval()
moe_suffix = '_moe' if lm_config.use_moe else ''
ckp = f'{args.save_dir}/{args.save_weight}_{lm_config.hidden_size}{moe_suffix}.pth'
raw_model = model.module if isinstance(model, DistributedDataParallel) else model
raw_model = getattr(raw_model, '_orig_mod', raw_model)
state_dict = raw_model.state_dict()
torch.save({k: v.half().cpu() for k, v in state_dict.items()}, ckp)
lm_checkpoint(lm_config, weight=args.save_weight, model=model, optimizer=optimizer,
epoch=epoch, step=step, wandb=wandb, save_dir='../checkpoints', scaler=scaler)
model.train()
del state_dict
del input_ids, labels, res, loss
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="MiniMind Full SFT")
parser.add_argument("--save_dir", type=str, default="../out", help="模型保存目录")
parser.add_argument('--save_weight', default='full_sft', type=str, help="保存权重的前缀名")
parser.add_argument("--epochs", type=int, default=2, help="训练轮数")
parser.add_argument("--batch_size", type=int, default=16, help="batch size")
parser.add_argument("--learning_rate", type=float, default=1e-6, help="初始学习率")
parser.add_argument("--device", type=str, default="cuda:0" if torch.cuda.is_available() else "cpu", help="训练设备")
parser.add_argument("--dtype", type=str, default="bfloat16", help="混合精度类型")
parser.add_argument("--num_workers", type=int, default=8, help="数据加载线程数")
parser.add_argument("--accumulation_steps", type=int, default=1, help="梯度累积步数")
parser.add_argument("--grad_clip", type=float, default=1.0, help="梯度裁剪阈值")
parser.add_argument("--log_interval", type=int, default=100, help="日志打印间隔")
parser.add_argument("--save_interval", type=int, default=1000, help="模型保存间隔")
parser.add_argument('--hidden_size', default=512, type=int, help="隐藏层维度")
parser.add_argument('--num_hidden_layers', default=8, type=int, help="隐藏层数量")
parser.add_argument('--max_seq_len', default=340, type=int, help="训练的最大截断长度(中文1token≈1.5~1.7字符)")
parser.add_argument('--use_moe', default=0, type=int, choices=[0, 1], help="是否使用MoE架构(0=否,1=是)")
parser.add_argument("--data_path", type=str, default="../dataset/sft_mini_512.jsonl", help="训练数据路径")
parser.add_argument('--from_weight', default='pretrain', type=str, help="基于哪个权重训练,为none则不基于任何权重训练")
parser.add_argument('--from_resume', default=0, type=int, choices=[0, 1], help="是否自动检测&续训(0=否,1=是)")
parser.add_argument("--use_wandb", action="store_true", help="是否使用wandb")
parser.add_argument("--wandb_project", type=str, default="MiniMind-Full-SFT", help="wandb项目名")
parser.add_argument("--use_compile", default=0, type=int, choices=[0, 1], help="是否使用torch.compile加速(0=否,1=是)")
args = parser.parse_args()
# ========== 1. 初始化环境和随机种子 ==========
local_rank = init_distributed_mode()
if dist.is_initialized(): args.device = f"cuda:{local_rank}"
setup_seed(42 + (dist.get_rank() if dist.is_initialized() else 0))
# ========== 2. 配置目录、模型参数、检查ckp ==========
os.makedirs(args.save_dir, exist_ok=True)
lm_config = MiniMindConfig(hidden_size=args.hidden_size, num_hidden_layers=args.num_hidden_layers, use_moe=bool(args.use_moe))
ckp_data = lm_checkpoint(lm_config, weight=args.save_weight, save_dir='../checkpoints') if args.from_resume==1 else None
# ========== 3. 设置混合精度 ==========
device_type = "cuda" if "cuda" in args.device else "cpu"
dtype = torch.bfloat16 if args.dtype == "bfloat16" else torch.float16
autocast_ctx = nullcontext() if device_type == "cpu" else torch.cuda.amp.autocast(dtype=dtype)
# ========== 4. 配wandb ==========
wandb = None
if args.use_wandb and is_main_process():
import swanlab as wandb
wandb_id = ckp_data.get('wandb_id') if ckp_data else None
resume = 'must' if wandb_id else None
wandb_run_name = f"MiniMind-Full-SFT-Epoch-{args.epochs}-BatchSize-{args.batch_size}-LearningRate-{args.learning_rate}"
wandb.init(project=args.wandb_project, name=wandb_run_name, id=wandb_id, resume=resume)
# ========== 5. 定义模型、数据、优化器 ==========
model, tokenizer = init_model(lm_config, args.from_weight, device=args.device)
if args.use_compile == 1:
model = torch.compile(model)
Logger('torch.compile enabled')
train_ds = SFTDataset(args.data_path, tokenizer, max_length=args.max_seq_len)
train_sampler = DistributedSampler(train_ds) if dist.is_initialized() else None
scaler = torch.cuda.amp.GradScaler(enabled=(args.dtype == 'float16'))
optimizer = optim.AdamW(model.parameters(), lr=args.learning_rate)
# ========== 6. 从ckp恢复状态 ==========
start_epoch, start_step = 0, 0
if ckp_data:
model.load_state_dict(ckp_data['model'])
optimizer.load_state_dict(ckp_data['optimizer'])
scaler.load_state_dict(ckp_data['scaler'])
start_epoch = ckp_data['epoch']
start_step = ckp_data.get('step', 0)
# ========== 7. DDP包模型 ==========
if dist.is_initialized():
model._ddp_params_and_buffers_to_ignore = {"freqs_cos", "freqs_sin"}
model = DistributedDataParallel(model, device_ids=[local_rank])
# ========== 8. 开始训练 ==========
for epoch in range(start_epoch, args.epochs):
train_sampler and train_sampler.set_epoch(epoch)
setup_seed(42 + epoch); indices = torch.randperm(len(train_ds)).tolist()
skip = start_step if (epoch == start_epoch and start_step > 0) else 0
batch_sampler = SkipBatchSampler(train_sampler or indices, args.batch_size, skip)
loader = DataLoader(train_ds, batch_sampler=batch_sampler, num_workers=args.num_workers, pin_memory=True)
if skip > 0:
Logger(f'Epoch [{epoch + 1}/{args.epochs}]: 跳过前{start_step}个step,从step {start_step + 1}开始')
train_epoch(epoch, loader, len(loader) + skip, start_step, wandb)
else:
train_epoch(epoch, loader, len(loader), 0, wandb)
# ========== 9. 清理分布进程 ==========
if dist.is_initialized(): dist.destroy_process_group()
================================================
FILE: trainer/train_grpo.py
================================================
import os
import sys
__package__ = "trainer"
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
import argparse
import re
import gc
import warnings
import torch
import torch.distributed as dist
from transformers import AutoTokenizer
from contextlib import nullcontext
from torch import optim
from torch.nn.parallel import DistributedDataParallel
from torch.utils.data import DataLoader, DistributedSampler
from torch.optim.lr_scheduler import CosineAnnealingLR
from transformers import AutoModel
from model.model_minimind import MiniMindConfig, MiniMindForCausalLM
from dataset.lm_dataset import RLAIFDataset
from trainer.trainer_utils import Logger, is_main_process, lm_checkpoint, init_distributed_mode, setup_seed, SkipBatchSampler, init_model
warnings.filterwarnings('ignore')
def calculate_rewards(prompts, responses, reward_model, reward_tokenizer):
"""整合所有奖励函数计算总奖励"""
def reasoning_model_reward(rewards):
pattern = r"^\n.*?\n \n\n.*?\n $"
pattern2 = r"^\n.*?\n \n\n\n.*?\n $"
matches_pattern = [re.match(pattern, response, re.S) for response in responses]
matches_pattern2 = [re.match(pattern2, response, re.S) for response in responses]
format_rewards = []
for match_pattern, match_pattern2 in zip(matches_pattern, matches_pattern2):
if match_pattern or match_pattern2:
format_rewards.append(0.5)
else:
format_rewards.append(0.0)
rewards += torch.tensor(format_rewards, device=args.device)
def mark_num(text):
reward = 0
if text.count("") == 1: reward += 0.25
if text.count(" ") == 1: reward += 0.25
if text.count("") == 1: reward += 0.25
if text.count(" ") == 1: reward += 0.25
return reward
mark_rewards = [mark_num(response) for response in responses]
rewards += torch.tensor(mark_rewards, device=args.device)
return rewards
rewards = torch.zeros(len(responses), device=args.device)
if args.reasoning == 1:
rewards = reasoning_model_reward(rewards)
with torch.no_grad():
reward_model_scores = []
batch_size = len(prompts)
scale = 3.0
for i in range(batch_size):
for j in range(args.num_generations):
response_idx = i * args.num_generations + j
response = responses[response_idx]
prompt = prompts[i]
pattern = r"<\|im_start\|>(system|user|assistant)\s+(.*?)<\|im_end\|>"
matches = re.findall(pattern, prompt, re.DOTALL)
messages = [{"role": role, "content": content.strip()} for role, content in matches]
tmp_chat = messages + [{"role": "assistant", "content": response}]
score = reward_model.get_score(reward_tokenizer, tmp_chat)
score = max(min(score, scale), -scale)
if args.reasoning == 1:
answer_match = re.search(r'(.*?) ', response, re.DOTALL)
if answer_match:
answer_content = answer_match.group(1).strip()
tmp_chat = messages + [{"role": "assistant", "content": answer_content}]
answer_score = reward_model.get_score(reward_tokenizer, tmp_chat)
answer_score = max(min(answer_score, scale), -scale)
score = score * 0.4 + answer_score * 0.6
reward_model_scores.append(score)
reward_model_scores = torch.tensor(reward_model_scores, device=args.device)
rewards += reward_model_scores
return rewards
def grpo_train_epoch(epoch, loader, iters, ref_model, reward_model, reward_tokenizer, start_step=0, wandb=None):
for step, batch in enumerate(loader, start=start_step + 1):
prompts = batch['prompt'] # list[str], length B
prompt_inputs = tokenizer(prompts, return_tensors="pt", padding=True, return_token_type_ids=False,
padding_side="left", add_special_tokens=False).to(args.device) # input_ids: [B, P], attention_mask: [B, P]
if args.max_seq_len:
prompt_inputs["input_ids"] = prompt_inputs["input_ids"][:, -args.max_seq_len:]
prompt_inputs["attention_mask"] = prompt_inputs["attention_mask"][:, -args.max_seq_len:]
with torch.no_grad():
# DDP 模型需要使用 .module 访问 generate 方法
model_for_gen = model.module if isinstance(model, DistributedDataParallel) else model
outputs = model_for_gen.generate(
**prompt_inputs, max_new_tokens=args.max_gen_len, do_sample=True, temperature=0.8,
num_return_sequences=args.num_generations, pad_token_id=tokenizer.pad_token_id) # [B*num_gen, P+R]
completion_ids = outputs[:, prompt_inputs["input_ids"].size(1):] # [B*num_gen, R]
def get_per_token_logps(mdl, input_ids, n_keep):
input_ids = input_ids.detach().clone() if input_ids.is_inference() else input_ids
logits = mdl(input_ids, logits_to_keep=n_keep + 1).logits[:, :-1, :]
per_token_logps = []
for logits_row, ids_row in zip(logits, input_ids[:, -n_keep:]):
ids_row = ids_row.detach().clone() if ids_row.is_inference() else ids_row
per_token_logps.append(torch.gather(logits_row.log_softmax(dim=-1), 1, ids_row.unsqueeze(1)).squeeze(1))
return torch.stack(per_token_logps)
with autocast_ctx:
per_token_logps = get_per_token_logps(model, outputs, completion_ids.size(1)) # [B*num_gen, R]
res = model(outputs) if lm_config.use_moe else None
aux_loss = res.aux_loss if res is not None else torch.tensor(0.0, device=args.device)
with torch.no_grad():
ref_per_token_logps = get_per_token_logps(ref_model, outputs, completion_ids.size(1)) # [B*num_gen, R]
completions = tokenizer.batch_decode(completion_ids, skip_special_tokens=True)
rewards = calculate_rewards(prompts, completions, reward_model, reward_tokenizer).to(args.device) # [B*num_gen]
grouped_rewards = rewards.view(-1, args.num_generations) # [B, num_gen]
mean_r = grouped_rewards.mean(dim=1).repeat_interleave(args.num_generations) # [B*num_gen]
std_r = grouped_rewards.std(dim=1).repeat_interleave(args.num_generations) # [B*num_gen]
advantages = torch.clamp((rewards - mean_r) / (std_r + 1e-4), -10, 10)
advantages = (advantages - advantages.mean()) / (advantages.std() + 1e-8) # [B*num_gen]
is_eos = completion_ids == tokenizer.eos_token_id # [B*num_gen, R]
eos_idx = torch.full((is_eos.size(0),), is_eos.size(1), dtype=torch.long, device=args.device)
eos_idx[is_eos.any(dim=1)] = is_eos.int().argmax(dim=1)[is_eos.any(dim=1)]
completion_mask = (torch.arange(is_eos.size(1), device=args.device).expand(is_eos.size(0), -1) <= eos_idx.unsqueeze(1)).int() # [B*num_gen, R]
kl_div = ref_per_token_logps - per_token_logps
per_token_kl = torch.exp(kl_div) - kl_div - 1 # [B*num_gen, R]
per_token_loss = -(torch.exp(per_token_logps - per_token_logps.detach()) * advantages.unsqueeze(1) - args.beta * per_token_kl) # [B*num_gen, R]
policy_loss = ((per_token_loss * completion_mask).sum(dim=1) / completion_mask.sum(dim=1)).mean()
loss = (policy_loss + aux_loss) / args.accumulation_steps # scalar
loss.backward()
if (step + 1) % args.accumulation_steps == 0:
if args.grad_clip > 0:
torch.nn.utils.clip_grad_norm_(model.parameters(), args.grad_clip)
optimizer.step()
scheduler.step()
optimizer.zero_grad()
if step % args.log_interval == 0 or step == iters:
policy_loss_val = loss.item() * args.accumulation_steps
current_aux_loss = aux_loss.item()
avg_reward_val = rewards.mean().item()
avg_len_val = completion_mask.sum(dim=1).float().mean().item()
current_lr = optimizer.param_groups[0]['lr']
Logger(f'Epoch:[{epoch + 1}/{args.epochs}]({step}/{iters}), '
f'Actor Loss: {policy_loss_val:.4f}, Aux Loss: {current_aux_loss:.4f}, Reward: {avg_reward_val:.4f}, '
f'Avg Response Len: {avg_len_val:.2f}, Learning Rate: {current_lr:.8f}')
if wandb and is_main_process():
wandb.log({
"policy_loss": policy_loss_val,
"aux_loss": current_aux_loss,
"reward": avg_reward_val,
"avg_response_len": avg_len_val,
"advantages_mean": advantages.mean().item(),
"learning_rate": current_lr
})
if (step % args.save_interval == 0 or step == iters - 1) and is_main_process():
model.eval()
moe_suffix = '_moe' if lm_config.use_moe else ''
ckp = f'{args.save_dir}/{args.save_weight}_{lm_config.hidden_size}{moe_suffix}.pth'
raw_model = model.module if isinstance(model, DistributedDataParallel) else model
raw_model = getattr(raw_model, '_orig_mod', raw_model)
state_dict = raw_model.state_dict()
torch.save({k: v.half().cpu() for k, v in state_dict.items()}, ckp)
lm_checkpoint(lm_config, weight=args.save_weight, model=model, optimizer=optimizer,
epoch=epoch, step=step, wandb=wandb, save_dir='../checkpoints', scheduler=scheduler)
model.train()
del state_dict
del prompt_inputs, outputs, completion_ids, per_token_logps, ref_per_token_logps
del completions, rewards, grouped_rewards, mean_r, std_r, advantages, completion_mask
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="MiniMind GRPO (Group Relative Policy Optimization)")
parser.add_argument("--save_dir", type=str, default="../out", help="模型保存目录")
parser.add_argument('--save_weight', default='grpo', type=str, help="保存权重的前缀名")
parser.add_argument("--epochs", type=int, default=1, help="训练轮数")
parser.add_argument("--batch_size", type=int, default=2, help="batch size")
parser.add_argument("--learning_rate", type=float, default=8e-8, help="初始学习率")
parser.add_argument("--device", type=str, default="cuda:0" if torch.cuda.is_available() else "cpu", help="训练设备")
parser.add_argument("--dtype", type=str, default="bfloat16", help="混合精度类型")
parser.add_argument("--num_workers", type=int, default=8, help="数据加载线程数")
parser.add_argument("--accumulation_steps", type=int, default=1, help="梯度累积步数")
parser.add_argument("--grad_clip", type=float, default=1.0, help="梯度裁剪阈值")
parser.add_argument("--log_interval", type=int, default=1, help="日志打印间隔")
parser.add_argument("--save_interval", type=int, default=10, help="模型保存间隔")
parser.add_argument('--hidden_size', default=512, type=int, help="隐藏层维度")
parser.add_argument('--num_hidden_layers', default=8, type=int, help="隐藏层数量")
parser.add_argument('--use_moe', default=0, type=int, choices=[0, 1], help="是否使用MoE架构(0=否,1=是)")
parser.add_argument('--max_seq_len', default=66, type=int, help="Prompt最大长度")
parser.add_argument("--max_gen_len", type=int, default=1536, help="生成的最大长度")
parser.add_argument("--data_path", type=str, default="../dataset/rlaif-mini.jsonl", help="RLAIF数据路径")
parser.add_argument("--num_generations", type=int, default=8, help="每个prompt生成的样本数")
parser.add_argument("--beta", type=float, default=0.02, help="KL惩罚系数")
parser.add_argument("--reasoning", type=int, default=1, choices=[0, 1], help='推理模型类型(0=普通模型,1=推理模型)')
parser.add_argument("--reward_model_path", type=str, default="../../internlm2-1_8b-reward", help="Reward模型路径")
parser.add_argument('--from_resume', default=0, type=int, choices=[0, 1], help="是否自动检测&续训(0=否,1=是)")
parser.add_argument("--use_wandb", action="store_true", help="是否使用wandb")
parser.add_argument("--wandb_project", type=str, default="MiniMind-GRPO", help="wandb项目名")
parser.add_argument("--use_compile", default=0, type=int, choices=[0, 1], help="是否使用torch.compile加速(0=否,1=是)")
args = parser.parse_args()
# ========== 1. 初始化环境和随机种子 ==========
local_rank = init_distributed_mode()
if dist.is_initialized(): args.device = f"cuda:{local_rank}"
setup_seed(42 + (dist.get_rank() if dist.is_initialized() else 0))
# ========== 2. 配置目录、模型参数、检查ckp ==========
os.makedirs(args.save_dir, exist_ok=True)
lm_config = MiniMindConfig(hidden_size=args.hidden_size, num_hidden_layers=args.num_hidden_layers,
max_seq_len=args.max_seq_len + args.max_gen_len, use_moe=bool(args.use_moe))
ckp_data = lm_checkpoint(lm_config, weight=args.save_weight, save_dir='../checkpoints') if args.from_resume==1 else None
# ========== 3. 设置混合精度 ==========
device_type = "cuda" if "cuda" in args.device else "cpu"
dtype = torch.bfloat16 if args.dtype == "bfloat16" else torch.float16
autocast_ctx = nullcontext() if device_type == "cpu" else torch.cuda.amp.autocast(dtype=dtype)
# ========== 4. 配wandb ==========
wandb = None
if args.use_wandb and is_main_process():
import swanlab as wandb
wandb_id = ckp_data.get('wandb_id') if ckp_data else None
resume = 'must' if wandb_id else None
wandb_run_name = f"MiniMind-GRPO-Epoch-{args.epochs}-BS-{args.batch_size}-LR-{args.learning_rate}"
wandb.init(project=args.wandb_project, name=wandb_run_name, id=wandb_id, resume=resume)
# ========== 5. 初始化模型和数据 ==========
base_weight = "reason" if args.reasoning == 1 else "full_sft"
# Policy模型
model, tokenizer = init_model(lm_config, base_weight, device=args.device)
if args.use_compile == 1:
model = torch.compile(model)
Logger('torch.compile enabled')
# Reference模型
ref_model, _ = init_model(lm_config, base_weight, device=args.device)
ref_model = ref_model.eval().requires_grad_(False)
# Reward模型
reward_model = AutoModel.from_pretrained(
args.reward_model_path, torch_dtype=torch.float16, trust_remote_code=True
)
reward_model = reward_model.to(args.device).eval().requires_grad_(False)
reward_tokenizer = AutoTokenizer.from_pretrained(args.reward_model_path, trust_remote_code=True)
# 数据和优化器
train_ds = RLAIFDataset(args.data_path, tokenizer, max_length=lm_config.max_seq_len)
train_sampler = DistributedSampler(train_ds) if dist.is_initialized() else None
optimizer = optim.AdamW(model.parameters(), lr=args.learning_rate)
loader_for_count = DataLoader(train_ds, batch_size=args.batch_size, sampler=train_sampler)
iters = len(loader_for_count)
total_optimizer_steps = (iters // args.accumulation_steps) * args.epochs
scheduler = CosineAnnealingLR(optimizer, T_max=total_optimizer_steps, eta_min=args.learning_rate / 10)
# ========== 6. 从ckp恢复状态 ==========
start_epoch, start_step = 0, 0
if ckp_data:
model.load_state_dict(ckp_data['model'])
optimizer.load_state_dict(ckp_data['optimizer'])
scheduler.load_state_dict(ckp_data['scheduler'])
start_epoch = ckp_data['epoch']
start_step = ckp_data.get('step', 0)
# ========== 7. DDP包模型 ==========
if dist.is_initialized():
model._ddp_params_and_buffers_to_ignore = {"freqs_cos", "freqs_sin"}
model = DistributedDataParallel(model, device_ids=[local_rank])
# ========== 8. 开始训练 ==========
for epoch in range(start_epoch, args.epochs):
train_sampler and train_sampler.set_epoch(epoch)
setup_seed(42 + epoch); indices = torch.randperm(len(train_ds)).tolist()
skip = start_step if (epoch == start_epoch and start_step > 0) else 0
batch_sampler = SkipBatchSampler(train_sampler or indices, args.batch_size, skip)
loader = DataLoader(train_ds, batch_sampler=batch_sampler, num_workers=args.num_workers, pin_memory=True)
if skip > 0:
Logger(f'Epoch [{epoch + 1}/{args.epochs}]: 跳过前{start_step}个step,从step {start_step + 1}开始')
grpo_train_epoch(epoch, loader, len(loader) + skip, ref_model, reward_model, reward_tokenizer, start_step, wandb)
else:
grpo_train_epoch(epoch, loader, len(loader), ref_model, reward_model, reward_tokenizer, 0, wandb)
# ========== 9. 清理分布进程 ==========
if dist.is_initialized(): dist.destroy_process_group()
================================================
FILE: trainer/train_lora.py
================================================
import os
import sys
__package__ = "trainer"
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
import argparse
import time
import warnings
import torch
import torch.distributed as dist
from contextlib import nullcontext
from torch import optim, nn
from torch.nn.parallel import DistributedDataParallel
from torch.utils.data import DataLoader, DistributedSampler
from model.model_minimind import MiniMindConfig
from dataset.lm_dataset import SFTDataset
from model.model_lora import save_lora, apply_lora
from trainer.trainer_utils import get_lr, Logger, is_main_process, lm_checkpoint, init_distributed_mode, setup_seed, init_model, SkipBatchSampler
warnings.filterwarnings('ignore')
def train_epoch(epoch, loader, iters, lora_params, start_step=0, wandb=None):
start_time = time.time()
for step, (input_ids, labels) in enumerate(loader, start=start_step + 1):
input_ids = input_ids.to(args.device)
labels = labels.to(args.device)
lr = get_lr(epoch * iters + step, args.epochs * iters, args.learning_rate)
for param_group in optimizer.param_groups:
param_group['lr'] = lr
with autocast_ctx:
res = model(input_ids, labels=labels)
loss = res.loss + res.aux_loss
loss = loss / args.accumulation_steps
scaler.scale(loss).backward()
if (step + 1) % args.accumulation_steps == 0:
scaler.unscale_(optimizer)
torch.nn.utils.clip_grad_norm_(lora_params, args.grad_clip)
scaler.step(optimizer)
scaler.update()
optimizer.zero_grad(set_to_none=True)
if step % args.log_interval == 0 or step == iters - 1:
spend_time = time.time() - start_time
current_loss = loss.item() * args.accumulation_steps
current_aux_loss = res.aux_loss.item() if res.aux_loss is not None else 0.0
current_logits_loss = current_loss - current_aux_loss
current_lr = optimizer.param_groups[-1]['lr']
eta_min = spend_time / (step + 1) * iters // 60 - spend_time // 60
Logger(f'Epoch:[{epoch + 1}/{args.epochs}]({step}/{iters}), loss: {current_loss:.4f}, logits_loss: {current_logits_loss:.4f}, aux_loss: {current_aux_loss:.4f}, lr: {current_lr:.8f}, epoch_time: {eta_min:.1f}min')
if wandb: wandb.log({"loss": current_loss, "logits_loss": current_logits_loss, "aux_loss": current_aux_loss, "learning_rate": current_lr, "epoch_time": eta_min})
if (step % args.save_interval == 0 or step == iters - 1) and is_main_process():
model.eval()
lora_save_path = f'{args.save_dir}/{args.lora_name}_{lm_config.hidden_size}.pth'
# LoRA只保存LoRA权重
save_lora(model, lora_save_path)
lm_checkpoint(lm_config, weight=args.lora_name, model=model, optimizer=optimizer, scaler=scaler, epoch=epoch, step=step, wandb=wandb, save_dir='../checkpoints')
model.train()
del input_ids, labels, res, loss
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="MiniMind LoRA Fine-tuning")
parser.add_argument("--save_dir", type=str, default="../out/lora", help="模型保存目录")
parser.add_argument("--lora_name", type=str, default="lora_identity", help="LoRA权重名称(如lora_identity/lora_medical等)")
parser.add_argument("--epochs", type=int, default=50, help="训练轮数")
parser.add_argument("--batch_size", type=int, default=32, help="batch size")
parser.add_argument("--learning_rate", type=float, default=1e-4, help="初始学习率")
parser.add_argument("--device", type=str, default="cuda:0" if torch.cuda.is_available() else "cpu", help="训练设备")
parser.add_argument("--dtype", type=str, default="bfloat16", help="混合精度类型")
parser.add_argument("--num_workers", type=int, default=8, help="数据加载线程数")
parser.add_argument("--accumulation_steps", type=int, default=1, help="梯度累积步数")
parser.add_argument("--grad_clip", type=float, default=1.0, help="梯度裁剪阈值")
parser.add_argument("--log_interval", type=int, default=10, help="日志打印间隔")
parser.add_argument("--save_interval", type=int, default=1000, help="模型保存间隔")
parser.add_argument('--hidden_size', default=512, type=int, help="隐藏层维度")
parser.add_argument('--num_hidden_layers', default=8, type=int, help="隐藏层数量")
parser.add_argument('--max_seq_len', default=340, type=int, help="训练的最大截断长度(中文1token≈1.5~1.7字符)")
parser.add_argument('--use_moe', default=0, type=int, choices=[0, 1], help="是否使用MoE架构(0=否,1=是)")
parser.add_argument("--data_path", type=str, default="../dataset/lora_identity.jsonl", help="LoRA训练数据路径")
parser.add_argument('--from_weight', default='full_sft', type=str, help="基于哪个权重训练,默认full_sft")
parser.add_argument('--from_resume', default=0, type=int, choices=[0, 1], help="是否自动检测&续训(0=否,1=是)")
parser.add_argument("--use_wandb", action="store_true", help="是否使用wandb")
parser.add_argument("--wandb_project", type=str, default="MiniMind-LoRA", help="wandb项目名")
parser.add_argument("--use_compile", default=0, type=int, choices=[0, 1], help="是否使用torch.compile加速(0=否,1=是)")
args = parser.parse_args()
# ========== 1. 初始化环境和随机种子 ==========
local_rank = init_distributed_mode()
if dist.is_initialized(): args.device = f"cuda:{local_rank}"
setup_seed(42 + (dist.get_rank() if dist.is_initialized() else 0))
# ========== 2. 配置目录、模型参数、检查ckp ==========
os.makedirs(args.save_dir, exist_ok=True)
lm_config = MiniMindConfig(hidden_size=args.hidden_size, num_hidden_layers=args.num_hidden_layers, use_moe=bool(args.use_moe))
ckp_data = lm_checkpoint(lm_config, weight=args.lora_name, save_dir='../checkpoints') if args.from_resume==1 else None
# ========== 3. 设置混合精度 ==========
device_type = "cuda" if "cuda" in args.device else "cpu"
dtype = torch.bfloat16 if args.dtype == "bfloat16" else torch.float16
autocast_ctx = nullcontext() if device_type == "cpu" else torch.cuda.amp.autocast(dtype=dtype)
# ========== 4. 配wandb ==========
wandb = None
if args.use_wandb and is_main_process():
import swanlab as wandb
wandb_id = ckp_data.get('wandb_id') if ckp_data else None
resume = 'must' if wandb_id else None
wandb_run_name = f"MiniMind-LoRA-{args.lora_name}-Epoch-{args.epochs}-BatchSize-{args.batch_size}-LR-{args.learning_rate}"
wandb.init(project=args.wandb_project, name=wandb_run_name, id=wandb_id, resume=resume)
# ========== 5. 定义模型、应用LoRA、冻结非LoRA参数 ==========
model, tokenizer = init_model(lm_config, args.from_weight, device=args.device)
if args.use_compile == 1:
model = torch.compile(model)
Logger('torch.compile enabled')
apply_lora(model)
# 统计参数
total_params = sum(p.numel() for p in model.parameters())
lora_params_count = sum(p.numel() for name, p in model.named_parameters() if 'lora' in name)
Logger(f"LLM 总参数量: {total_params / 1e6:.3f} M")
Logger(f"LoRA 参数量: {lora_params_count / 1e6:.3f} M")
Logger(f"LoRA 参数占比: {lora_params_count / total_params * 100:.2f}%")
# 冻结非LoRA参数,收集LoRA参数
lora_params = []
for name, param in model.named_parameters():
if 'lora' in name:
param.requires_grad = True
lora_params.append(param)
else:
param.requires_grad = False
# ========== 6. 定义数据和优化器 ==========
train_ds = SFTDataset(args.data_path, tokenizer, max_length=args.max_seq_len)
train_sampler = DistributedSampler(train_ds) if dist.is_initialized() else None
scaler = torch.cuda.amp.GradScaler(enabled=(args.dtype == 'float16'))
optimizer = optim.AdamW(lora_params, lr=args.learning_rate)
# ========== 7. 从ckp恢复状态 ==========
start_epoch, start_step = 0, 0
if ckp_data:
model.load_state_dict(ckp_data['model'], strict=False)
optimizer.load_state_dict(ckp_data['optimizer'])
scaler.load_state_dict(ckp_data['scaler'])
start_epoch = ckp_data['epoch']
start_step = ckp_data.get('step', 0)
# ========== 8. DDP包模型 ==========
if dist.is_initialized():
model._ddp_params_and_buffers_to_ignore = {"freqs_cos", "freqs_sin"}
model = DistributedDataParallel(model, device_ids=[local_rank])
# ========== 9. 开始训练 ==========
for epoch in range(start_epoch, args.epochs):
train_sampler and train_sampler.set_epoch(epoch)
setup_seed(42 + epoch); indices = torch.randperm(len(train_ds)).tolist()
skip = start_step if (epoch == start_epoch and start_step > 0) else 0
batch_sampler = SkipBatchSampler(train_sampler or indices, args.batch_size, skip)
loader = DataLoader(train_ds, batch_sampler=batch_sampler, num_workers=args.num_workers, pin_memory=True)
if skip > 0:
Logger(f'Epoch [{epoch + 1}/{args.epochs}]: 跳过前{start_step}个step,从step {start_step + 1}开始')
train_epoch(epoch, loader, len(loader) + skip, lora_params, start_step, wandb)
else:
train_epoch(epoch, loader, len(loader), lora_params, 0, wandb)
# ========== 10. 清理分布进程 ==========
if dist.is_initialized(): dist.destroy_process_group()
================================================
FILE: trainer/train_ppo.py
================================================
import os
import sys
__package__ = "trainer"
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
import argparse
import re
import warnings
import torch
import torch.distributed as dist
import torch.nn.functional as F
from transformers import AutoTokenizer
from contextlib import nullcontext
from torch import optim, nn
from torch.nn.parallel import DistributedDataParallel
from torch.utils.data import DataLoader, DistributedSampler
from torch.nn.utils import clip_grad_norm_
from torch.optim.lr_scheduler import CosineAnnealingLR
from transformers import AutoModel
from model.model_minimind import MiniMindConfig, MiniMindForCausalLM
from dataset.lm_dataset import RLAIFDataset
from trainer.trainer_utils import Logger, is_main_process, lm_checkpoint, init_distributed_mode, setup_seed, SkipBatchSampler, init_model
warnings.filterwarnings('ignore')
# 自定义的Critic模型,继承自MiniMindLM
class CriticModel(MiniMindForCausalLM):
def __init__(self, params):
super().__init__(params)
# 替换lm_head为输出单一价值的线性层
self.value_head = nn.Linear(params.hidden_size, 1)
def forward(self, input_ids=None, attention_mask=None, **kwargs):
# 使用基础模型获取隐藏状态
outputs = self.model(input_ids=input_ids, attention_mask=attention_mask, **kwargs)
hidden_states = self.model.norm(outputs[0])
# 使用value_head获取价值估计
values = self.value_head(hidden_states).squeeze(-1)
return values
def calculate_rewards(prompts, responses, reward_model, reward_tokenizer):
"""整合所有奖励函数计算总奖励"""
def reasoning_model_reward(rewards):
# 1. 格式奖励(仅针对训练推理模型时使用)
pattern = r"^\n.*?\n \n\n.*?\n $"
pattern2 = r"^\n.*?\n \n\n\n.*?\n $"
matches_pattern = [re.match(pattern, response, re.S) for response in responses]
matches_pattern2 = [re.match(pattern2, response, re.S) for response in responses]
format_rewards = []
for match_pattern, match_pattern2 in zip(matches_pattern, matches_pattern2):
if match_pattern:
format_rewards.append(0.5)
elif match_pattern2:
format_rewards.append(0.5)
else:
format_rewards.append(0.0)
rewards += torch.tensor(format_rewards, device=args.device)
# 2. 标记奖励(防止严格奖励稀疏,仅针对训练推理模型时使用)
def mark_num(text):
reward = 0
if text.count("") == 1:
reward += 0.25
if text.count(" ") == 1:
reward += 0.25
if text.count("") == 1:
reward += 0.25
if text.count(" ") == 1:
reward += 0.25
return reward
mark_rewards = [mark_num(response) for response in responses]
rewards += torch.tensor(mark_rewards, device=args.device)
return rewards
rewards = torch.zeros(len(responses), device=args.device)
# 格式奖励
if args.reasoning == 1:
rewards = reasoning_model_reward(rewards)
# 使用reward model计算整个response的奖励
with torch.no_grad():
reward_model_scores = []
for prompt, response in zip(prompts, responses):
pattern = r"<\|im_start\|>(system|user|assistant)\s+(.*?)<\|im_end\|>"
matches = re.findall(pattern, prompt, re.DOTALL)
messages = [{"role": role, "content": content.strip()} for role, content in matches]
tmp_chat = messages + [{"role": "assistant", "content": response}]
score = reward_model.get_score(reward_tokenizer, tmp_chat)
scale = 3.0
score = max(min(score, scale), -scale)
# 当args.reasoning=1时,额外计算内容的奖励
if args.reasoning == 1:
answer_match = re.search(r'(.*?) ', response, re.DOTALL)
if answer_match:
answer_content = answer_match.group(1).strip()
# 对answer内容单独计算reward
tmp_chat = messages + [{"role": "assistant", "content": answer_content}]
answer_score = reward_model.get_score(reward_tokenizer, tmp_chat)
answer_score = max(min(answer_score, scale), -scale)
score = score * 0.4 + answer_score * 0.6
reward_model_scores.append(score)
reward_model_scores = torch.tensor(reward_model_scores, device=args.device)
rewards += reward_model_scores
return rewards
def ppo_train_epoch(epoch, loader, iters, old_actor_model, ref_model, actor_scheduler, critic_scheduler, reward_model, reward_tokenizer, start_step=0, wandb=None):
actor_model.train()
critic_model.train()
for step, batch in enumerate(loader, start=start_step + 1):
prompts = batch["prompt"] # list[str], length B
enc = tokenizer(prompts, return_tensors="pt", padding=True, truncation=True,
max_length=args.max_seq_len, padding_side="left").to(args.device) # input_ids: [B, P], attention_mask: [B, P]
prompt_length = enc.input_ids.shape[1]
with torch.no_grad():
# DDP 模型需要使用 .module 访问 generate 方法
model_for_gen = actor_model.module if isinstance(actor_model, DistributedDataParallel) else actor_model
gen_out = model_for_gen.generate(
input_ids=enc.input_ids, attention_mask=enc.attention_mask,
max_new_tokens=args.max_gen_len, do_sample=True, temperature=0.8,
pad_token_id=tokenizer.pad_token_id, eos_token_id=tokenizer.eos_token_id) # [B, P+R]
responses_text = [tokenizer.decode(gen_out[i, prompt_length:], skip_special_tokens=True) for i in range(len(prompts))]
rewards = calculate_rewards(prompts, responses_text, reward_model, reward_tokenizer) # [B]
full_mask = (gen_out != tokenizer.pad_token_id).long() # [B, P+R]
values_seq = critic_model(input_ids=gen_out, attention_mask=full_mask) # [B, P+R]
last_indices = (full_mask * torch.arange(full_mask.size(1), device=gen_out.device)).argmax(dim=1)
values = values_seq[torch.arange(values_seq.size(0), device=values_seq.device), last_indices] # [B]
advantages = rewards - values.detach() # [B]
with autocast_ctx:
res = actor_model(input_ids=gen_out, attention_mask=full_mask)
logits = res.logits # [B, P+R, V]
aux_loss = res.aux_loss if lm_config.use_moe else torch.tensor(0.0, device=args.device)
labels = gen_out[:, 1:].clone() # [B, P+R-1]
logp_tokens = F.log_softmax(logits[:, :-1], dim=-1).gather(2, labels.unsqueeze(-1)).squeeze(-1) # [B, P+R-1]
seq_len = gen_out.size(1) - 1
resp_mask = torch.arange(seq_len, device=gen_out.device).unsqueeze(0) >= prompt_length - 1
final_mask = resp_mask & (~labels.eq(tokenizer.pad_token_id)) # [B, P+R-1]
actor_logp = (logp_tokens * final_mask).sum(dim=1) # [B]
with torch.no_grad():
old_logits = old_actor_model(input_ids=gen_out, attention_mask=full_mask).logits # [B, P+R, V]
old_logp_tokens = F.log_softmax(old_logits[:, :-1], dim=-1).gather(2, labels.unsqueeze(-1)).squeeze(-1) # [B, P+R-1]
old_logp = (old_logp_tokens * final_mask).sum(dim=1) # [B]
ref_logits = ref_model(input_ids=gen_out, attention_mask=full_mask).logits # [B, P+R, V]
ref_logp_tokens = F.log_softmax(ref_logits[:, :-1], dim=-1).gather(2, labels.unsqueeze(-1)).squeeze(-1) # [B, P+R-1]
ref_logp = (ref_logp_tokens * final_mask).sum(dim=1) # [B]
kl = (actor_logp - old_logp).mean() # scalar
kl_ref = (actor_logp - ref_logp).mean() # scalar
ratio = torch.exp(actor_logp - old_logp) # [B]
surr1 = ratio * advantages # [B]
surr2 = torch.clamp(ratio, 1.0 - args.clip_epsilon, 1.0 + args.clip_epsilon) * advantages # [B]
policy_loss = -torch.min(surr1, surr2).mean() # scalar
value_loss = F.mse_loss(values, rewards) # scalar
loss = (policy_loss + args.vf_coef * value_loss + args.kl_coef * kl_ref + aux_loss) / args.accumulation_steps # scalar
loss.backward()
if (step + 1) % args.accumulation_steps == 0:
clip_grad_norm_(actor_model.parameters(), args.grad_clip)
clip_grad_norm_(critic_model.parameters(), args.grad_clip)
actor_optimizer.step()
critic_optimizer.step()
actor_scheduler.step()
critic_scheduler.step()
actor_optimizer.zero_grad()
critic_optimizer.zero_grad()
if is_main_process():
response_ids = gen_out[:, enc.input_ids.shape[1]:]
is_eos = (response_ids == tokenizer.eos_token_id)
eos_indices = torch.argmax(is_eos.int(), dim=1)
has_eos = is_eos.any(dim=1)
lengths = torch.where(has_eos, eos_indices + 1, torch.tensor(response_ids.shape[1], device=is_eos.device))
avg_len = lengths.float().mean()
actor_loss_val = policy_loss.item()
critic_loss_val = value_loss.item()
current_aux_loss = aux_loss.item()
reward_val = rewards.mean().item()
kl_val = kl.item()
kl_ref_val = kl_ref.item()
avg_len_val = avg_len.item()
actor_lr = actor_optimizer.param_groups[0]['lr']
critic_lr = critic_optimizer.param_groups[0]['lr']
if wandb is not None:
wandb.log({
"actor_loss": actor_loss_val,
"critic_loss": critic_loss_val,
"aux_loss": current_aux_loss,
"reward": reward_val,
"kl": kl_val,
"kl_ref": kl_ref_val,
"avg_response_len": avg_len_val,
"actor_lr": actor_lr,
})
Logger(f"Epoch:[{epoch + 1}/{args.epochs}]({step}/{iters}), "
f"Actor Loss: {actor_loss_val:.4f}, Critic Loss: {critic_loss_val:.4f}, Aux Loss: {current_aux_loss:.4f}, "
f"Reward: {reward_val:.4f}, KL: {kl_val:.4f}, KL_ref: {kl_ref_val:.4f}, "
f"Avg Response Len: {avg_len_val:.2f}, Actor LR: {actor_lr:.8f}, Critic LR: {critic_lr:.8f}")
if (step + 1) % args.update_old_actor_freq == 0:
raw_actor = actor_model.module if isinstance(actor_model, DistributedDataParallel) else actor_model
raw_actor = getattr(raw_actor, '_orig_mod', raw_actor)
state_dict = raw_actor.state_dict()
old_actor_model.load_state_dict({k: v.detach().cpu() for k, v in state_dict.items()})
old_actor_model.to(args.device)
if (step % args.save_interval == 0 or step == iters - 1) and is_main_process():
actor_model.eval()
moe_suffix = '_moe' if lm_config.use_moe else ''
ckp = f'{args.save_dir}/{args.save_weight}_{lm_config.hidden_size}{moe_suffix}.pth'
raw_actor = actor_model.module if isinstance(actor_model, DistributedDataParallel) else actor_model
raw_actor = getattr(raw_actor, '_orig_mod', raw_actor)
actor_state = raw_actor.state_dict()
torch.save({k: v.half().cpu() for k, v in actor_state.items()}, ckp)
# 使用 lm_checkpoint 保存完整状态(包括 critic)
lm_checkpoint(lm_config, weight=args.save_weight, model=actor_model, optimizer=actor_optimizer,
epoch=epoch, step=step, wandb=wandb, save_dir='../checkpoints',
scheduler=actor_scheduler, critic_model=critic_model,
critic_optimizer=critic_optimizer, critic_scheduler=critic_scheduler)
actor_model.train()
del actor_state
del enc, gen_out, responses_text, rewards, full_mask, values_seq, values, advantages
del logits, labels, logp_tokens, final_mask, actor_logp, old_logits, old_logp, ref_logits, ref_logp
del kl, kl_ref, ratio, surr1, surr2, policy_loss, value_loss, loss
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="MiniMind PPO (Proximal Policy Optimization)")
parser.add_argument("--save_dir", type=str, default="../out", help="模型保存目录")
parser.add_argument('--save_weight', default='ppo_actor', type=str, help="保存权重的前缀名")
parser.add_argument("--epochs", type=int, default=1, help="训练轮数")
parser.add_argument("--batch_size", type=int, default=2, help="batch size")
parser.add_argument("--learning_rate", type=float, default=8e-8, help="Actor学习率")
parser.add_argument("--critic_learning_rate", type=float, default=8e-8, help="Critic学习率")
parser.add_argument("--device", type=str, default="cuda:0" if torch.cuda.is_available() else "cpu", help="训练设备")
parser.add_argument("--dtype", type=str, default="bfloat16", help="混合精度类型")
parser.add_argument("--num_workers", type=int, default=8, help="数据加载线程数")
parser.add_argument("--accumulation_steps", type=int, default=1, help="梯度累积步数")
parser.add_argument("--grad_clip", type=float, default=1.0, help="梯度裁剪阈值")
parser.add_argument("--log_interval", type=int, default=1, help="日志打印间隔")
parser.add_argument("--save_interval", type=int, default=10, help="模型保存间隔")
parser.add_argument('--hidden_size', default=512, type=int, help="隐藏层维度")
parser.add_argument('--num_hidden_layers', default=8, type=int, help="隐藏层数量")
parser.add_argument('--use_moe', default=0, type=int, choices=[0, 1], help="是否使用MoE架构(0=否,1=是)")
parser.add_argument('--max_seq_len', default=66, type=int, help="Prompt最大长度")
parser.add_argument("--max_gen_len", type=int, default=1536, help="生成的最大长度")
parser.add_argument("--data_path", type=str, default="../dataset/rlaif-mini.jsonl", help="RLAIF数据路径")
parser.add_argument("--clip_epsilon", type=float, default=0.1, help="PPO裁剪参数")
parser.add_argument("--vf_coef", type=float, default=0.5, help="Value function系数")
parser.add_argument("--kl_coef", type=float, default=0.02, help="KL散度惩罚系数")
parser.add_argument("--reasoning", type=int, default=1, choices=[0, 1], help='推理模型类型(0=普通模型,1=推理模型)')
parser.add_argument("--update_old_actor_freq", type=int, default=4, help="更新old_actor_model的频率")
parser.add_argument("--reward_model_path", type=str, default="../../internlm2-1_8b-reward", help="Reward模型路径")
parser.add_argument('--from_resume', default=0, type=int, choices=[0, 1], help="是否自动检测&续训(0=否,1=是)")
parser.add_argument("--use_wandb", action="store_true", help="是否使用wandb")
parser.add_argument("--wandb_project", type=str, default="MiniMind-PPO", help="wandb项目名")
parser.add_argument("--use_compile", default=0, type=int, choices=[0, 1], help="是否使用torch.compile加速(0=否,1=是)")
args = parser.parse_args()
# ========== 1. 初始化环境和随机种子 ==========
local_rank = init_distributed_mode()
if dist.is_initialized(): args.device = f"cuda:{local_rank}"
setup_seed(42 + (dist.get_rank() if dist.is_initialized() else 0))
# ========== 2. 配置目录、模型参数、检查ckp ==========
os.makedirs(args.save_dir, exist_ok=True)
lm_config = MiniMindConfig(hidden_size=args.hidden_size, num_hidden_layers=args.num_hidden_layers, use_moe=bool(args.use_moe))
ckp_data = lm_checkpoint(lm_config, weight=args.save_weight, save_dir='../checkpoints') if args.from_resume==1 else None
# ========== 3. 设置混合精度 ==========
device_type = "cuda" if "cuda" in args.device else "cpu"
dtype = torch.bfloat16 if args.dtype == "bfloat16" else torch.float16
autocast_ctx = nullcontext() if device_type == "cpu" else torch.cuda.amp.autocast(dtype=dtype)
# ========== 4. 配wandb ==========
wandb = None
if args.use_wandb and is_main_process():
import swanlab as wandb
wandb_id = ckp_data.get('wandb_id') if ckp_data else None
resume = 'must' if wandb_id else None
wandb_run_name = f"MiniMind-PPO-Epoch-{args.epochs}-BS-{args.batch_size}-LR-{args.learning_rate}"
wandb.init(project=args.wandb_project, name=wandb_run_name, id=wandb_id, resume=resume)
# ========== 5. 初始化模型和数据 ==========
base_weight = "reason" if args.reasoning == 1 else "full_sft"
# Actor模型
actor_model, tokenizer = init_model(lm_config, base_weight, device=args.device)
if args.use_compile == 1:
actor_model = torch.compile(actor_model)
Logger('torch.compile enabled')
# Old Actor模型
old_actor_model, _ = init_model(lm_config, base_weight, device=args.device)
old_actor_model = old_actor_model.eval().requires_grad_(False)
# Reference模型
ref_model, _ = init_model(lm_config, base_weight, device=args.device)
ref_model = ref_model.eval().requires_grad_(False)
# Critic模型
moe_suffix = '_moe' if lm_config.use_moe else ''
ckp = f'{args.save_dir}/{base_weight}_{lm_config.hidden_size}{moe_suffix}.pth'
state_dict = torch.load(ckp, map_location=args.device)
critic_model = CriticModel(lm_config)
critic_model.load_state_dict(state_dict, strict=False)
critic_model = critic_model.to(args.device)
# Reward模型
reward_model = AutoModel.from_pretrained(
args.reward_model_path, torch_dtype=torch.float16, trust_remote_code=True
)
reward_model = reward_model.to(args.device).eval().requires_grad_(False)
reward_tokenizer = AutoTokenizer.from_pretrained(args.reward_model_path, trust_remote_code=True)
# 数据和优化器
train_ds = RLAIFDataset(args.data_path, tokenizer, max_length=(args.max_seq_len + args.max_gen_len))
train_sampler = DistributedSampler(train_ds) if dist.is_initialized() else None
actor_optimizer = optim.AdamW(actor_model.parameters(), lr=args.learning_rate)
critic_optimizer = optim.AdamW(critic_model.parameters(), lr=args.critic_learning_rate)
loader_for_count = DataLoader(train_ds, batch_size=args.batch_size, sampler=train_sampler)
iters = len(loader_for_count)
total_optimizer_steps = (iters // args.accumulation_steps) * args.epochs
actor_scheduler = CosineAnnealingLR(actor_optimizer, T_max=total_optimizer_steps, eta_min=args.learning_rate / 10)
critic_scheduler = CosineAnnealingLR(critic_optimizer, T_max=total_optimizer_steps, eta_min=args.critic_learning_rate / 10)
# ========== 6. 从ckp恢复状态 ==========
start_epoch, start_step = 0, 0
if ckp_data:
actor_model.load_state_dict(ckp_data['model'])
critic_model.load_state_dict(ckp_data['critic_model'])
actor_optimizer.load_state_dict(ckp_data['optimizer'])
critic_optimizer.load_state_dict(ckp_data['critic_optimizer'])
actor_scheduler.load_state_dict(ckp_data['scheduler'])
critic_scheduler.load_state_dict(ckp_data['critic_scheduler'])
start_epoch = ckp_data['epoch']
start_step = ckp_data.get('step', 0)
# ========== 7. DDP包模型 ==========
if dist.is_initialized():
actor_model._ddp_params_and_buffers_to_ignore = {"freqs_cos", "freqs_sin"}
critic_model._ddp_params_and_buffers_to_ignore = {"freqs_cos", "freqs_sin"}
actor_model = DistributedDataParallel(actor_model, device_ids=[local_rank])
critic_model = DistributedDataParallel(critic_model, device_ids=[local_rank])
old_actor_model.to(args.device)
# ========== 8. 开始训练 ==========
for epoch in range(start_epoch, args.epochs):
train_sampler and train_sampler.set_epoch(epoch)
setup_seed(42 + epoch); indices = torch.randperm(len(train_ds)).tolist()
skip = start_step if (epoch == start_epoch and start_step > 0) else 0
batch_sampler = SkipBatchSampler(train_sampler or indices, args.batch_size, skip)
loader = DataLoader(train_ds, batch_sampler=batch_sampler, num_workers=args.num_workers, pin_memory=True)
if skip > 0:
Logger(f'Epoch [{epoch + 1}/{args.epochs}]: 跳过前{start_step}个step,从step {start_step + 1}开始')
ppo_train_epoch(epoch, loader, len(loader) + skip, old_actor_model, ref_model,
actor_scheduler, critic_scheduler, reward_model, reward_tokenizer, start_step, wandb)
else:
ppo_train_epoch(epoch, loader, len(loader), old_actor_model, ref_model,
actor_scheduler, critic_scheduler, reward_model, reward_tokenizer, 0, wandb)
# ========== 9. 清理分布进程 ==========
if dist.is_initialized(): dist.destroy_process_group()
================================================
FILE: trainer/train_pretrain.py
================================================
import os
import sys
__package__ = "trainer"
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
import argparse
import time
import warnings
import torch
import torch.distributed as dist
from contextlib import nullcontext
from torch import optim, nn
from torch.nn.parallel import DistributedDataParallel
from torch.utils.data import DataLoader, DistributedSampler
from model.model_minimind import MiniMindConfig
from dataset.lm_dataset import PretrainDataset
from trainer.trainer_utils import get_lr, Logger, is_main_process, lm_checkpoint, init_distributed_mode, setup_seed, init_model, SkipBatchSampler
warnings.filterwarnings('ignore')
def train_epoch(epoch, loader, iters, start_step=0, wandb=None):
start_time = time.time()
for step, (input_ids, labels) in enumerate(loader, start=start_step + 1):
input_ids = input_ids.to(args.device)
labels = labels.to(args.device)
lr = get_lr(epoch * iters + step, args.epochs * iters, args.learning_rate)
for param_group in optimizer.param_groups:
param_group['lr'] = lr
with autocast_ctx:
res = model(input_ids, labels=labels)
loss = res.loss + res.aux_loss
loss = loss / args.accumulation_steps
scaler.scale(loss).backward()
if (step + 1) % args.accumulation_steps == 0:
scaler.unscale_(optimizer)
torch.nn.utils.clip_grad_norm_(model.parameters(), args.grad_clip)
scaler.step(optimizer)
scaler.update()
optimizer.zero_grad(set_to_none=True)
if step % args.log_interval == 0 or step == iters - 1:
spend_time = time.time() - start_time
current_loss = loss.item() * args.accumulation_steps
current_aux_loss = res.aux_loss.item() if res.aux_loss is not None else 0.0
current_logits_loss = current_loss - current_aux_loss
current_lr = optimizer.param_groups[-1]['lr']
eta_min = spend_time / (step + 1) * iters // 60 - spend_time // 60
Logger(f'Epoch:[{epoch + 1}/{args.epochs}]({step}/{iters}), loss: {current_loss:.4f}, logits_loss: {current_logits_loss:.4f}, aux_loss: {current_aux_loss:.4f}, lr: {current_lr:.8f}, epoch_time: {eta_min:.1f}min')
if wandb: wandb.log({"loss": current_loss, "logits_loss": current_logits_loss, "aux_loss": current_aux_loss, "learning_rate": current_lr, "epoch_time": eta_min})
if (step % args.save_interval == 0 or step == iters - 1) and is_main_process():
model.eval()
moe_suffix = '_moe' if lm_config.use_moe else ''
ckp = f'{args.save_dir}/{args.save_weight}_{lm_config.hidden_size}{moe_suffix}.pth'
raw_model = model.module if isinstance(model, DistributedDataParallel) else model
raw_model = getattr(raw_model, '_orig_mod', raw_model)
state_dict = raw_model.state_dict()
torch.save({k: v.half().cpu() for k, v in state_dict.items()}, ckp)
lm_checkpoint(lm_config, weight=args.save_weight, model=model, optimizer=optimizer, scaler=scaler, epoch=epoch, step=step, wandb=wandb, save_dir='../checkpoints')
model.train()
del state_dict
del input_ids, labels, res, loss
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="MiniMind Pretraining")
parser.add_argument("--save_dir", type=str, default="../out", help="模型保存目录")
parser.add_argument('--save_weight', default='pretrain', type=str, help="保存权重的前缀名")
parser.add_argument("--epochs", type=int, default=1, help="训练轮数(建议1轮zero或2-6轮充分训练)")
parser.add_argument("--batch_size", type=int, default=32, help="batch size")
parser.add_argument("--learning_rate", type=float, default=5e-4, help="初始学习率")
parser.add_argument("--device", type=str, default="cuda:0" if torch.cuda.is_available() else "cpu", help="训练设备")
parser.add_argument("--dtype", type=str, default="bfloat16", help="混合精度类型")
parser.add_argument("--num_workers", type=int, default=8, help="数据加载线程数")
parser.add_argument("--accumulation_steps", type=int, default=8, help="梯度累积步数")
parser.add_argument("--grad_clip", type=float, default=1.0, help="梯度裁剪阈值")
parser.add_argument("--log_interval", type=int, default=100, help="日志打印间隔")
parser.add_argument("--save_interval", type=int, default=1000, help="模型保存间隔")
parser.add_argument('--hidden_size', default=512, type=int, help="隐藏层维度")
parser.add_argument('--num_hidden_layers', default=8, type=int, help="隐藏层数量")
parser.add_argument('--max_seq_len', default=340, type=int, help="训练的最大截断长度(中文1token≈1.5~1.7字符)")
parser.add_argument('--use_moe', default=0, type=int, choices=[0, 1], help="是否使用MoE架构(0=否,1=是)")
parser.add_argument("--data_path", type=str, default="../dataset/pretrain_hq.jsonl", help="预训练数据路径")
parser.add_argument('--from_weight', default='none', type=str, help="基于哪个权重训练,为none则从头开始")
parser.add_argument('--from_resume', default=0, type=int, choices=[0, 1], help="是否自动检测&续训(0=否,1=是)")
parser.add_argument("--use_wandb", action="store_true", help="是否使用wandb")
parser.add_argument("--wandb_project", type=str, default="MiniMind-Pretrain", help="wandb项目名")
parser.add_argument("--use_compile", default=0, type=int, choices=[0, 1], help="是否使用torch.compile加速(0=否,1=是)")
args = parser.parse_args()
# ========== 1. 初始化环境和随机种子 ==========
local_rank = init_distributed_mode()
if dist.is_initialized(): args.device = f"cuda:{local_rank}"
setup_seed(42 + (dist.get_rank() if dist.is_initialized() else 0))
# ========== 2. 配置目录、模型参数、检查ckp ==========
os.makedirs(args.save_dir, exist_ok=True)
lm_config = MiniMindConfig(hidden_size=args.hidden_size, num_hidden_layers=args.num_hidden_layers, use_moe=bool(args.use_moe))
ckp_data = lm_checkpoint(lm_config, weight=args.save_weight, save_dir='../checkpoints') if args.from_resume==1 else None
# ========== 3. 设置混合精度 ==========
device_type = "cuda" if "cuda" in args.device else "cpu"
dtype = torch.bfloat16 if args.dtype == "bfloat16" else torch.float16
autocast_ctx = nullcontext() if device_type == "cpu" else torch.cuda.amp.autocast(dtype=dtype)
# ========== 4. 配wandb ==========
wandb = None
if args.use_wandb and is_main_process():
import swanlab as wandb
wandb_id = ckp_data.get('wandb_id') if ckp_data else None
resume = 'must' if wandb_id else None
wandb_run_name = f"MiniMind-Pretrain-Epoch-{args.epochs}-BatchSize-{args.batch_size}-LearningRate-{args.learning_rate}"
wandb.init(project=args.wandb_project, name=wandb_run_name, id=wandb_id, resume=resume)
# ========== 5. 定义模型、数据、优化器 ==========
model, tokenizer = init_model(lm_config, args.from_weight, device=args.device)
if args.use_compile == 1:
model = torch.compile(model)
Logger('torch.compile enabled')
train_ds = PretrainDataset(args.data_path, tokenizer, max_length=args.max_seq_len)
train_sampler = DistributedSampler(train_ds) if dist.is_initialized() else None
scaler = torch.cuda.amp.GradScaler(enabled=(args.dtype == 'float16'))
optimizer = optim.AdamW(model.parameters(), lr=args.learning_rate)
# ========== 6. 从ckp恢复状态 ==========
start_epoch, start_step = 0, 0
if ckp_data:
model.load_state_dict(ckp_data['model'])
optimizer.load_state_dict(ckp_data['optimizer'])
scaler.load_state_dict(ckp_data['scaler'])
start_epoch = ckp_data['epoch']
start_step = ckp_data.get('step', 0)
# ========== 7. DDP包模型 ==========
if dist.is_initialized():
model._ddp_params_and_buffers_to_ignore = {"freqs_cos", "freqs_sin"}
model = DistributedDataParallel(model, device_ids=[local_rank])
# ========== 8. 开始训练 ==========
for epoch in range(start_epoch, args.epochs):
train_sampler and train_sampler.set_epoch(epoch)
setup_seed(42 + epoch); indices = torch.randperm(len(train_ds)).tolist()
skip = start_step if (epoch == start_epoch and start_step > 0) else 0
batch_sampler = SkipBatchSampler(train_sampler or indices, args.batch_size, skip)
loader = DataLoader(train_ds, batch_sampler=batch_sampler, num_workers=args.num_workers, pin_memory=True)
if skip > 0:
Logger(f'Epoch [{epoch + 1}/{args.epochs}]: 跳过前{start_step}个step,从step {start_step + 1}开始')
train_epoch(epoch, loader, len(loader) + skip, start_step, wandb)
else:
train_epoch(epoch, loader, len(loader), 0, wandb)
# ========== 9. 清理分布进程 ==========
if dist.is_initialized(): dist.destroy_process_group()
================================================
FILE: trainer/train_reason.py
================================================
import os
import sys
__package__ = "trainer"
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
import argparse
import time
import warnings
import torch
import torch.distributed as dist
from contextlib import nullcontext
from torch import optim, nn
from torch.nn.parallel import DistributedDataParallel
from torch.utils.data import DataLoader, DistributedSampler
from model.model_minimind import MiniMindConfig
from dataset.lm_dataset import SFTDataset
from trainer.trainer_utils import get_lr, Logger, is_main_process, lm_checkpoint, init_distributed_mode, setup_seed, init_model, SkipBatchSampler
warnings.filterwarnings('ignore')
def train_epoch(epoch, loader, iters, tokenizer, lm_config, start_step=0, wandb=None):
start_of_think_ids = tokenizer('').input_ids
end_of_think_ids = tokenizer(' ').input_ids
start_of_answer_ids = tokenizer('').input_ids
end_of_answer_ids = tokenizer(' ').input_ids
loss_fct = nn.CrossEntropyLoss(reduction='none')
start_time = time.time()
for step, (input_ids, labels) in enumerate(loader, start=start_step + 1):
input_ids = input_ids.to(args.device)
labels = labels.to(args.device)
lr = get_lr(epoch * iters + step, args.epochs * iters, args.learning_rate)
for param_group in optimizer.param_groups:
param_group['lr'] = lr
with autocast_ctx:
res = model(input_ids)
shift_logits = res.logits[..., :-1, :].contiguous()
shift_labels = labels[..., 1:].contiguous()
loss = loss_fct(shift_logits.view(-1, shift_logits.size(-1)), shift_labels.view(-1)).view(shift_labels.size())
loss_mask = (shift_labels != -100).float()
sp_ids = torch.isin(shift_labels.view(-1),
torch.tensor(start_of_think_ids + end_of_think_ids
+ start_of_answer_ids + end_of_answer_ids
).to(args.device))
loss_mask_flat = loss_mask.view(-1)
loss_mask_sum = loss_mask_flat.sum()
loss_mask_flat[sp_ids] = 10
loss_mask = loss_mask_flat.view(shift_labels.size())
logits_loss = (loss * loss_mask).sum() / loss_mask_sum
loss = logits_loss + res.aux_loss
loss = loss / args.accumulation_steps
scaler.scale(loss).backward()
if (step + 1) % args.accumulation_steps == 0:
scaler.unscale_(optimizer)
torch.nn.utils.clip_grad_norm_(model.parameters(), args.grad_clip)
scaler.step(optimizer)
scaler.update()
optimizer.zero_grad(set_to_none=True)
if step % args.log_interval == 0 or step == iters - 1:
spend_time = time.time() - start_time
current_loss = loss.item() * args.accumulation_steps
current_aux_loss = res.aux_loss.item() if res.aux_loss is not None else 0.0
current_logits_loss = logits_loss.item()
current_lr = optimizer.param_groups[-1]['lr']
eta_min = spend_time / (step + 1) * iters // 60 - spend_time // 60
Logger(f'Epoch:[{epoch + 1}/{args.epochs}]({step}/{iters}), loss: {current_loss:.4f}, logits_loss: {current_logits_loss:.4f}, aux_loss: {current_aux_loss:.4f}, lr: {current_lr:.8f}, epoch_time: {eta_min:.1f}min')
if wandb: wandb.log({"loss": current_loss, "logits_loss": current_logits_loss, "aux_loss": current_aux_loss, "learning_rate": current_lr, "epoch_time": eta_min})
if (step % args.save_interval == 0 or step == iters - 1) and is_main_process():
model.eval()
moe_suffix = '_moe' if lm_config.use_moe else ''
ckp = f'{args.save_dir}/{args.save_weight}_{lm_config.hidden_size}{moe_suffix}.pth'
raw_model = model.module if isinstance(model, DistributedDataParallel) else model
raw_model = getattr(raw_model, '_orig_mod', raw_model)
state_dict = raw_model.state_dict()
torch.save({k: v.half().cpu() for k, v in state_dict.items()}, ckp)
lm_checkpoint(lm_config, weight=args.save_weight, model=model, optimizer=optimizer, scaler=scaler, epoch=epoch, step=step, wandb=wandb, save_dir='../checkpoints')
model.train()
del state_dict
del input_ids, labels, res, loss
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="MiniMind Reasoning Distillation")
parser.add_argument("--save_dir", type=str, default="../out", help="模型保存目录")
parser.add_argument('--save_weight', default='reason', type=str, help="保存权重的前缀名")
parser.add_argument("--epochs", type=int, default=1, help="训练轮数")
parser.add_argument("--batch_size", type=int, default=8, help="batch size")
parser.add_argument("--learning_rate", type=float, default=1e-6, help="初始学习率")
parser.add_argument("--device", type=str, default="cuda:0" if torch.cuda.is_available() else "cpu", help="训练设备")
parser.add_argument("--dtype", type=str, default="bfloat16", help="混合精度类型")
parser.add_argument("--num_workers", type=int, default=8, help="数据加载线程数")
parser.add_argument("--accumulation_steps", type=int, default=1, help="梯度累积步数")
parser.add_argument("--grad_clip", type=float, default=1.0, help="梯度裁剪阈值")
parser.add_argument("--log_interval", type=int, default=100, help="日志打印间隔")
parser.add_argument("--save_interval", type=int, default=100, help="模型保存间隔")
parser.add_argument('--hidden_size', default=512, type=int, help="隐藏层维度")
parser.add_argument('--num_hidden_layers', default=8, type=int, help="隐藏层数量")
parser.add_argument('--max_seq_len', default=720, type=int, help="训练的最大截断长度(中文1token≈1.5~1.7字符)")
parser.add_argument('--use_moe', default=0, type=int, choices=[0, 1], help="是否使用MoE架构(0=否,1=是)")
parser.add_argument("--data_path", type=str, default="../dataset/r1_mix_1024.jsonl", help="推理蒸馏数据路径")
parser.add_argument('--from_weight', default='dpo', type=str, help="基于哪个权重训练,默认dpo")
parser.add_argument('--from_resume', default=0, type=int, choices=[0, 1], help="是否自动检测&续训(0=否,1=是)")
parser.add_argument("--use_wandb", action="store_true", help="是否使用wandb")
parser.add_argument("--wandb_project", type=str, default="MiniMind-Reasoning", help="wandb项目名")
parser.add_argument("--use_compile", default=0, type=int, choices=[0, 1], help="是否使用torch.compile加速(0=否,1=是)")
args = parser.parse_args()
# ========== 1. 初始化环境和随机种子 ==========
local_rank = init_distributed_mode()
if dist.is_initialized(): args.device = f"cuda:{local_rank}"
setup_seed(42 + (dist.get_rank() if dist.is_initialized() else 0))
# ========== 2. 配置目录、模型参数、检查ckp ==========
os.makedirs(args.save_dir, exist_ok=True)
lm_config = MiniMindConfig(hidden_size=args.hidden_size, num_hidden_layers=args.num_hidden_layers, use_moe=bool(args.use_moe))
ckp_data = lm_checkpoint(lm_config, weight=args.save_weight, save_dir='../checkpoints') if args.from_resume==1 else None
# ========== 3. 设置混合精度 ==========
device_type = "cuda" if "cuda" in args.device else "cpu"
dtype = torch.bfloat16 if args.dtype == "bfloat16" else torch.float16
autocast_ctx = nullcontext() if device_type == "cpu" else torch.cuda.amp.autocast(dtype=dtype)
# ========== 4. 配wandb ==========
wandb = None
if args.use_wandb and is_main_process():
import swanlab as wandb
wandb_id = ckp_data.get('wandb_id') if ckp_data else None
resume = 'must' if wandb_id else None
wandb_run_name = f"MiniMind-Reasoning-Epoch-{args.epochs}-BatchSize-{args.batch_size}-LR-{args.learning_rate}"
wandb.init(project=args.wandb_project, name=wandb_run_name, id=wandb_id, resume=resume)
# ========== 5. 定义模型、数据、优化器 ==========
model, tokenizer = init_model(lm_config, args.from_weight, device=args.device)
if args.use_compile == 1:
model = torch.compile(model)
Logger('torch.compile enabled')
train_ds = SFTDataset(args.data_path, tokenizer, max_length=args.max_seq_len)
train_sampler = DistributedSampler(train_ds) if dist.is_initialized() else None
scaler = torch.cuda.amp.GradScaler(enabled=(args.dtype == 'float16'))
optimizer = optim.AdamW(model.parameters(), lr=args.learning_rate)
# ========== 6. 从ckp恢复状态 ==========
start_epoch, start_step = 0, 0
if ckp_data:
model.load_state_dict(ckp_data['model'])
optimizer.load_state_dict(ckp_data['optimizer'])
scaler.load_state_dict(ckp_data['scaler'])
start_epoch = ckp_data['epoch']
start_step = ckp_data.get('step', 0)
# ========== 7. DDP包模型 ==========
if dist.is_initialized():
model._ddp_params_and_buffers_to_ignore = {"freqs_cos", "freqs_sin"}
model = DistributedDataParallel(model, device_ids=[local_rank])
# ========== 8. 开始训练 ==========
for epoch in range(start_epoch, args.epochs):
train_sampler and train_sampler.set_epoch(epoch)
setup_seed(42 + epoch); indices = torch.randperm(len(train_ds)).tolist()
skip = start_step if (epoch == start_epoch and start_step > 0) else 0
batch_sampler = SkipBatchSampler(train_sampler or indices, args.batch_size, skip)
loader = DataLoader(train_ds, batch_sampler=batch_sampler, num_workers=args.num_workers, pin_memory=True)
if skip > 0:
Logger(f'Epoch [{epoch + 1}/{args.epochs}]: 跳过前{start_step}个step,从step {start_step + 1}开始')
train_epoch(epoch, loader, len(loader) + skip, tokenizer, lm_config, start_step, wandb)
else:
train_epoch(epoch, loader, len(loader), tokenizer, lm_config, 0, wandb)
# ========== 9. 清理分布进程 ==========
if dist.is_initialized(): dist.destroy_process_group()
================================================
FILE: trainer/train_spo.py
================================================
import os
import sys
__package__ = "trainer"
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
import argparse
import re
import gc
import warnings
import torch
import torch.distributed as dist
from transformers import AutoTokenizer
from contextlib import nullcontext
from torch import optim
from torch.nn.parallel import DistributedDataParallel
from torch.utils.data import DataLoader, DistributedSampler
from torch.optim.lr_scheduler import CosineAnnealingLR
from transformers import AutoModel
from model.model_minimind import MiniMindConfig, MiniMindForCausalLM
from dataset.lm_dataset import RLAIFDataset
from trainer.trainer_utils import Logger, is_main_process, lm_checkpoint, init_distributed_mode, setup_seed, SkipBatchSampler, init_model
warnings.filterwarnings('ignore')
class AutoAdaptiveValueTracker:
"""SPO自适应价值追踪器"""
def __init__(self, rho_mode='kl', rho_const=0.9, D_half=0.06, clip_lower=0.5, clip_upper=0.96):
self.rho_mode = rho_mode
self.rho_const = rho_const
self.D_half = D_half
self.clip_lower = clip_lower
self.clip_upper = clip_upper
N_init = 1.0 / (1.0 - self.clip_lower)
self.alpha = 0.5 * N_init
self.beta = 0.5 * N_init
self.old_mean_logprob = None
def get_baselines(self, batch_size):
baseline = self.alpha / (self.alpha + self.beta)
return torch.full((batch_size,), baseline, dtype=torch.float32)
def compute_rho(self, cur_mean_logprob):
if self.rho_mode == 'constant':
return self.rho_const
if self.old_mean_logprob is None:
return self.rho_const
kl = abs(self.old_mean_logprob - cur_mean_logprob)
rho = 2 ** (-kl / self.D_half)
return max(min(rho, self.clip_upper), self.clip_lower)
def update(self, rewards, cur_logprobs=None, response_masks=None):
if cur_logprobs is not None and response_masks is not None:
mean_logprob = ((cur_logprobs * response_masks).sum() / response_masks.sum()).item()
rho = self.compute_rho(mean_logprob)
self.old_mean_logprob = mean_logprob
else:
rho = self.rho_const
scale = 3.0
normalized_rewards = (rewards + scale) / (2 * scale)
avg_normalized_reward = normalized_rewards.mean().item()
self.alpha = rho * self.alpha + avg_normalized_reward
self.beta = rho * self.beta + (1 - avg_normalized_reward)
return rho
def calculate_rewards(prompts, responses, reward_model, reward_tokenizer):
"""整合所有奖励函数计算总奖励"""
def reasoning_model_reward(rewards):
pattern = r"^\n.*?\n \n\n.*?\n $"
pattern2 = r"^\n.*?\n \n\n\n.*?\n $"
matches_pattern = [re.match(pattern, response, re.S) for response in responses]
matches_pattern2 = [re.match(pattern2, response, re.S) for response in responses]
format_rewards = []
for match_pattern, match_pattern2 in zip(matches_pattern, matches_pattern2):
if match_pattern or match_pattern2:
format_rewards.append(0.5)
else:
format_rewards.append(0.0)
rewards += torch.tensor(format_rewards, device=args.device)
def mark_num(text):
reward = 0
if text.count("") == 1: reward += 0.25
if text.count(" ") == 1: reward += 0.25
if text.count("") == 1: reward += 0.25
if text.count(" ") == 1: reward += 0.25
return reward
mark_rewards = [mark_num(response) for response in responses]
rewards += torch.tensor(mark_rewards, device=args.device)
return rewards
rewards = torch.zeros(len(responses), device=args.device)
if args.reasoning == 1:
rewards = reasoning_model_reward(rewards)
with torch.no_grad():
reward_model_scores = []
scale = 3.0
for i, (prompt, response) in enumerate(zip(prompts, responses)):
pattern = r"<\|im_start\|>(system|user|assistant)\s+(.*?)<\|im_end\|>"
matches = re.findall(pattern, prompt, re.DOTALL)
messages = [{"role": role, "content": content.strip()} for role, content in matches]
tmp_chat = messages + [{"role": "assistant", "content": response}]
score = reward_model.get_score(reward_tokenizer, tmp_chat)
score = max(min(score, scale), -scale)
if args.reasoning == 1:
answer_match = re.search(r'(.*?) ', response, re.DOTALL)
if answer_match:
answer_content = answer_match.group(1).strip()
tmp_chat = messages + [{"role": "assistant", "content": answer_content}]
answer_score = reward_model.get_score(reward_tokenizer, tmp_chat)
answer_score = max(min(answer_score, scale), -scale)
score = score * 0.4 + answer_score * 0.6
reward_model_scores.append(score)
reward_model_scores = torch.tensor(reward_model_scores, device=args.device)
rewards += reward_model_scores
return rewards
def spo_train_epoch(epoch, loader, iters, ref_model, reward_model, reward_tokenizer, value_tracker, start_step=0, wandb=None):
for step, batch in enumerate(loader, start=start_step + 1):
prompts = batch['prompt'] # list[str], length B
prompt_inputs = tokenizer(prompts, return_tensors="pt", padding=True, return_token_type_ids=False,
padding_side="left", add_special_tokens=False).to(args.device) # input_ids: [B, P], attention_mask: [B, P]
if args.max_seq_len:
prompt_inputs["input_ids"] = prompt_inputs["input_ids"][:, -args.max_seq_len:]
prompt_inputs["attention_mask"] = prompt_inputs["attention_mask"][:, -args.max_seq_len:]
with torch.no_grad():
# DDP 模型需要使用 .module 访问 generate 方法
model_for_gen = model.module if isinstance(model, DistributedDataParallel) else model
outputs = model_for_gen.generate(
**prompt_inputs, max_new_tokens=args.max_gen_len, do_sample=True, temperature=0.8,
num_return_sequences=1, pad_token_id=tokenizer.pad_token_id) # [B, P+R]
completion_ids = outputs[:, prompt_inputs["input_ids"].size(1):] # [B, R]
def get_per_token_logps(mdl, input_ids, n_keep):
input_ids = input_ids.detach().clone() if input_ids.is_inference() else input_ids
logits = mdl(input_ids, logits_to_keep=n_keep + 1).logits[:, :-1, :]
per_token_logps = []
for logits_row, ids_row in zip(logits, input_ids[:, -n_keep:]):
ids_row = ids_row.detach().clone() if ids_row.is_inference() else ids_row
per_token_logps.append(torch.gather(logits_row.log_softmax(dim=-1), 1, ids_row.unsqueeze(1)).squeeze(1))
return torch.stack(per_token_logps)
with autocast_ctx:
per_token_logps = get_per_token_logps(model, outputs, completion_ids.size(1)) # [B, R]
res = model(outputs) if lm_config.use_moe else None
aux_loss = res.aux_loss if res is not None else torch.tensor(0.0, device=args.device)
with torch.no_grad():
ref_per_token_logps = get_per_token_logps(ref_model, outputs, completion_ids.size(1)) # [B, R]
completions = tokenizer.batch_decode(completion_ids, skip_special_tokens=True) # list[str], length B
rewards = calculate_rewards(prompts, completions, reward_model, reward_tokenizer).to(args.device) # [B]
baselines = value_tracker.get_baselines(len(prompts)).to(args.device) # [B]
scale = 3.0
# Un-normalize baselines to be in the same scale as raw rewards [-3, 3]
unnormalized_baselines = baselines * (2 * scale) - scale # [B]
advantages = rewards - unnormalized_baselines # [B]
# 直接使用 baseline 提供的优势估计,只做裁剪防止梯度爆炸。不再做 batch 内归一化,因为 baseline 已经提供了跨 batch 的稳定基线
advantages = advantages.clamp(-5.0, 5.0)
is_eos = completion_ids == tokenizer.eos_token_id # [B, R]
eos_idx = torch.full((is_eos.size(0),), is_eos.size(1), dtype=torch.long, device=args.device) # [B]
eos_idx[is_eos.any(dim=1)] = is_eos.int().argmax(dim=1)[is_eos.any(dim=1)]
completion_mask = (torch.arange(is_eos.size(1), device=args.device).expand(is_eos.size(0), -1) <= eos_idx.unsqueeze(1)).int() # [B, R]
kl_div = ref_per_token_logps - per_token_logps # [B, R]
per_token_kl = torch.exp(kl_div) - kl_div - 1 # [B, R]
per_token_loss = -per_token_logps * advantages.unsqueeze(1) + args.beta * per_token_kl # [B, R]
policy_loss = ((per_token_loss * completion_mask).sum(dim=1) / completion_mask.sum(dim=1)).mean()
loss = (policy_loss + aux_loss) / args.accumulation_steps # scalar
loss.backward()
response_masks = completion_mask.float() # [B, R]
rho = value_tracker.update(rewards, per_token_logps.detach(), response_masks)
if (step + 1) % args.accumulation_steps == 0:
if args.grad_clip > 0:
torch.nn.utils.clip_grad_norm_(model.parameters(), args.grad_clip)
optimizer.step()
scheduler.step()
optimizer.zero_grad()
if step % args.log_interval == 0 or step == iters:
policy_loss_val = loss.item() * args.accumulation_steps
current_aux_loss = aux_loss.item()
avg_reward_val = rewards.mean().item()
avg_len_val = completion_mask.sum(dim=1).float().mean().item()
kl_val = ((per_token_kl * completion_mask).sum() / (completion_mask.sum() + 1e-8)).item()
avg_baseline_val = baselines.mean().item()
current_lr = optimizer.param_groups[0]['lr']
Logger(f'Epoch:[{epoch + 1}/{args.epochs}]({step}/{iters}), '
f'Actor Loss: {policy_loss_val:.4f}, Aux Loss: {current_aux_loss:.4f}, Reward: {avg_reward_val:.4f}, '
f'Baseline: {avg_baseline_val:.4f}, KL: {kl_val:.4f}, Rho: {rho:.4f}, '
f'Avg Response Len: {avg_len_val:.2f}, Learning Rate: {current_lr:.8f}')
if wandb and is_main_process():
wandb.log({
"policy_loss": policy_loss_val,
"aux_loss": current_aux_loss,
"reward": avg_reward_val,
"kl": kl_val,
"rho": float(rho),
"baseline": avg_baseline_val,
"advantages_mean": advantages.mean().item(),
"learning_rate": current_lr
})
if (step % args.save_interval == 0 or step == iters - 1) and is_main_process():
model.eval()
moe_suffix = '_moe' if lm_config.use_moe else ''
ckp = f'{args.save_dir}/{args.save_weight}_{lm_config.hidden_size}{moe_suffix}.pth'
raw_model = model.module if isinstance(model, DistributedDataParallel) else model
raw_model = getattr(raw_model, '_orig_mod', raw_model)
state_dict = raw_model.state_dict()
torch.save({k: v.half().cpu() for k, v in state_dict.items()}, ckp)
lm_checkpoint(lm_config, weight=args.save_weight, model=model, optimizer=optimizer,
epoch=epoch, step=step, wandb=wandb, save_dir='../checkpoints', scheduler=scheduler)
model.train()
del state_dict
del prompt_inputs, outputs, completion_ids, per_token_logps, ref_per_token_logps
del completions, rewards, advantages, completion_mask, baselines, response_masks
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="MiniMind SPO (Self-Play Optimization)")
parser.add_argument("--save_dir", type=str, default="../out", help="模型保存目录")
parser.add_argument('--save_weight', default='spo', type=str, help="保存权重的前缀名")
parser.add_argument("--epochs", type=int, default=1, help="训练轮数")
parser.add_argument("--batch_size", type=int, default=2, help="batch size")
parser.add_argument("--learning_rate", type=float, default=1e-7, help="初始学习率")
parser.add_argument("--device", type=str, default="cuda:0" if torch.cuda.is_available() else "cpu", help="训练设备")
parser.add_argument("--dtype", type=str, default="bfloat16", help="混合精度类型")
parser.add_argument("--num_workers", type=int, default=8, help="数据加载线程数")
parser.add_argument("--accumulation_steps", type=int, default=4, help="梯度累积步数")
parser.add_argument("--grad_clip", type=float, default=1.0, help="梯度裁剪阈值")
parser.add_argument("--log_interval", type=int, default=1, help="日志打印间隔")
parser.add_argument("--save_interval", type=int, default=10, help="模型保存间隔")
parser.add_argument('--hidden_size', default=512, type=int, help="隐藏层维度")
parser.add_argument('--num_hidden_layers', default=8, type=int, help="隐藏层数量")
parser.add_argument('--use_moe', default=0, type=int, choices=[0, 1], help="是否使用MoE架构(0=否,1=是)")
parser.add_argument('--max_seq_len', default=66, type=int, help="Prompt最大长度")
parser.add_argument("--max_gen_len", type=int, default=1536, help="生成的最大长度")
parser.add_argument("--data_path", type=str, default="../dataset/rlaif-mini.jsonl", help="RLAIF数据路径")
parser.add_argument("--beta", type=float, default=0.02, help="KL惩罚系数")
parser.add_argument("--reasoning", type=int, default=1, choices=[0, 1], help='推理模型类型(0=普通模型,1=推理模型)')
parser.add_argument("--reward_model_path", type=str, default="../../internlm2-1_8b-reward", help="Reward模型路径")
parser.add_argument('--from_resume', default=0, type=int, choices=[0, 1], help="是否自动检测&续训(0=否,1=是)")
parser.add_argument("--use_wandb", action="store_true", help="是否使用wandb")
parser.add_argument("--wandb_project", type=str, default="MiniMind-SPO", help="wandb项目名")
parser.add_argument("--use_compile", default=0, type=int, choices=[0, 1], help="是否使用torch.compile加速(0=否,1=是)")
args = parser.parse_args()
# ========== 1. 初始化环境和随机种子 ==========
local_rank = init_distributed_mode()
if dist.is_initialized(): args.device = f"cuda:{local_rank}"
setup_seed(42 + (dist.get_rank() if dist.is_initialized() else 0))
# ========== 2. 配置目录、模型参数、检查ckp ==========
os.makedirs(args.save_dir, exist_ok=True)
lm_config = MiniMindConfig(hidden_size=args.hidden_size, num_hidden_layers=args.num_hidden_layers,
max_seq_len=args.max_seq_len + args.max_gen_len, use_moe=bool(args.use_moe))
ckp_data = lm_checkpoint(lm_config, weight=args.save_weight, save_dir='../checkpoints') if args.from_resume==1 else None
# ========== 3. 设置混合精度 ==========
device_type = "cuda" if "cuda" in args.device else "cpu"
dtype = torch.bfloat16 if args.dtype == "bfloat16" else torch.float16
autocast_ctx = nullcontext() if device_type == "cpu" else torch.cuda.amp.autocast(dtype=dtype)
# ========== 4. 配wandb ==========
wandb = None
if args.use_wandb and is_main_process():
import swanlab as wandb
wandb_id = ckp_data.get('wandb_id') if ckp_data else None
resume = 'must' if wandb_id else None
wandb_run_name = f"MiniMind-SPO-Epoch-{args.epochs}-BS-{args.batch_size}-LR-{args.learning_rate}"
wandb.init(project=args.wandb_project, name=wandb_run_name, id=wandb_id, resume=resume)
# ========== 5. 初始化模型(Policy, Ref, Reward)和Value Tracker、数据 ==========
base_weight = "reason" if args.reasoning == 1 else "full_sft"
# Policy模型
model, tokenizer = init_model(lm_config, base_weight, device=args.device)
if args.use_compile == 1:
model = torch.compile(model)
Logger('torch.compile enabled')
# Reference模型
ref_model, _ = init_model(lm_config, base_weight, device=args.device)
ref_model = ref_model.eval().requires_grad_(False)
# Reward模型
reward_model = AutoModel.from_pretrained(
args.reward_model_path, torch_dtype=torch.float16, trust_remote_code=True
)
reward_model = reward_model.to(args.device).eval().requires_grad_(False)
reward_tokenizer = AutoTokenizer.from_pretrained(args.reward_model_path, trust_remote_code=True)
# Value Tracker
value_tracker = AutoAdaptiveValueTracker(rho_mode='kl', rho_const=0.9, D_half=0.06, clip_lower=0.5, clip_upper=0.96)
train_ds = RLAIFDataset(args.data_path, tokenizer, max_length=lm_config.max_seq_len)
train_sampler = DistributedSampler(train_ds) if dist.is_initialized() else None
optimizer = optim.AdamW(model.parameters(), lr=args.learning_rate)
loader_for_count = DataLoader(train_ds, batch_size=args.batch_size, sampler=train_sampler)
iters = len(loader_for_count)
total_optimizer_steps = (iters // args.accumulation_steps) * args.epochs
scheduler = CosineAnnealingLR(optimizer, T_max=total_optimizer_steps, eta_min=args.learning_rate / 10)
# ========== 6. 从ckp恢复状态 ==========
start_epoch, start_step = 0, 0
if ckp_data:
model.load_state_dict(ckp_data['model'])
optimizer.load_state_dict(ckp_data['optimizer'])
scheduler.load_state_dict(ckp_data['scheduler'])
start_epoch = ckp_data['epoch']
start_step = ckp_data.get('step', 0)
# ========== 7. DDP包模型 ==========
if dist.is_initialized():
model._ddp_params_and_buffers_to_ignore = {"freqs_cos", "freqs_sin"}
model = DistributedDataParallel(model, device_ids=[local_rank])
# ========== 8. 开始训练 ==========
for epoch in range(start_epoch, args.epochs):
train_sampler and train_sampler.set_epoch(epoch)
setup_seed(42 + epoch); indices = torch.randperm(len(train_ds)).tolist()
skip = start_step if (epoch == start_epoch and start_step > 0) else 0
batch_sampler = SkipBatchSampler(train_sampler or indices, args.batch_size, skip)
loader = DataLoader(train_ds, batch_sampler=batch_sampler, num_workers=args.num_workers, pin_memory=True)
if skip > 0:
Logger(f'Epoch [{epoch + 1}/{args.epochs}]: 跳过前{start_step}个step,从step {start_step + 1}开始')
spo_train_epoch(epoch, loader, len(loader) + skip, ref_model, reward_model, reward_tokenizer, value_tracker, start_step, wandb)
else:
spo_train_epoch(epoch, loader, len(loader), ref_model, reward_model, reward_tokenizer, value_tracker, 0, wandb)
# ========== 9. 清理分布进程 ==========
if dist.is_initialized(): dist.destroy_process_group()
================================================
FILE: trainer/train_tokenizer.py
================================================
# 注:不建议再重复训练tokenizer(“词典”),MiniMind已自带,此脚本仅供学习和参考。基于不同词典训练的模型将导致输出完全不统一,降低社区的模型复用性
# Note: It is not recommended to re-train the tokenizer. MiniMind already includes one. This script is for learning and reference only. Training models with different tokenizers will lead to inconsistent outputs and reduce model reusability in the community.
import os
import json
from tokenizers import decoders, models, pre_tokenizers, trainers, Tokenizer
DATA_PATH = '../dataset/pretrain_hq.jsonl'
TOKENIZER_DIR = '../model_learn_tokenizer/'
VOCAB_SIZE = 6400
def get_texts(data_path):
with open(data_path, 'r', encoding='utf-8') as f:
for i, line in enumerate(f):
if i >= 10000: break # 实验性,可只用前10000行测试
data = json.loads(line)
yield data['text']
def train_tokenizer(data_path, tokenizer_dir, vocab_size):
tokenizer = Tokenizer(models.BPE())
tokenizer.pre_tokenizer = pre_tokenizers.ByteLevel(add_prefix_space=False)
trainer = trainers.BpeTrainer(
vocab_size=vocab_size,
special_tokens=["<|endoftext|>", "<|im_start|>", "<|im_end|>"],
show_progress=True,
initial_alphabet=pre_tokenizers.ByteLevel.alphabet()
)
texts = get_texts(data_path)
tokenizer.train_from_iterator(texts, trainer=trainer)
tokenizer.decoder = decoders.ByteLevel()
assert tokenizer.token_to_id("<|endoftext|>") == 0
assert tokenizer.token_to_id("<|im_start|>") == 1
assert tokenizer.token_to_id("<|im_end|>") == 2
os.makedirs(tokenizer_dir, exist_ok=True)
tokenizer.save(os.path.join(tokenizer_dir, "tokenizer.json"))
tokenizer.model.save(tokenizer_dir)
config = {
"add_bos_token": False,
"add_eos_token": False,
"add_prefix_space": False,
"added_tokens_decoder": {
"0": {
"content": "<|endoftext|>",
"lstrip": False,
"normalized": False,
"rstrip": False,
"single_word": False,
"special": True
},
"1": {
"content": "<|im_start|>",
"lstrip": False,
"normalized": False,
"rstrip": False,
"single_word": False,
"special": True
},
"2": {
"content": "<|im_end|>",
"lstrip": False,
"normalized": False,
"rstrip": False,
"single_word": False,
"special": True
}
},
"additional_special_tokens": [],
"bos_token": "<|im_start|>",
"clean_up_tokenization_spaces": False,
"eos_token": "<|im_end|>",
"legacy": True,
"model_max_length": 32768,
"pad_token": "<|endoftext|>",
"sp_model_kwargs": {},
"spaces_between_special_tokens": False,
"tokenizer_class": "PreTrainedTokenizerFast",
"unk_token": "<|endoftext|>",
"chat_template": "{%- if tools %}\n {{- '<|im_start|>system\\n' }}\n {%- if messages[0].role == 'system' %}\n {{- messages[0].content + '\\n\\n' }}\n {%- endif %}\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\" }}\n {%- for tool in tools %}\n {{- \"\\n\" }}\n {{- tool | tojson }}\n {%- endfor %}\n {{- \"\\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\" }}\n{%- else %}\n {%- if messages[0]['role'] == 'system' -%}\n {{- '<|im_start|>system\\n' + messages[0]['content'] + '<|im_end|>\\n' }}\n {%- else -%}\n {{- '<|im_start|>system\\nYou are a helpful assistant<|im_end|>\\n' }}\n {%- endif %}\n{%- endif %}\n{%- set ns = namespace(multi_step_tool=true, last_query_index=messages|length - 1) %}\n{%- for message in messages[::-1] %}\n {%- set index = (messages|length - 1) - loop.index0 %}\n {%- if ns.multi_step_tool and message.role == \"user\" and message.content is string and not(message.content.startswith('') and message.content.endswith(' ')) %}\n {%- set ns.multi_step_tool = false %}\n {%- set ns.last_query_index = index %}\n {%- endif %}\n{%- endfor %}\n{%- for message in messages %}\n {%- if message.content is string %}\n {%- set content = message.content %}\n {%- else %}\n {%- set content = '' %}\n {%- endif %}\n {%- if (message.role == \"user\") or (message.role == \"system\" and not loop.first) %}\n {{- '<|im_start|>' + message.role + '\\n' + content + '<|im_end|>' + '\\n' }}\n {%- elif message.role == \"assistant\" %}\n {{- '<|im_start|>' + message.role + '\\n' + content }}\n {%- if message.tool_calls %}\n {%- for tool_call in message.tool_calls %}\n {%- if (loop.first and content) or (not loop.first) %}\n {{- '\\n' }}\n {%- endif %}\n {%- if tool_call.function %}\n {%- set tool_call = tool_call.function %}\n {%- endif %}\n {{- '\\n{\"name\": \"' }}\n {{- tool_call.name }}\n {{- '\", \"arguments\": ' }}\n {%- if tool_call.arguments is string %}\n {{- tool_call.arguments }}\n {%- else %}\n {{- tool_call.arguments | tojson }}\n {%- endif %}\n {{- '}\\n ' }}\n {%- endfor %}\n {%- endif %}\n {{- '<|im_end|>\\n' }}\n {%- elif message.role == \"tool\" %}\n {%- if loop.first or (messages[loop.index0 - 1].role != \"tool\") %}\n {{- '<|im_start|>user' }}\n {%- endif %}\n {{- '\\n\\n' }}\n {{- content }}\n {{- '\\n ' }}\n {%- if loop.last or (messages[loop.index0 + 1].role != \"tool\") %}\n {{- '<|im_end|>\\n' }}\n {%- endif %}\n {%- endif %}\n{%- endfor %}\n{%- if add_generation_prompt %}\n {{- '<|im_start|>assistant\\n' }}\n {%- if enable_thinking is defined and enable_thinking is false %}\n {{- '\\n\\n \\n\\n' }}\n {%- endif %}\n{%- endif %}"
}
with open(os.path.join(tokenizer_dir, "tokenizer_config.json"), "w", encoding="utf-8") as f:
json.dump(config, f, ensure_ascii=False, indent=4)
print("Tokenizer training completed.")
def eval_tokenizer(tokenizer_dir):
from transformers import AutoTokenizer
tokenizer = AutoTokenizer.from_pretrained(tokenizer_dir)
messages = [
{"role": "system", "content": "你是一个优秀的聊天机器人,总是给我正确的回应!"},
{"role": "user", "content": '你来自哪里?'},
{"role": "assistant", "content": '我来自地球'}
]
new_prompt = tokenizer.apply_chat_template(
messages,
tokenize=False
)
print('-'*100)
print(new_prompt)
print('-'*100)
print('tokenizer词表长度:', len(tokenizer))
model_inputs = tokenizer(new_prompt)
print('encoder长度:', len(model_inputs['input_ids']))
response = tokenizer.decode(model_inputs['input_ids'], skip_special_tokens=False)
print('decoder一致性:', response == new_prompt, "\n")
print('-'*100)
print('流式解码(字节缓冲)测试:')
input_ids = model_inputs['input_ids']
token_cache = []
for tid in input_ids:
token_cache.append(tid)
current_decode = tokenizer.decode(token_cache)
if current_decode and '\ufffd' not in current_decode:
display_ids = token_cache[0] if len(token_cache) == 1 else token_cache
raw_tokens = [tokenizer.convert_ids_to_tokens(int(t)) for t in (token_cache if isinstance(token_cache, list) else [token_cache])]
print(f'Token ID: {str(display_ids):15} -> Raw: {str(raw_tokens):20} -> Decode Str: {current_decode}')
token_cache = []
if __name__ == '__main__':
train_tokenizer(DATA_PATH, TOKENIZER_DIR, VOCAB_SIZE)
eval_tokenizer(TOKENIZER_DIR)
================================================
FILE: trainer/trainer_utils.py
================================================
"""
训练工具函数集合
"""
import os
import sys
__package__ = "trainer"
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
import random
import math
import numpy as np
import torch
import torch.distributed as dist
from torch.nn.parallel import DistributedDataParallel
from torch.utils.data import Sampler
from transformers import AutoTokenizer
from model.model_minimind import MiniMindForCausalLM
def get_model_params(model, config):
total = sum(p.numel() for p in model.parameters()) / 1e6
n_routed = getattr(config, 'n_routed_experts', getattr(config, 'num_experts', 0))
n_active = getattr(config, 'num_experts_per_tok', 0)
n_shared = getattr(config, 'n_shared_experts', 0)
expert = sum(p.numel() for n, p in model.named_parameters() if 'mlp.experts.0.' in n) / 1e6
shared_expert = sum(p.numel() for n, p in model.named_parameters() if 'mlp.shared_experts.0.' in n) / 1e6
base = total - (expert * n_routed) - (shared_expert * n_shared)
active = base + (expert * n_active) + (shared_expert * n_shared)
if active < total: Logger(f'Model Params: {total:.2f}M-A{active:.2f}M')
else: Logger(f'Model Params: {total:.2f}M')
def is_main_process():
return not dist.is_initialized() or dist.get_rank() == 0
def Logger(content):
if is_main_process():
print(content)
def get_lr(current_step, total_steps, lr):
return lr*(0.1 + 0.45*(1 + math.cos(math.pi * current_step / total_steps)))
def init_distributed_mode():
if int(os.environ.get("RANK", -1)) == -1:
return 0 # 非DDP模式
dist.init_process_group(backend="nccl")
local_rank = int(os.environ["LOCAL_RANK"])
torch.cuda.set_device(local_rank)
return local_rank
def setup_seed(seed: int):
random.seed(seed)
np.random.seed(seed)
torch.manual_seed(seed)
torch.cuda.manual_seed(seed)
torch.cuda.manual_seed_all(seed)
torch.backends.cudnn.deterministic = True
torch.backends.cudnn.benchmark = False
def lm_checkpoint(lm_config, weight='full_sft', model=None, optimizer=None, epoch=0, step=0, wandb=None, save_dir='../checkpoints', **kwargs):
os.makedirs(save_dir, exist_ok=True)
moe_path = '_moe' if lm_config.use_moe else ''
ckp_path = f'{save_dir}/{weight}_{lm_config.hidden_size}{moe_path}.pth'
resume_path = f'{save_dir}/{weight}_{lm_config.hidden_size}{moe_path}_resume.pth'
if model is not None:
raw_model = model.module if isinstance(model, DistributedDataParallel) else model
raw_model = getattr(raw_model, '_orig_mod', raw_model)
state_dict = raw_model.state_dict()
state_dict = {k: v.half().cpu() for k, v in state_dict.items()}
ckp_tmp = ckp_path + '.tmp'
torch.save(state_dict, ckp_tmp)
os.replace(ckp_tmp, ckp_path)
wandb_id = None
if wandb:
if hasattr(wandb, 'get_run'):
run = wandb.get_run()
wandb_id = getattr(run, 'id', None) if run else None
else:
wandb_id = getattr(wandb, 'id', None)
resume_data = {
'model': state_dict,
'optimizer': optimizer.state_dict(),
'epoch': epoch,
'step': step,
'world_size': dist.get_world_size() if dist.is_initialized() else 1,
'wandb_id': wandb_id
}
for key, value in kwargs.items():
if value is not None:
if hasattr(value, 'state_dict'):
raw_value = value.module if isinstance(value, DistributedDataParallel) else value
raw_value = getattr(raw_value, '_orig_mod', raw_value)
resume_data[key] = raw_value.state_dict()
else:
resume_data[key] = value
resume_tmp = resume_path + '.tmp'
torch.save(resume_data, resume_tmp)
os.replace(resume_tmp, resume_path)
del state_dict, resume_data
torch.cuda.empty_cache()
else: # 加载模式
if os.path.exists(resume_path):
ckp_data = torch.load(resume_path, map_location='cpu')
saved_ws = ckp_data.get('world_size', 1)
current_ws = dist.get_world_size() if dist.is_initialized() else 1
if saved_ws != current_ws:
ckp_data['step'] = ckp_data['step'] * saved_ws // current_ws
Logger(f'GPU数量变化({saved_ws}→{current_ws}),step已自动转换为{ckp_data["step"]}')
return ckp_data
return None
def init_model(lm_config, from_weight='pretrain', tokenizer_path='../model', save_dir='../out', device='cuda'):
tokenizer = AutoTokenizer.from_pretrained(tokenizer_path)
model = MiniMindForCausalLM(lm_config)
if from_weight!= 'none':
moe_suffix = '_moe' if lm_config.use_moe else ''
weight_path = f'{save_dir}/{from_weight}_{lm_config.hidden_size}{moe_suffix}.pth'
weights = torch.load(weight_path, map_location=device)
model.load_state_dict(weights, strict=False)
get_model_params(model, lm_config)
Logger(f'Trainable Params: {sum(p.numel() for p in model.parameters() if p.requires_grad) / 1e6:.3f}M')
return model.to(device), tokenizer
class SkipBatchSampler(Sampler):
def __init__(self, sampler, batch_size, skip_batches=0):
self.sampler = sampler
self.batch_size = batch_size
self.skip_batches = skip_batches
def __iter__(self):
batch = []
skipped = 0
for idx in self.sampler:
batch.append(idx)
if len(batch) == self.batch_size:
if skipped < self.skip_batches:
skipped += 1
batch = []
continue
yield batch
batch = []
if len(batch) > 0 and skipped >= self.skip_batches:
yield batch
def __len__(self):
total_batches = (len(self.sampler) + self.batch_size - 1) // self.batch_size
return max(0, total_batches - self.skip_batches)