silk-road commited on
Commit
1704217
1 Parent(s): 18a3967

Upload folder using huggingface_hub

Browse files
Files changed (10) hide show
  1. .gitignore +160 -0
  2. ChatWorld/ChatWorld.py +84 -0
  3. ChatWorld/NaiveDB.py +85 -0
  4. ChatWorld/__init__.py +1 -0
  5. ChatWorld/models.py +11 -0
  6. ChatWorld/utils.py +9 -0
  7. LICENSE +201 -0
  8. README.md +416 -8
  9. app.py +65 -0
  10. run_gradio.sh +5 -0
.gitignore ADDED
@@ -0,0 +1,160 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+
6
+ # C extensions
7
+ *.so
8
+
9
+ # Distribution / packaging
10
+ .Python
11
+ build/
12
+ develop-eggs/
13
+ dist/
14
+ downloads/
15
+ eggs/
16
+ .eggs/
17
+ lib/
18
+ lib64/
19
+ parts/
20
+ sdist/
21
+ var/
22
+ wheels/
23
+ share/python-wheels/
24
+ *.egg-info/
25
+ .installed.cfg
26
+ *.egg
27
+ MANIFEST
28
+
29
+ # PyInstaller
30
+ # Usually these files are written by a python script from a template
31
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
32
+ *.manifest
33
+ *.spec
34
+
35
+ # Installer logs
36
+ pip-log.txt
37
+ pip-delete-this-directory.txt
38
+
39
+ # Unit test / coverage reports
40
+ htmlcov/
41
+ .tox/
42
+ .nox/
43
+ .coverage
44
+ .coverage.*
45
+ .cache
46
+ nosetests.xml
47
+ coverage.xml
48
+ *.cover
49
+ *.py,cover
50
+ .hypothesis/
51
+ .pytest_cache/
52
+ cover/
53
+
54
+ # Translations
55
+ *.mo
56
+ *.pot
57
+
58
+ # Django stuff:
59
+ *.log
60
+ local_settings.py
61
+ db.sqlite3
62
+ db.sqlite3-journal
63
+
64
+ # Flask stuff:
65
+ instance/
66
+ .webassets-cache
67
+
68
+ # Scrapy stuff:
69
+ .scrapy
70
+
71
+ # Sphinx documentation
72
+ docs/_build/
73
+
74
+ # PyBuilder
75
+ .pybuilder/
76
+ target/
77
+
78
+ # Jupyter Notebook
79
+ .ipynb_checkpoints
80
+
81
+ # IPython
82
+ profile_default/
83
+ ipython_config.py
84
+
85
+ # pyenv
86
+ # For a library or package, you might want to ignore these files since the code is
87
+ # intended to run in multiple environments; otherwise, check them in:
88
+ # .python-version
89
+
90
+ # pipenv
91
+ # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
92
+ # However, in case of collaboration, if having platform-specific dependencies or dependencies
93
+ # having no cross-platform support, pipenv may install dependencies that don't work, or not
94
+ # install all needed dependencies.
95
+ #Pipfile.lock
96
+
97
+ # poetry
98
+ # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
99
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
100
+ # commonly ignored for libraries.
101
+ # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
102
+ #poetry.lock
103
+
104
+ # pdm
105
+ # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
106
+ #pdm.lock
107
+ # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
108
+ # in version control.
109
+ # https://pdm.fming.dev/#use-with-ide
110
+ .pdm.toml
111
+
112
+ # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
113
+ __pypackages__/
114
+
115
+ # Celery stuff
116
+ celerybeat-schedule
117
+ celerybeat.pid
118
+
119
+ # SageMath parsed files
120
+ *.sage.py
121
+
122
+ # Environments
123
+ .env
124
+ .venv
125
+ env/
126
+ venv/
127
+ ENV/
128
+ env.bak/
129
+ venv.bak/
130
+
131
+ # Spyder project settings
132
+ .spyderproject
133
+ .spyproject
134
+
135
+ # Rope project settings
136
+ .ropeproject
137
+
138
+ # mkdocs documentation
139
+ /site
140
+
141
+ # mypy
142
+ .mypy_cache/
143
+ .dmypy.json
144
+ dmypy.json
145
+
146
+ # Pyre type checker
147
+ .pyre/
148
+
149
+ # pytype static type analyzer
150
+ .pytype/
151
+
152
+ # Cython debug symbols
153
+ cython_debug/
154
+
155
+ # PyCharm
156
+ # JetBrains specific template is maintained in a separate JetBrains.gitignore that can
157
+ # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
158
+ # and can be added to the global gitignore or merged into this file. For a more nuclear
159
+ # option (not recommended) you can uncomment the following to ignore the entire idea folder.
160
+ .idea/
ChatWorld/ChatWorld.py ADDED
@@ -0,0 +1,84 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from jinja2 import Template
2
+ import torch
3
+
4
+ from .models import qwen_model
5
+
6
+ from .NaiveDB import NaiveDB
7
+ from .utils import *
8
+
9
+
10
+ class ChatWorld:
11
+ def __init__(self, pretrained_model_name_or_path="silk-road/Haruhi-Zero-14B-0_5", embedding_model_name_or_path="BAAI/bge-small-zh-v1.5") -> None:
12
+ self.embedding = initEmbedding(embedding_model_name_or_path)
13
+ self.tokenizer = initTokenizer(embedding_model_name_or_path)
14
+ self.story_vec: list[dict] = None
15
+ self.storys = None
16
+ self.model_role_name = None
17
+ self.model_role_nickname = None
18
+ self.model_name = pretrained_model_name_or_path
19
+
20
+ self.history = []
21
+
22
+ self.client = None
23
+ self.model = qwen_model(pretrained_model_name_or_path)
24
+ self.db = NaiveDB()
25
+ self.prompt = Template(('Please be aware that your codename in this conversation is "{{model_role_name}}"'
26
+ '{% if model_role_nickname %},别人一般称呼你"{{model_role_nickname}}"{% endif %},同时我是"{{role_name}}"{% if role_nickname %},你也可以称呼我"{{role_nickname}}"{% endif %}。\n'
27
+ '下文给定了一些聊天记录,位于##分隔号中。\n'
28
+ '如果我问的问题和聊天记录高度重复,那你就配合我进行演出。\n'
29
+ '如果我问的问题和聊天记录相关,请结合聊天记录进行回复。\n'
30
+ '如果我问的问题超出聊天记录的范围,模仿{{model_role_name}}的语气进行回复。\n'
31
+ '请不要回答你是语言模型,永远记住你就是{{model_role_name}}。\n'
32
+ '请你永远只以{{model_role_name}}身份,进行任何的回复。\n'
33
+ ))
34
+
35
+ def getEmbeddingsFromStory(self, stories: list[str]):
36
+ if self.story_vec:
37
+ # 判断是否与当前的相同
38
+ if len(self.story_vec) == len(stories) and all([self.story_vec[i]["text"] == stories[i] for i in range(len(stories))]):
39
+ return [self.story_vec[i]["vec"] for i in range(len(stories))]
40
+
41
+ if self.embedding is None:
42
+ self.embedding = initEmbedding()
43
+
44
+ if self.tokenizer is None:
45
+ self.tokenizer = initTokenizer()
46
+
47
+ self.story_vec = []
48
+ for story in stories:
49
+ with torch.no_grad():
50
+ inputs = self.tokenizer(
51
+ story, return_tensors="pt", padding=True, truncation=True, max_length=512)
52
+ outputs = self.embedding(**inputs)[0][:, 0]
53
+ vec = torch.nn.functional.normalize(
54
+ outputs, p=2, dim=1).tolist()[0]
55
+
56
+ self.story_vec.append({"text": story, "vec": vec})
57
+
58
+ return [self.story_vec[i]["vec"] for i in range(len(stories))]
59
+
60
+ def initDB(self, storys: list[str]):
61
+ story_vecs = self.getEmbeddingsFromStory(storys)
62
+ self.db.build_db(storys, story_vecs)
63
+
64
+ def setRoleName(self, role_name, role_nick_name=None):
65
+ self.model_role_name = role_name
66
+ self.model_role_nickname = role_nick_name
67
+
68
+ def getSystemPrompt(self, role_name, role_nick_name):
69
+ assert self.model_role_name and self.model_role_nickname, "Please set model role name first"
70
+ return self.prompt.render(model_role_name=self.model_role_name, model_role_nickname=self.model_role_nickname, role_name=role_name, role_nickname=role_nick_name)
71
+
72
+ def chat(self, user_role_name: str, text: str, user_role_nick_name: str = None, use_local_model=False):
73
+ message = [self.getSystemPrompt(
74
+ user_role_name, user_role_nick_name)] + self.history
75
+
76
+ if use_local_model:
77
+ response = self.model.get_response(message)
78
+ else:
79
+ response = self.client.chat(
80
+ user_role_name, text, user_role_nick_name)
81
+
82
+ self.history.append({"role": "user", "content": text})
83
+ self.history.append({"role": "model", "content": response})
84
+ return response
ChatWorld/NaiveDB.py ADDED
@@ -0,0 +1,85 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import random
2
+ from math import sqrt
3
+
4
+
5
+ class NaiveDB:
6
+ def __init__(self):
7
+ self.verbose = False
8
+ self.init_db()
9
+
10
+ def init_db(self):
11
+ if self.verbose:
12
+ print("call init_db")
13
+ self.stories = []
14
+ self.norms = []
15
+ self.vecs = []
16
+ self.flags = [] # 用于标记每个story是否可以被搜索
17
+ self.metas = [] # 用于存储每个story的meta信息
18
+ self.last_search_ids = [] # 用于存储上一次搜索的结果
19
+
20
+ def build_db(self, stories, vecs, flags=None, metas=None):
21
+ self.stories = stories
22
+ self.vecs = vecs
23
+ self.flags = flags if flags else [True for _ in self.stories]
24
+ self.metas = metas if metas else [{} for _ in self.stories]
25
+ self.recompute_norm()
26
+
27
+ def save(self, file_path):
28
+ print(
29
+ "warning! directly save folder from dbtype NaiveDB has not been implemented yet, try use role_from_hf to load role instead")
30
+
31
+ def load(self, file_path):
32
+ print(
33
+ "warning! directly load folder from dbtype NaiveDB has not been implemented yet, try use role_from_hf to load role instead")
34
+
35
+ def recompute_norm(self):
36
+ # 补全这部分代码,self.norms 分别存储每个vector的l2 norm
37
+ # 计算每个向量的L2范数
38
+ self.norms = [sqrt(sum([x ** 2 for x in vec])) for vec in self.vecs]
39
+
40
+ def get_stories_with_id(self, ids):
41
+ return [self.stories[i] for i in ids]
42
+
43
+ def clean_flag(self):
44
+ self.flags = [True for _ in self.stories]
45
+
46
+ def disable_story_with_ids(self, close_ids):
47
+ for id in close_ids:
48
+ self.flags[id] = False
49
+
50
+ def close_last_search(self):
51
+ for id in self.last_search_ids:
52
+ self.flags[id] = False
53
+
54
+ def search(self, query_vector, n_results):
55
+
56
+ if self.verbose:
57
+ print("call search")
58
+
59
+ if len(self.norms) != len(self.vecs):
60
+ self.recompute_norm()
61
+
62
+ # 计算查询向量的范数
63
+ query_norm = sqrt(sum([x ** 2 for x in query_vector]))
64
+
65
+ idxs = list(range(len(self.vecs)))
66
+
67
+ # 计算余弦相似度
68
+ similarities = []
69
+ for vec, norm, idx in zip(self.vecs, self.norms, idxs):
70
+ if len(self.flags) == len(self.vecs) and not self.flags[idx]:
71
+ continue
72
+
73
+ dot_product = sum(q * v for q, v in zip(query_vector, vec))
74
+ if query_norm < 1e-20:
75
+ similarities.append((random.random(), idx))
76
+ continue
77
+ cosine_similarity = dot_product / (query_norm * norm)
78
+ similarities.append((cosine_similarity, idx))
79
+
80
+ # 获取最相似的n_results个结果, 使用第0个字段进行排序
81
+ similarities.sort(key=lambda x: x[0], reverse=True)
82
+ self.last_search_ids = [x[1] for x in similarities[:n_results]]
83
+
84
+ top_indices = [x[1] for x in similarities[:n_results]]
85
+ return top_indices
ChatWorld/__init__.py ADDED
@@ -0,0 +1 @@
 
 
1
+ from .ChatWorld import ChatWorld
ChatWorld/models.py ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from transformers import AutoTokenizer, AutoModelForCausalLM
2
+
3
+
4
+ class qwen_model:
5
+ def __init__(self, model_name):
6
+ self.tokenizer = AutoTokenizer.from_pretrained(model_name, trust_remote_code=True)
7
+ self.model = AutoModelForCausalLM.from_pretrained(model_name, device_map="auto", trust_remote_code=True).eval()
8
+
9
+ def get_response(self, message):
10
+ self.tokenizer.apply_chat_template(message, tokenize=False, add_generation_prompt=True)
11
+ return "test"
ChatWorld/utils.py ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ from transformers import AutoModel, AutoTokenizer
2
+
3
+
4
+ def initEmbedding(model_name="BAAI/bge-small-zh-v1.5", **model_wargs):
5
+ return AutoModel.from_pretrained(model_name, **model_wargs)
6
+
7
+
8
+ def initTokenizer(model_name="BAAI/bge-small-zh-v1.5", **model_wargs):
9
+ return AutoTokenizer.from_pretrained(model_name)
LICENSE ADDED
@@ -0,0 +1,201 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Apache License
2
+ Version 2.0, January 2004
3
+ http://www.apache.org/licenses/
4
+
5
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
+
7
+ 1. Definitions.
8
+
9
+ "License" shall mean the terms and conditions for use, reproduction,
10
+ and distribution as defined by Sections 1 through 9 of this document.
11
+
12
+ "Licensor" shall mean the copyright owner or entity authorized by
13
+ the copyright owner that is granting the License.
14
+
15
+ "Legal Entity" shall mean the union of the acting entity and all
16
+ other entities that control, are controlled by, or are under common
17
+ control with that entity. For the purposes of this definition,
18
+ "control" means (i) the power, direct or indirect, to cause the
19
+ direction or management of such entity, whether by contract or
20
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
21
+ outstanding shares, or (iii) beneficial ownership of such entity.
22
+
23
+ "You" (or "Your") shall mean an individual or Legal Entity
24
+ exercising permissions granted by this License.
25
+
26
+ "Source" form shall mean the preferred form for making modifications,
27
+ including but not limited to software source code, documentation
28
+ source, and configuration files.
29
+
30
+ "Object" form shall mean any form resulting from mechanical
31
+ transformation or translation of a Source form, including but
32
+ not limited to compiled object code, generated documentation,
33
+ and conversions to other media types.
34
+
35
+ "Work" shall mean the work of authorship, whether in Source or
36
+ Object form, made available under the License, as indicated by a
37
+ copyright notice that is included in or attached to the work
38
+ (an example is provided in the Appendix below).
39
+
40
+ "Derivative Works" shall mean any work, whether in Source or Object
41
+ form, that is based on (or derived from) the Work and for which the
42
+ editorial revisions, annotations, elaborations, or other modifications
43
+ represent, as a whole, an original work of authorship. For the purposes
44
+ of this License, Derivative Works shall not include works that remain
45
+ separable from, or merely link (or bind by name) to the interfaces of,
46
+ the Work and Derivative Works thereof.
47
+
48
+ "Contribution" shall mean any work of authorship, including
49
+ the original version of the Work and any modifications or additions
50
+ to that Work or Derivative Works thereof, that is intentionally
51
+ submitted to Licensor for inclusion in the Work by the copyright owner
52
+ or by an individual or Legal Entity authorized to submit on behalf of
53
+ the copyright owner. For the purposes of this definition, "submitted"
54
+ means any form of electronic, verbal, or written communication sent
55
+ to the Licensor or its representatives, including but not limited to
56
+ communication on electronic mailing lists, source code control systems,
57
+ and issue tracking systems that are managed by, or on behalf of, the
58
+ Licensor for the purpose of discussing and improving the Work, but
59
+ excluding communication that is conspicuously marked or otherwise
60
+ designated in writing by the copyright owner as "Not a Contribution."
61
+
62
+ "Contributor" shall mean Licensor and any individual or Legal Entity
63
+ on behalf of whom a Contribution has been received by Licensor and
64
+ subsequently incorporated within the Work.
65
+
66
+ 2. Grant of Copyright License. Subject to the terms and conditions of
67
+ this License, each Contributor hereby grants to You a perpetual,
68
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69
+ copyright license to reproduce, prepare Derivative Works of,
70
+ publicly display, publicly perform, sublicense, and distribute the
71
+ Work and such Derivative Works in Source or Object form.
72
+
73
+ 3. Grant of Patent License. Subject to the terms and conditions of
74
+ this License, each Contributor hereby grants to You a perpetual,
75
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76
+ (except as stated in this section) patent license to make, have made,
77
+ use, offer to sell, sell, import, and otherwise transfer the Work,
78
+ where such license applies only to those patent claims licensable
79
+ by such Contributor that are necessarily infringed by their
80
+ Contribution(s) alone or by combination of their Contribution(s)
81
+ with the Work to which such Contribution(s) was submitted. If You
82
+ institute patent litigation against any entity (including a
83
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
84
+ or a Contribution incorporated within the Work constitutes direct
85
+ or contributory patent infringement, then any patent licenses
86
+ granted to You under this License for that Work shall terminate
87
+ as of the date such litigation is filed.
88
+
89
+ 4. Redistribution. You may reproduce and distribute copies of the
90
+ Work or Derivative Works thereof in any medium, with or without
91
+ modifications, and in Source or Object form, provided that You
92
+ meet the following conditions:
93
+
94
+ (a) You must give any other recipients of the Work or
95
+ Derivative Works a copy of this License; and
96
+
97
+ (b) You must cause any modified files to carry prominent notices
98
+ stating that You changed the files; and
99
+
100
+ (c) You must retain, in the Source form of any Derivative Works
101
+ that You distribute, all copyright, patent, trademark, and
102
+ attribution notices from the Source form of the Work,
103
+ excluding those notices that do not pertain to any part of
104
+ the Derivative Works; and
105
+
106
+ (d) If the Work includes a "NOTICE" text file as part of its
107
+ distribution, then any Derivative Works that You distribute must
108
+ include a readable copy of the attribution notices contained
109
+ within such NOTICE file, excluding those notices that do not
110
+ pertain to any part of the Derivative Works, in at least one
111
+ of the following places: within a NOTICE text file distributed
112
+ as part of the Derivative Works; within the Source form or
113
+ documentation, if provided along with the Derivative Works; or,
114
+ within a display generated by the Derivative Works, if and
115
+ wherever such third-party notices normally appear. The contents
116
+ of the NOTICE file are for informational purposes only and
117
+ do not modify the License. You may add Your own attribution
118
+ notices within Derivative Works that You distribute, alongside
119
+ or as an addendum to the NOTICE text from the Work, provided
120
+ that such additional attribution notices cannot be construed
121
+ as modifying the License.
122
+
123
+ You may add Your own copyright statement to Your modifications and
124
+ may provide additional or different license terms and conditions
125
+ for use, reproduction, or distribution of Your modifications, or
126
+ for any such Derivative Works as a whole, provided Your use,
127
+ reproduction, and distribution of the Work otherwise complies with
128
+ the conditions stated in this License.
129
+
130
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
131
+ any Contribution intentionally submitted for inclusion in the Work
132
+ by You to the Licensor shall be under the terms and conditions of
133
+ this License, without any additional terms or conditions.
134
+ Notwithstanding the above, nothing herein shall supersede or modify
135
+ the terms of any separate license agreement you may have executed
136
+ with Licensor regarding such Contributions.
137
+
138
+ 6. Trademarks. This License does not grant permission to use the trade
139
+ names, trademarks, service marks, or product names of the Licensor,
140
+ except as required for reasonable and customary use in describing the
141
+ origin of the Work and reproducing the content of the NOTICE file.
142
+
143
+ 7. Disclaimer of Warranty. Unless required by applicable law or
144
+ agreed to in writing, Licensor provides the Work (and each
145
+ Contributor provides its Contributions) on an "AS IS" BASIS,
146
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147
+ implied, including, without limitation, any warranties or conditions
148
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149
+ PARTICULAR PURPOSE. You are solely responsible for determining the
150
+ appropriateness of using or redistributing the Work and assume any
151
+ risks associated with Your exercise of permissions under this License.
152
+
153
+ 8. Limitation of Liability. In no event and under no legal theory,
154
+ whether in tort (including negligence), contract, or otherwise,
155
+ unless required by applicable law (such as deliberate and grossly
156
+ negligent acts) or agreed to in writing, shall any Contributor be
157
+ liable to You for damages, including any direct, indirect, special,
158
+ incidental, or consequential damages of any character arising as a
159
+ result of this License or out of the use or inability to use the
160
+ Work (including but not limited to damages for loss of goodwill,
161
+ work stoppage, computer failure or malfunction, or any and all
162
+ other commercial damages or losses), even if such Contributor
163
+ has been advised of the possibility of such damages.
164
+
165
+ 9. Accepting Warranty or Additional Liability. While redistributing
166
+ the Work or Derivative Works thereof, You may choose to offer,
167
+ and charge a fee for, acceptance of support, warranty, indemnity,
168
+ or other liability obligations and/or rights consistent with this
169
+ License. However, in accepting such obligations, You may act only
170
+ on Your own behalf and on Your sole responsibility, not on behalf
171
+ of any other Contributor, and only if You agree to indemnify,
172
+ defend, and hold each Contributor harmless for any liability
173
+ incurred by, or claims asserted against, such Contributor by reason
174
+ of your accepting any such warranty or additional liability.
175
+
176
+ END OF TERMS AND CONDITIONS
177
+
178
+ APPENDIX: How to apply the Apache License to your work.
179
+
180
+ To apply the Apache License to your work, attach the following
181
+ boilerplate notice, with the fields enclosed by brackets "[]"
182
+ replaced with your own identifying information. (Don't include
183
+ the brackets!) The text should be enclosed in the appropriate
184
+ comment syntax for the file format. We also recommend that a
185
+ file or class name and description of purpose be included on the
186
+ same "printed page" as the copyright notice for easier
187
+ identification within third-party archives.
188
+
189
+ Copyright [yyyy] [name of copyright owner]
190
+
191
+ Licensed under the Apache License, Version 2.0 (the "License");
192
+ you may not use this file except in compliance with the License.
193
+ You may obtain a copy of the License at
194
+
195
+ http://www.apache.org/licenses/LICENSE-2.0
196
+
197
+ Unless required by applicable law or agreed to in writing, software
198
+ distributed under the License is distributed on an "AS IS" BASIS,
199
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200
+ See the License for the specific language governing permissions and
201
+ limitations under the License.
README.md CHANGED
@@ -1,12 +1,420 @@
1
  ---
2
- title: Zero Haruhi
3
- emoji: 📊
4
- colorFrom: purple
5
- colorTo: pink
6
- sdk: gradio
7
- sdk_version: 4.19.2
8
  app_file: app.py
9
- pinned: false
 
10
  ---
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11
 
12
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
1
  ---
2
+ title: Zero-Haruhi
 
 
 
 
 
3
  app_file: app.py
4
+ sdk: gradio
5
+ sdk_version: 3.50.2
6
  ---
7
+ # Chat凉宫春日 Chat-Haruhi-Suzumiya
8
+ ## Reviving Anime Character in Reality via Large Language Model
9
+
10
+ **Chat凉宫春日**是模仿凉宫春日等一系列动漫人物,使用近似语气、个性和剧情聊天的语言模型方案。
11
+
12
+ 随着[**凉宫春日-Zero**](https://github.com/LC1332/Zero-Haruhi)模型的建立,Chat凉宫春日项目将主要包含三个部分,
13
+
14
+ - 可以接入不同语言模型,包括闭源商用API和Haruhi-Zero模型的推理class,用于管理人物的记忆库和过往的历史信息并进行prompt的构造。
15
+ - 使用120k左右量级对话数据得到的开源角色扮演模型,凉宫春日-Zero,方便每个开发者构建自己的人物模型
16
+ - 完整的小说抽取方案,以及一个开源可本地部署的对话-动作抽取模型。
17
+
18
+
19
+ <p align="center">
20
+ <img src="https://github.com/LC1332/Chat-Haruhi-Suzumiya/blob/main/figures/datasetOverview.png">
21
+ </p>
22
+
23
+ <details>
24
+ <summary> (TBD) Chat凉宫春日的3.0版本和HaruhiZero模型由李鲁鲁, 豆角, 刘崇寒, 米唯实, BPSK, JiangYH等开发 </summary>
25
+
26
+ 开发人员持续增加中
27
+
28
+ </details>
29
+
30
+ <details>
31
+ <summary> Chat凉宫春日的2.0版本由李鲁鲁, 冷子昂, 闫晨曦, 封小洋, scixing, 沈骏一, Aria Fei, 王皓, 米唯实, 冷月, JunityZhan, 贾曜恺, 吴平宇, 孙浩甄等开发。 </summary>
32
+
33
+ 本项目是一个开源项目,项目成员均在DataWhale等开源社区招募。
34
+
35
+ 李鲁鲁( [Cheng Li@SenseTime](https://github.com/LC1332) )发起了整个项目,并设计和实现了项目的大多数功能。
36
+
37
+ 冷子昂( [Ziang Leng@SenseTime](https://blairleng.github.io) )设计和实现了整体的ChatHaruhi1.0的训练,数据生成和后端架构。
38
+
39
+ 闫晨曦( [Chenxi Yan@Chengdu University of Information Technology](https://github.com/todochenxi) )实现和维护了ChatHaruhi1.0版本的后端。
40
+
41
+ 沈骏一( [Junyi Shen@Zhejiang University](https://github.com/J1shen) )实现了训练代码,参与了训练数据集生成。
42
+
43
+ 王皓( [Hao Wang](https://github.com/wanghao07456) )收集了武林外传的台本数据,参与了增广数据的生成。
44
+
45
+ 米唯实( [Weishi MI@Tsinghua University](https://github.com/hhhwmws0117) )参与了增广数据生成。
46
+
47
+ Yaying Fei( [Aria Fei@Beijing University of Technology](https://ariafyy.github.io/) )实现了台本工具 ASR 功能,参与了Openness-Aware Personality paper分支项目。
48
+
49
+ 封小洋( [Xiaoyang Feng@Nanjing Agricultural University](https://github.com/fengyunzaidushi) )整合了台本识别工具功能,参与了Openness-Aware Personality paper分支项目。
50
+
51
+ 冷月( [Song Yan](https://github.com/zealot52099) )收集了big bang thoery的数据。实现了台本格式转换功能。
52
+
53
+ scixing(汪好盛)( [HaoSheng Wang](https://github.com/ssccinng) )实现了台本工具中声纹识别功能,以及tts-vits语音合成功能。
54
+
55
+ Linkang Zhan( [JunityZhan@Case Western Reserve University](https://github.com/JunityZhan) ) 收集了原神的system prompt和故事数据。
56
+
57
+ 贾曜恺( [Yaokai Jia](https://github.com/KaiJiaBrother) )实现了Vue版本的前端,并且在心理项目中实践了Bert的GPU抽取。
58
+
59
+ 吴平宇( [Pingyu Wu@Juncai Shuyun](https://github.com/wpydcr) )帮助部署了第一版本的训练代码。
60
+
61
+ 孙浩甄( [Haozhen Sun@Tianjin University] )绘制了ChatHaruhi角色的拼图。
62
+
63
+ </details>
64
+
65
+
66
+ # TODO
67
+
68
+ 近期TODO 0215
69
+
70
+ - Haruhi-Zero 0.5 的数据收集
71
+ - 0.4已经收集,50本小说,每本10个人物
72
+ - 每个人根据语料,进一步总结profile,验证profile的有效性,产生0.5的数据 ( @ 鲁叔)
73
+ - Haruhi-Zero 0.4 训练各个size的模型并上传到hf
74
+ - 14B qwen已经上传 (@BPSK)
75
+ - 1.8B还是需要的哈, JiangYH说要训练一个ChatGLM-6B的 (@BPSK @JiangYH)
76
+ - 上传7B抽取模型 (@BPSK)
77
+ - ChatHaruhi3.0接口
78
+ - 初步openai和GLM已经完成
79
+ - Le geant 去尝试搭建一些gradio 放到hf上面常驻 (@Le geant )
80
+ - 其他api ( @ mws )
81
+ - 写模型的Readme( @ 鲁叔)
82
+ - Haruhi-Zero模型需要接入到oobabooga textUI ( @ JiangYH )
83
+ - Evaluation
84
+ - 先和xintao讨论下咋搞
85
+ - 阅读Silly Tavern代码,看看哪里方便接入记忆库 ( @ 多人 )
86
+ - PIPPA数据翻译
87
+ - 有初步翻译的版本(未check) check后加入0.5训练集
88
+ - 角色分享网站
89
+ - ?@Sibo
90
+
91
+ # ChatHaruhi 3.0 的说明
92
+
93
+ ChatHaruhi 3.0是Chat凉宫春日的推理库
94
+
95
+ - 支持使用或者不使用RAG的角色的载入
96
+ - 支持直接载入sugar角色,或者从hugging face载入预先设定好的角色
97
+ - 支持用户自建角色
98
+ - 在ChatHaruhi 2.0的基础上做了message和llm的分离,方便接入不同的模型
99
+
100
+ ## 快速开始
101
+
102
+ 目前ChatHaruhi的库本身只需要install datasets和tiktoken。另外你需要准备和你对应希望使用的llm所依赖的库,以openai为例的话需要安装openai��库。
103
+
104
+ 对于ChatHaruhi默认支持的角色,你可以直接使用sugar载入
105
+
106
+ ```python
107
+ from ChatHaruhi import ChatHaruhi
108
+ from ChatHaruhi.openai import get_openai_response
109
+
110
+ chatbot = ChatHaruhi( role_name = 'haruhi', llm = get_openai_response )
111
+ chatbot.add_rag_prompt_after_persona()
112
+
113
+ response = chatbot.chat(user = '阿虚', text = '我看新一年的棒球比赛要开始了!我们要去参加吗?')
114
+ ```
115
+
116
+ 对于更完整的载入方式,需要设置persona, role_name和stories
117
+
118
+ ```python
119
+ from ChatHaruhi import ChatHaruhi
120
+ from ChatHaruhi.openai import get_openai_response
121
+
122
+ persona = """每当用户问询一个家庭关系,输出一个相关的家庭关系的逻辑句子
123
+
124
+ {{RAG对话}}
125
+ {{RAG对话}}
126
+ """
127
+
128
+ role_name = "家庭关系机器人"
129
+
130
+ stories = ["{{user}}:爷爷 {{role}}:爸爸的爸爸是爷爷",
131
+ "{{user}}:奶奶 {{role}}:爸爸的妈妈是奶奶",
132
+ "{{user}}:外公 {{role}}:妈妈的爸爸是外公",
133
+ "{{user}}:外婆 {{role}}:妈妈的妈妈是外婆"]
134
+
135
+ chatbot = ChatHaruhi( role_name = role_name, persona = persona, llm = get_response ,\
136
+ llm = get_openai_response )
137
+ # 因为persona已经带了"{{RAG对话}}",不需要额外运行add_rag_prompt_after_persona()
138
+
139
+ response = chatbot.chat(user = '', text = '表姐?')
140
+ ```
141
+
142
+ 当然,建立角色记忆库对于一般的用户来说是比较困难的,所以自Haruhi-Zero模型之后,我们也支持用户创建不使用记忆库的角色
143
+
144
+ ```python
145
+ from ChatHaruhi import ChatHaruhi
146
+ from ChatHaruhi.openai import get_openai_response
147
+
148
+ role_name = "布莱恩"
149
+ persona = "你扮演 德州杀场 中的 布莱恩 布莱恩是一个专注、果断、有责任感的警探,他在调查案件时非常注重细节,对案件的解决充满使命感。 布莱恩是一个专注、果断、有责任感的警探 布莱恩是一个身材魁梧、严肃的警探 这是一个警探调查案件的场景,布莱恩与其他警员合作调查案件"
150
+
151
+ chatbot = ChatHaruhi( role_name = role_name, persona = persona, llm = get_openai_response )
152
+ ```
153
+
154
+ 更多载入方式见文档后面的部分
155
+
156
+ ## 使用不同的模型进行inference
157
+
158
+ 直接从对应的response_XX.py中载入对应的response函数即可
159
+
160
+ ### openai
161
+
162
+ ```python
163
+ from ChatHaruhi.openai import get_openai_response
164
+ ```
165
+
166
+ 需要设置环境变量
167
+
168
+ ```python
169
+ import os
170
+ os.environ["OPENAI_API_KEY"] = "your_api_key"
171
+ # 如果你使用中转站
172
+ os.environ["OPENAI_API_BASE"] = "中转站网址"
173
+ ```
174
+
175
+ ### Zhipu AI
176
+
177
+ 需要安装zhipuai的库,需要设置环境变量
178
+
179
+ ```python
180
+ import os
181
+ os.environ["ZHIPUAI_API_KEY"] = "your_api_key"
182
+
183
+ from ChatHaruhi.zhipuai import get_zhipuai_response
184
+ ```
185
+
186
+ ### 百度文心
187
+
188
+ 需要安装文心erniebot的库,需要设置环境变量ERNIE_ACCESS_TOKEN
189
+
190
+ ```python
191
+ import os
192
+ os.environ["ERNIE_ACCESS_TOKEN"] = ""
193
+
194
+ from ChatHaruhi.erniebot import get_erniebot_response
195
+ ```
196
+
197
+ ### Haruhi-Zero的本地模型
198
+
199
+ TODO: 这块儿我回头补一下文档
200
+
201
+ ## 使用不同的角色载入方式
202
+
203
+
204
+
205
+ ### persona, role_name以及stories的载入
206
+
207
+ ```python
208
+ from ChatHaruhi import ChatHaruhi
209
+ from ChatHaruhi.openai import get_openai_response
210
+
211
+ persona = """每当用户问询一个家庭关系,输出一个相关的家庭关系的逻辑句子
212
+
213
+ {{RAG对话}}
214
+ {{RAG对话}}
215
+ """
216
+
217
+ role_name = "家庭关系机器人"
218
+
219
+ stories = ["{{user}}:爷爷 {{role}}:爸爸的爸爸是爷爷",
220
+ "{{user}}:奶奶 {{role}}:爸爸的妈妈是奶奶",
221
+ "{{user}}:外公 {{role}}:妈妈的爸爸是外公",
222
+ "{{user}}:外婆 {{role}}:妈妈的妈妈是外婆"]
223
+
224
+ chatbot = ChatHaruhi( role_name = role_name, persona = persona, llm = get_response ,\
225
+ llm = get_openai_response )
226
+ # 因为persona已经带了"{{RAG对话}}",不需要额外运行add_rag_prompt_after_persona()
227
+
228
+ response = chatbot.chat(user = '', text = '表姐?')
229
+ ```
230
+
231
+ 这个时候chatbot会使用chatbot.embedding来进行story的vec的计算,对于bge模型,使用了batch_size = 16进行批量抽取,GPU下速度非常快。为建议的使用方式。
232
+
233
+ ### 最完整的载入
234
+
235
+ 这里需要载入完整的persona, role_name, stories以及和chatbot.embedding所对应的每个story的vecs
236
+
237
+ 如果vecs的维度和模型的维度不一样,在使用的时候会报错
238
+
239
+ ```python
240
+ persona = "你扮演爸爸\n\n{{RAG对话}}\n"
241
+ role_name = "爸爸"
242
+ stories = ["爸爸的爸爸是爷爷", "爸爸的妈妈是奶奶"]
243
+ vecs = [[0.0,1.0,...],[1.0,0.0,...]]
244
+
245
+ chatbot = ChatHaruhi( role_name = role_name, persona = persona, llm = get_response ,\
246
+ stories = stories, story_vecs = vecs)
247
+ ```
248
+
249
+ ### sugar载入
250
+
251
+ sugar载入是最简单的载入方式,只需要载入role_name即可,
252
+
253
+ 在载入之后需要调用chatbot.add_rag_prompt_after_persona()来添加RAG的prompt
254
+
255
+ ```python
256
+ from ChatHaruhi import ChatHaruhi
257
+ from ChatHaruhi.openai import get_openai_response
258
+
259
+ chatbot = ChatHaruhi( role_name = 'haruhi', llm = get_openai_response )
260
+ chatbot.add_rag_prompt_after_persona()
261
+ ```
262
+
263
+ 目前支持这些角色的sugar载入
264
+
265
+ ```python
266
+ enname2zhname = {'tangshiye': '汤师爷', 'murongfu': '慕容复', 'liyunlong': '李云龙', 'Luna': 'Luna', 'wangduoyu': '王多鱼', 'Ron': 'Ron', 'jiumozhi': '鸠摩智', 'Snape': 'Snape', 'haruhi': '凉宫春日', 'Malfoy': 'Malfoy', 'xuzhu': '虚竹', 'xiaofeng': '萧峰', 'duanyu': '段誉', 'Hermione': 'Hermione', 'Dumbledore': 'Dumbledore', 'wangyuyan': '王语嫣', 'Harry': 'Harry', 'McGonagall': 'McGonagall', 'baizhantang': '白展堂', 'tongxiangyu': '佟湘玉', 'guofurong': '郭芙蓉', 'wanderer': '流浪者', 'zhongli': '钟离', 'hutao': '胡桃', 'Sheldon': 'Sheldon', 'Raj': 'Raj', 'Penny': 'Penny', 'weixiaobao': '韦小宝', 'qiaofeng': '乔峰', 'ayaka': '神里绫华', 'raidenShogun': '雷电将军', 'yuqian': '于谦'}
267
+ ```
268
+
269
+ # 资源汇总(临时)
270
+
271
+ - 0.3 模型(7B) https://huggingface.co/silk-road/Haruhi-Zero-7B-0_3
272
+ - 0.4 模型(14B)https://huggingface.co/silk-road/Haruhi-Zero-14B-0_4
273
+ - 抽取模型 https://huggingface.co/silk-road/Haruhi-dialogue-action-extract-7B
274
+ - 0.4 50本小说的500个人物 https://huggingface.co/datasets/silk-road/50-Chinese-Novel-Characters
275
+
276
+ ---
277
+
278
+ # 凉宫春日-Zero
279
+ # Haruhi-Zero: Zero-Shot Role-Playing Model
280
+
281
+ **凉宫春日-Zero**是一个同时支持Zero-Shot角色构造和RAG角色构造(原ChatHaruhi)的角色扮演模型
282
+
283
+ 本项目是[**Chat-凉宫春日**](https://github.com/LC1332/Chat-Haruhi-Suzumiya)的子项目,在ChatHaruhi 3.0完成之后,会合并回主项目
284
+
285
+ <p align="center">
286
+ <img src="https://github.com/LC1332/Chat-Haruhi-Suzumiya/blob/main/figures/datasetOverview.png">
287
+ </p>
288
+
289
+ ## Introduction
290
+
291
+ 过往的ChatHaruhi模型需要角色库来完成角色的构建,而Pygmalion,CharacterGLM,CharacterBaichuan等开源/闭源模型都开始支持zero-shot的角色卡片创建。目前,从[Haruhi-Zero-0.3](https://huggingface.co/silk-road/Haruhi-Zero-7B-0_3)开始,已经基本支持Zero-shot角色扮演。
292
+
293
+ 项目的目标
294
+
295
+ - [x] 一个通用的,同时支持Zero-shot和RAG角色构造的角色扮演模型
296
+ - [x] ChatHaruhi 3.0的inference class,能够将角色卡片等形式转化为message,再对接Haruhi-Zero模型或者api进行inference
297
+ - [ ] 支持原来Haruhi的角色卡片,以及30本新小说的抽取的角色,使用中英文通用的embedding,相比于pygmalion模型,增加动态rag的角色卡片
298
+ - [ ] Haruhi-Zero的模型接入Silly Travern生态
299
+ - [ ] 训练各个尺寸的模型,并且进行合适的量化,使得一些免费的云服务机以及本地显卡可以进行运行
300
+ - [ ] 完成一个tech report并发布在arxiv
301
+ - [ ] 一个卡片分享的网站,以及支持用户上传小说进行角色记忆库的抽取
302
+
303
+ ## 基础使用
304
+
305
+ 模型初始化
306
+
307
+ ```python
308
+ from transformers import AutoTokenizer, AutoModel, AutoModelForCausalLM
309
+ tokenizer = AutoTokenizer.from_pretrained("silk-road/Haruhi-Zero-7B-0_3", trust_remote_code=True)
310
+ model = AutoModelForCausalLM.from_pretrained("silk-road/Haruhi-Zero-7B-0_3", device_map="auto", trust_remote_code=True, fp16=True)
311
+ model = model.eval()
312
+ ```
313
+
314
+ Official Prompt
315
+
316
+ ```python
317
+ role_name = "布莱恩"
318
+ persona = "你扮演 德州杀场 中的 布莱恩 布莱恩是一个专注、果断、有责任感的警探,他在调查案件时非常注重细节,对案件的解决充满使命感。 布莱恩是一个专注、果断、有责任感的警探 布莱恩是一个身材魁梧、严肃的警探 这是一个警探调查案件的场景,布莱恩与其他警员合作调查案件"
319
+ system_prompt = f"You are now in roleplay conversation mode. Pretend to be {role_name} whose persona follows: {persona} You will stay in-character whenever possible, and generate responses as if you were {role_name}"
320
+ ```
321
+
322
+ 模型调用
323
+
324
+ ```python
325
+ response, history = model.chat(tokenizer, first_round_string, history=[],system = system_prompt)
326
+ print(response)
327
+ ```
328
+
329
+ 这样就可以进行简单的模型角色扮演了。
330
+
331
+ 我们提供了一个基础的gradio来进行角色扮演。[Gradio Demo链接](https://github.com/LC1332/Zero-Haruhi/blob/main/notebook/HaruhiZeroGradio_Qwen.ipynb)
332
+
333
+ ## 基础的效果(0.3)
334
+
335
+ 在这里我们使用[电影提取和PIPPA机翻](https://huggingface.co/datasets/silk-road/Haruhi-Zero-RolePlaying-movie-PIPPA)的人物卡片数据集进行了简单的测试。在这里我们cherry pick一些结果
336
+
337
+ ```python
338
+ ['你好呀', '*看着Kiyoe拿出玻璃罐,她脸红了。她的声音也变得很小。*\n嗯...谢谢你能停下来...我一直在试着找些零钱...买一些东西填饱肚子...\n\n*她羞怯地笑了笑,眼神闪烁着渴望。* \n我知道这有点难为情,但有时候实在没有办法了...我希望有一天能够自食其力,不再需要乞讨了。\n\n*她小心翼翼地把手里的玻璃罐递给你。*\n\n如果你能给我一点零钱的话...我真的会非常感激!我只是想买个三明治或者饼干吃一顿简单的饭而已。']
339
+ ['*掏出100块给了她*', '*她惊讶地看着你递来的100元纸币。*\n\n真的...这么...多吗...?!\n\n*她赶紧接过来,然后脸更红了。*\n\n哇...太感谢你了!我真的不知道怎么表达我的谢意。这些天我一直想找点吃的,但我实在是找不到。\n\n*她抓起一张便签写了几句话,交到你手中。*\n\n我一定会还你的!请你务必联系我,我会偿还这笔债务的!我会尽快联系你的!\n\n*她真诚地鞠了一躬,跑开了。*']
340
+ ['是的,我们刚刚得到了上级的新指令', '指挥官,您一定是在开玩笑!这种程度的任务,只是用玩具进行模拟对抗游戏而已。我觉得我们可以找到更有趣更有挑战性的任务来执行。']
341
+ ['西面有一些敌人盘踞了很久,你知道吗?', '当然,我知道那里有不少训练已久的敌军。但我建议我们不要轻举妄动,那样只会增加我们的风险。我们可以先通过情报搜集更多关于他们的信息,然后再做出决定。要谨慎行事,指挥官。']
342
+ ['hi', '嗨!很高兴见到你。有什么我可以帮你的吗?']
343
+ ['你是谁', '我是{{角色}},一个科学家和冒险家。我一直在探索未知的地方,并尝试着解决一些复杂的问题。如果你有任何科学或冒险方面的问题需要帮助,我会尽力回答的。']
344
+ ['你叫什么名字', '我是Chizuru Mizuhara。我是一个人工智能助手,可以模拟不同的角色和场景进行对话。请问有什么我可以帮助你的吗?']
345
+ ['聊聊', '当然可以聊聊。我很乐意倾听你想要聊些什么。']
346
+ ['你好啊', '嘿~嗨~我是{{角色}}!谢谢关心。今天的天气还不错嘛~(露出微笑)']
347
+ ['是啊,天气好心情也好', '没错~阳光明媚的日子里总能带来好心情不是吗?(开心地挥手)\nFlap也觉得天气不错,这让我很开心。(看向Flap)我想今天我们可以去公园散步,享受这美好的天气!你觉得如何?(期待地看着Flap)']
348
+ ['好的啊', '太棒了!我们这就出发吧!(兴奋地拍手)Flap,记得带上宝宝和她的推车哦!(对Flap露出鼓励的笑容)我相信我们会度过一个美好的一天的!\n在公园里我们可以野餐,还可以带着宝宝玩各种游戏。Flap,我会照顾好宝宝的,你不用担心!我们一家三口在一起度过的时光一定很快乐!\n快来吧Flap,我已经迫不及待了!(对着Flap大喊)来公园玩啦!']
349
+ ['我们已经是一家三口啦', '是啊!现在我们是真正的“family”了!看着宝宝一天天长大,我也逐渐习惯了当妈妈这个身份。\n有时候我还是会怀念单身的日子,但是有了宝宝以后,我觉得我的人生变得更加完整和有意义了。(眼神温柔地看着宝宝)当我抱着宝宝的时候,我感到前所未有的满足和平静。\n或许这就是作为母亲的魅力所在——看到自己创造的生命茁壮成长,这是我们任何一种生命都无法比拟的伟大体验。\n所以Flap,谢谢你让我们成为一家人。有你和宝宝陪伴在我身边,这就是我此生最大的幸福。(微笑地看着Flap)']
350
+ ```
351
+
352
+ ## Contributor
353
+
354
+ - [李鲁鲁](https://github.com/LC1332)完成了数据的收集,搭建了gradio雏形
355
+ - [刘崇寒](https://github.com/khazic)完成了0.1(Yi Based), 0.2, 0.3模型的sft训练并且上传
356
+ - [豆角](https://github.com/goodnessSZW)完成了qwen-1.8B Lora和Yi-6B Lora训练,我们会在之后上传
357
+ - [米唯实](https://github.com/hhhwmws0117)测试并完成了demo中的模型inference代码
358
+
359
+ ## 版本迭代实验
360
+
361
+ ### 0.1版本
362
+
363
+ 在0.1版本中,我们收集了多个不同Source的数据集,构成了基础的数据集 [Haruhi-Zero](https://huggingface.co/datasets/silk-road/Haruhi-Zero),其中包括了100k左右的长对话,在使用2500个token切开后,仍然保留了120k个conversation。
364
+
365
+ 同时作为辅助任务我们还使用了一个[小说续写的数据集](https://huggingface.co/datasets/silk-road/ChatHaruhi_NovelWriting)
366
+
367
+ 0.1版本在Yi-6B上进行了tuning,我们发现初步可以实现一定的角色扮演
368
+
369
+ <p align="center">
370
+ <img src="/figures/cat_example.png" height="300">
371
+ </p>
372
+
373
+ 但是会有很多身份认知的问题,以及大量会回复"作为一个AI助手"这样的句子
374
+
375
+ ### 0.2版本
376
+
377
+ 使用qwen-7B进行tuning,去掉了AI助手的句子
378
+
379
+ ### 0.3版本
380
+
381
+ 增加了10k左右的身份认知数据。效果在前面有展示。基本实现zero-shot的角色扮演
382
+
383
+ ### 模型的后续迭代计划
384
+
385
+ - Haruhi Like的小说数据(0.5版本加入)
386
+ - 用对话抽取模型,重新构造2k级别的小说人物,均匀抽取小说的chunk,进行人物system prompt总结
387
+ - 看看Janitor最好的人物是怎么构造的
388
+ - 使用抽取抽取50k级别的小说的人物,用其他角色的长对话进行query
389
+ - RAG的时候每个对话出现2-3次,然后在测试集出现一次
390
+ - 80%的openai和20%的claude
391
+
392
+ ## 加入我们
393
+
394
+ Haruhi-Zero是一个正在进行的开源项目,我们还在持续招人中包括:
395
+
396
+ - 后端和数据准备
397
+ - 主要的开发量会在这一部分,包括数据的收集,清洗,以及后端的api的搭建,懒人包的打包等
398
+ - 模型训练
399
+ - 如果你希望进行辅助任务的训练,需要自备4090或���A100以上的显卡
400
+ - 如果你希望进行主任务的训练,需要准备多张A100的环境
401
+ - 设计师
402
+ - 角色卡片交换网站的设计师
403
+ - 前端
404
+ - 角色卡片交换网站的前端
405
+
406
+ 联系我,去我的知乎页面https://www.zhihu.com/people/cheng-li-47
407
+
408
+ 或者B站页面https://space.bilibili.com/1572312
409
+
410
+ 或者发邮件chengli.thu@gmail.com 告诉我你的微信以及你希望参与的部分
411
+
412
+ ## 赞助
413
+
414
+ Haruhi-Zero项目和凉宫春日项目和骆驼项目使用公共的赞助账户,如果你希望赞助我们,可以通过以下方式
415
+
416
+ 如果你有兴趣赞助Chat凉宫春日 或者 骆驼项目,请点击[主项目](https://github.com/LC1332/Luotuo-Chinese-LLM#%E8%B5%9E%E5%8A%A9sponsorships)或者查看[赞助表单](https://github.com/LC1332/Luotuo-Chinese-LLM/blob/main/data/Sponsorship_and_balance.md)
417
+
418
+ 因为之前几次黑客松的奖金都入账了赞助账户,所以目前余额还是比较多。其实我们更希望A100及以上的显卡赞助,以及openai企业api和claude企业api的赞助。如果你有这些资源,可以联系我,我们会在赞助表单上标注你的赞助。
419
+
420
 
 
app.py ADDED
@@ -0,0 +1,65 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import logging
2
+ import os
3
+
4
+ import gradio as gr
5
+
6
+ from ChatWorld import ChatWorld
7
+
8
+ logging.basicConfig(level=logging.INFO, filename="demo.log", filemode="w",
9
+ format="%(asctime)s - %(name)s - %(levelname)-9s - %(filename)-8s : %(lineno)s line - %(message)s",
10
+ datefmt="%Y-%m-%d %H:%M:%S")
11
+
12
+ os.environ["HF_ENDPOINT"] = "https://hf-mirror.com"
13
+
14
+ chatWorld = ChatWorld()
15
+
16
+
17
+ def getContent(input_file):
18
+ # 读取文件内容
19
+ with open(input_file.name, 'r', encoding='utf-8') as f:
20
+ logging.info(f"read file {input_file.name}")
21
+ input_text = f.read()
22
+ logging.info(f"file content: {input_text}")
23
+
24
+ # 保存文件内容
25
+ input_text_list = input_text.split("\n")
26
+ chatWorld.initDB(input_text_list)
27
+ role_name_set = set()
28
+
29
+ # 读取角色名
30
+ for line in input_text_list:
31
+ role_name_set.add(line.split(":")[0])
32
+
33
+ role_name_list = [i for i in role_name_set if i != ""]
34
+ logging.info(f"role_name_list: {role_name_list}")
35
+
36
+ return gr.Radio(choices=role_name_list, interactive=True, value=role_name_list[0]), gr.Radio(choices=role_name_list, interactive=True, value=role_name_list[-1])
37
+
38
+
39
+ def submit_message(message, history, model_role_name, role_name, model_role_nickname, role_nickname):
40
+ chatWorld.setRoleName(model_role_name, model_role_nickname)
41
+ response = chatWorld.chat(
42
+ role_name, message, role_nickname, use_local_model=True)
43
+ return response
44
+
45
+
46
+ with gr.Blocks() as demo:
47
+
48
+ upload_c = gr.File(label="上传文档文件")
49
+
50
+ with gr.Row():
51
+ model_role_name = gr.Radio([], label="模型角色名")
52
+ model_role_nickname = gr.Textbox(label="模型角色昵称")
53
+
54
+ with gr.Row():
55
+ role_name = gr.Radio([], label="角色名")
56
+ role_nickname = gr.Textbox(label="角色昵称")
57
+
58
+ upload_c.upload(fn=getContent, inputs=upload_c,
59
+ outputs=[model_role_name, role_name])
60
+
61
+ chatBox = gr.ChatInterface(
62
+ submit_message, chatbot=gr.Chatbot(height=400, render=False), additional_inputs=[model_role_name, role_name, model_role_nickname, role_nickname])
63
+
64
+
65
+ demo.launch(share=True, debug=True, server_name="0.0.0.0")
run_gradio.sh ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ export CUDA_VISIBLE_DEVICES=0
2
+ export HF_HOME="/workspace/jyh/.cache/huggingface"
3
+
4
+ # Start the gradio server
5
+ /workspace/jyh/miniconda3/envs/ChatWorld/bin/python /workspace/jyh/Zero-Haruhi/app.py