├── .env.example
├── .gitignore
├── Blog
└── Hand-on-RAG.md
├── RAG
├── Embeddings.py
├── LLM.py
├── Reranker.py
├── VectorBase.py
└── utils.py
├── README.md
├── data
├── 2024-01-23_10-07-23
│ └── Git教程.md
├── 2024-01-23_10-10-05
│ └── Git教程.md
├── 2024-01-23_10-14-41
│ └── Github Api 使用.md
├── 2024-01-23_11-59-03
│ └── Github Api 使用.md
└── 2024-01-23_12-01-19
│ └── Github Api 使用.md
├── example.py
├── example_with_reranker.py
├── images
├── RAG.png
└── Retrieval-Augmented Generation(RAG-Learning).png
├── paper.md
├── requirements.txt
├── storage
├── doecment.json
└── vectors.json
└── test.ipynb
/.env.example:
--------------------------------------------------------------------------------
1 | OPENAI_API_KEY='your openai key'
2 | OPENAI_BASE_URL='https://api.openai.com/v1'
3 |
4 | ZHIPUAI_API_KEY='your zhipuai key'
5 |
6 | # 硅基流动 API KEY and BASE URL
7 | SILICONFLOW_API_KEY='your silicon api key'
8 | SILICONFLOW_BASE_URL='https://api.siliconflow.cn/v1'
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ### Python template
2 | # Byte-compiled / optimized / DLL files
3 | __pycache__/
4 | *.py[cod]
5 | *$py.class
6 | .vscode/
7 | # C extensions
8 | *.so
9 |
10 | # Distribution / packaging
11 | .Python
12 | build/
13 | develop-eggs/
14 | dist/
15 | downloads/
16 | eggs/
17 | .eggs/
18 | lib/
19 | lib64/
20 | parts/
21 | sdist/
22 | var/
23 | wheels/
24 | share/python-wheels/
25 | *.egg-info/
26 | .installed.cfg
27 | *.egg
28 | MANIFEST
29 |
30 | # PyInstaller
31 | # Usually these files are written by a python script from a template
32 | # before PyInstaller builds the exe, so as to inject date/other infos into it.
33 | *.manifest
34 | *.spec
35 |
36 | # Installer logs
37 | pip-log.txt
38 | pip-delete-this-directory.txt
39 |
40 | # Unit test / coverage reports
41 | htmlcov/
42 | .tox/
43 | .nox/
44 | .coverage
45 | .coverage.*
46 | .cache
47 | nosetests.xml
48 | coverage.xml
49 | *.cover
50 | *.py,cover
51 | .hypothesis/
52 | .pytest_cache/
53 | cover/
54 |
55 | # Translations
56 | *.mo
57 | *.pot
58 |
59 | # Django stuff:
60 | *.log
61 | local_settings.py
62 | db.sqlite3
63 | db.sqlite3-journal
64 |
65 | # Flask stuff:
66 | instance/
67 | .webassets-cache
68 |
69 | # Scrapy stuff:
70 | .scrapy
71 |
72 | # Sphinx documentation
73 | docs/_build/
74 |
75 | # PyBuilder
76 | .pybuilder/
77 | target/
78 |
79 | # Jupyter Notebook
80 | .ipynb_checkpoints
81 |
82 | # IPython
83 | profile_default/
84 | ipython_config.py
85 |
86 | # pyenv
87 | # For a library or package, you might want to ignore these files since the code is
88 | # intended to run in multiple environments; otherwise, check them in:
89 | # .python-version
90 |
91 | # pipenv
92 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
93 | # However, in case of collaboration, if having platform-specific dependencies or dependencies
94 | # having no cross-platform support, pipenv may install dependencies that don't work, or not
95 | # install all needed dependencies.
96 | #Pipfile.lock
97 |
98 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow
99 | __pypackages__/
100 |
101 | # Celery stuff
102 | celerybeat-schedule
103 | celerybeat.pid
104 |
105 | # SageMath parsed files
106 | *.sage.py
107 |
108 | # Environments
109 | .conda/
110 | .env
111 | .venv
112 | env/
113 | venv/
114 | ENV/
115 | env.bak/
116 | venv.bak/
117 |
118 | # Spyder project settings
119 | .spyderproject
120 | .spyproject
121 |
122 | # Rope project settings
123 | .ropeproject
124 |
125 | # mkdocs documentation
126 | /site
127 |
128 | # mypy
129 | .mypy_cache/
130 | .dmypy.json
131 | dmypy.json
132 |
133 | # Pyre type checker
134 | .pyre/
135 |
136 | # pytype static type analyzer
137 | .pytype/
138 |
139 | # Cython debug symbols
140 | cython_debug/
141 |
142 | ### JetBrains template
143 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
144 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
145 |
146 | # User-specific stuff
147 | .idea/**/workspace.xml
148 | .idea/**/tasks.xml
149 | .idea/**/usage.statistics.xml
150 | .idea/**/dictionaries
151 | .idea/**/shelf
152 |
153 | # Generated files
154 | .idea/**/contentModel.xml
155 |
156 | # Sensitive or high-churn files
157 | .idea/**/dataSources/
158 | .idea/**/dataSources.ids
159 | .idea/**/dataSources.local.xml
160 | .idea/**/sqlDataSources.xml
161 | .idea/**/dynamic.xml
162 | .idea/**/uiDesigner.xml
163 | .idea/**/dbnavigator.xml
164 |
165 | # Gradle
166 | .idea/**/gradle.xml
167 | .idea/**/libraries
168 |
169 | # Gradle and Maven with auto-import
170 | # When using Gradle or Maven with auto-import, you should exclude module files,
171 | # since they will be recreated, and may cause churn. Uncomment if using
172 | # auto-import.
173 | # .idea/artifacts
174 | # .idea/compiler.xml
175 | # .idea/jarRepositories.xml
176 | # .idea/modules.xml
177 | # .idea/*.iml
178 | # .idea/modules
179 | # *.iml
180 | # *.ipr
181 |
182 | # CMake
183 | cmake-build-*/
184 |
185 | # Mongo Explorer plugin
186 | .idea/**/mongoSettings.xml
187 |
188 | # File-based project format
189 | *.iws
190 |
191 | # IntelliJ
192 | out/
193 |
194 | # mpeltonen/sbt-idea plugin
195 | .idea_modules/
196 |
197 | # JIRA plugin
198 | atlassian-ide-plugin.xml
199 |
200 | # Cursive Clojure plugin
201 | .idea/replstate.xml
202 |
203 | # Crashlytics plugin (for Android Studio and IntelliJ)
204 | com_crashlytics_export_strings.xml
205 | crashlytics.properties
206 | crashlytics-build.properties
207 | fabric.properties
208 |
209 | # Editor-based Rest Client
210 | .idea/httpRequests
211 |
212 | # Android studio 3.1+ serialized cache file
213 | .idea/caches/build_file_checksums.ser
214 |
215 | .idea
216 |
217 | # logs
218 | log/result
219 |
220 | # model
221 | model/
222 | models/
223 |
224 | *.yaml
225 |
226 | # scripts
227 | scripts/
--------------------------------------------------------------------------------
/Blog/Hand-on-RAG.md:
--------------------------------------------------------------------------------
1 | # TinyRAG
2 |
3 | 接下来我会带领大家一步一步的实现一个简单的RAG模型,这个模型是基于RAG的一个简化版本,我们称之为Tiny-RAG。Tiny-RAG是一个基于RAG的简化版本,它只包含了RAG的核心功能,即Retrieval和Generation。Tiny-RAG的目的是为了帮助大家更好的理解RAG模型的原理和实现。
4 |
5 | OK,让我们开始吧!
6 |
7 | ## 1. RAG 介绍
8 |
9 | LLM会产生误导性的 “幻觉”,依赖的信息可能过时,处理特定知识时效率不高,缺乏专业领域的深度洞察,同时在推理能力上也有所欠缺。
10 |
11 | 正是在这样的背景下,检索增强生成技术(Retrieval-Augmented Generation,RAG)应时而生,成为 AI 时代的一大趋势。
12 |
13 | RAG 通过在语言模型生成答案之前,先从广泛的文档数据库中检索相关信息,然后利用这些信息来引导生成过程,极大地提升了内容的准确性和相关性。RAG 有效地缓解了幻觉问题,提高了知识更新的速度,并增强了内容生成的可追溯性,使得大型语言模型在实际应用中变得更加实用和可信。
14 |
15 | RAG的基本结构有哪些呢?
16 |
17 | - 要有一个向量化模块,用来将文档片段向量化。
18 | - 要有一个文档加载和切分的模块,用来加载文档并切分成文档片段。
19 | - 要有一个数据库来存放文档片段和对应的向量表示。
20 | - 要有一个检索模块,用来根据 Query (问题)检索相关的文档片段。
21 | - 要有一个大模型模块,用来根据检索出来的文档回答用户的问题。
22 |
23 | OK,那上述这些也就是 TinyRAG 仓库的所有模块内容。
24 |
25 | .png)
26 |
27 | 那接下来,让我们梳理一下 RAG 的流程是什么样的呢?
28 |
29 | - **索引**:将文档库分割成较短的 Chunk,并通过编码器构建向量索引。
30 | - **检索**:根据问题和 chunks 的相似度检索相关文档片段。
31 | - **生成**:以检索到的上下文为条件,生成问题的回答。
32 |
33 | 那也就是下图所示的流程,图片出处 ***[Retrieval-Augmented Generation for Large Language Models: A Survey](https://arxiv.org/pdf/2312.10997.pdf)***
34 |
35 | 
36 |
37 | ## 2. 向量化
38 |
39 | 首先让我们来动手实现一个向量化的类,这是RAG架构的基础。向量化的类主要是用来将文档片段向量化,将一段文本映射为一个向量。
40 |
41 | 那首先我们要设置一个 `Embedding` 基类,这样我们再用其他的模型的时候,只需要继承这个基类,然后在此基础上进行修改即可,方便代码扩展。
42 |
43 | ```python
44 | class BaseEmbeddings:
45 | """
46 | Base class for embeddings
47 | """
48 | def __init__(self, path: str, is_api: bool) -> None:
49 | self.path = path
50 | self.is_api = is_api
51 |
52 | def get_embedding(self, text: str, model: str) -> List[float]:
53 | raise NotImplementedError
54 |
55 | @classmethod
56 | def cosine_similarity(cls, vector1: List[float], vector2: List[float]) -> float:
57 | """
58 | calculate cosine similarity between two vectors
59 | """
60 | dot_product = np.dot(vector1, vector2)
61 | magnitude = np.linalg.norm(vector1) * np.linalg.norm(vector2)
62 | if not magnitude:
63 | return 0
64 | return dot_product / magnitude
65 | ```
66 |
67 | 观察一下`BaseEmbeddings`基类都有什么方法,首先有一个`get_embedding`方法,这个方法是用来获取文本的向量表示的,然后有一个`cosine_similarity`方法,这个方法是用来计算两个向量之间的余弦相似度的。其次在初始化类的时候设置了,模型的路径和是否是API模型。比如使用OpenAI的Embedding API的话就需要设置`self.is_api=Ture`。
68 |
69 | 继承`BaseEmbeddings`类的话,就只需要编写`get_embedding`方法即可,`cosine_similarity`方法会被继承下来,直接用就行。这就是编写基类的好处。
70 |
71 | ```python
72 | class OpenAIEmbedding(BaseEmbeddings):
73 | """
74 | class for OpenAI embeddings
75 | """
76 | def __init__(self, path: str = '', is_api: bool = True) -> None:
77 | super().__init__(path, is_api)
78 | if self.is_api:
79 | from openai import OpenAI
80 | self.client = OpenAI()
81 | self.client.api_key = os.getenv("OPENAI_API_KEY")
82 | self.client.base_url = os.getenv("OPENAI_BASE_URL")
83 |
84 | def get_embedding(self, text: str, model: str = "text-embedding-3-large") -> List[float]:
85 | if self.is_api:
86 | text = text.replace("\n", " ")
87 | return self.client.embeddings.create(input=[text], model=model).data[0].embedding
88 | else:
89 | raise NotImplementedError
90 | ```
91 |
92 | ## 3. 文档加载和切分
93 |
94 | 接下来我们来实现一个文档加载和切分的类,这个类主要是用来加载文档并切分成文档片段。
95 |
96 | 那我们都需要切分什么文档呢?这个文档可以是一篇文章,一本书,一段对话,一段代码等等。这个文档的内容可以是任何的,只要是文本就行。比如:pdf文件、md文件、txt文件等等。
97 |
98 | 这里只展示一部分内容了,完整的代码可以在 ***[RAG/utils.py](../RAG/utils.py)*** 文件中找到。在这个代码中可以看到,能加载的文件类型有:pdf、md、txt,只需要编写对应的函数即可。
99 |
100 | ```python
101 | def read_file_content(cls, file_path: str):
102 | # 根据文件扩展名选择读取方法
103 | if file_path.endswith('.pdf'):
104 | return cls.read_pdf(file_path)
105 | elif file_path.endswith('.md'):
106 | return cls.read_markdown(file_path)
107 | elif file_path.endswith('.txt'):
108 | return cls.read_text(file_path)
109 | else:
110 | raise ValueError("Unsupported file type")
111 | ```
112 |
113 | 那我们把文件内容都读取之后,还需要切分呀!那怎么切分呢,OK,接下来咱们就按 Token 的长度来切分文档。我们可以设置一个最大的 Token 长度,然后根据这个最大的 Token 长度来切分文档。这样切分出来的文档片段就是一个一个的差不多相同长度的文档片段了。
114 |
115 | 不过在切分的时候要注意,片段与片段之间最好要有一些重叠的内容,这样才能保证检索的时候能够检索到相关的文档片段。还有就是切分文档的时候最好以句子为单位,也就是按 `\n` 进行粗切分,这样可以基本保证句子内容是完整的。
116 |
117 | ```python
118 | def get_chunk(cls, text: str, max_token_len: int = 600, cover_content: int = 150):
119 | chunk_text = []
120 |
121 | curr_len = 0
122 | curr_chunk = ''
123 |
124 | lines = text.split('\n') # 假设以换行符分割文本为行
125 |
126 | for line in lines:
127 | line = line.replace(' ', '')
128 | line_len = len(enc.encode(line))
129 | if line_len > max_token_len:
130 | print('warning line_len = ', line_len)
131 | if curr_len + line_len <= max_token_len:
132 | curr_chunk += line
133 | curr_chunk += '\n'
134 | curr_len += line_len
135 | curr_len += 1
136 | else:
137 | chunk_text.append(curr_chunk)
138 | curr_chunk = curr_chunk[-cover_content:]+line
139 | curr_len = line_len + cover_content
140 |
141 | if curr_chunk:
142 | chunk_text.append(curr_chunk)
143 |
144 | return chunk_text
145 | ```
146 |
147 | ## 4. 数据库 && 向量检索
148 |
149 | 上面,我们做好了文档切分,也做好了 Embedding 模型的加载。那接下来就得设计一个向量数据库用来存放文档片段和对应的向量表示了。
150 |
151 | 还有就是也要设计一个检索模块,用来根据 Query (问题)检索相关的文档片段。OK,我们冲冲冲!
152 |
153 | 一个数据库对于最小RAG架构来说,需要实现几个功能呢?
154 |
155 | - `persist`:数据库持久化,本地保存
156 | - `load_vector`:从本地加载数据库
157 | - `get_vector`:获得文档的向量表示
158 | - `query`:根据问题检索相关的文档片段
159 |
160 | 嗯嗯,以上四个模块就是一个最小的RAG结构数据库需要实现的功能,具体代码可以在 ***[RAG/VectorBase.py](../RAG/VectorBase.py)*** 文件中找到。
161 |
162 | ```python
163 | class VectorStore:
164 | def __init__(self, document: List[str] = ['']) -> None:
165 | self.document = document
166 |
167 | def get_vector(self, EmbeddingModel: BaseEmbeddings) -> List[List[float]]:
168 | # 获得文档的向量表示
169 | pass
170 |
171 | def persist(self, path: str = 'storage'):
172 | # 数据库持久化,本地保存
173 | pass
174 |
175 | def load_vector(self, path: str = 'storage'):
176 | # 从本地加载数据库
177 | pass
178 |
179 | def query(self, query: str, EmbeddingModel: BaseEmbeddings, k: int = 1) -> List[str]:
180 | # 根据问题检索相关的文档片段
181 | pass
182 | ```
183 |
184 | 那让我们来看一下, `query` 方法具体是怎么实现的呢?
185 |
186 | 首先先把用户提出的问题向量化,然后去数据库中检索相关的文档片段,最后返回检索到的文档片段。可以看到咱们在向量检索的时候仅使用 `Numpy` 进行加速,代码非常容易理解和修改。
187 |
188 | 主要是方便改写和大家理解,并没有使用成熟的数据库,这样可以更好的理解RAG的原理。
189 |
190 | ```python
191 | def query(self, query: str, EmbeddingModel: BaseEmbeddings, k: int = 1) -> List[str]:
192 | query_vector = EmbeddingModel.get_embedding(query)
193 | result = np.array([self.get_similarity(query_vector, vector)
194 | for vector in self.vectors])
195 | return np.array(self.document)[result.argsort()[-k:][::-1]].tolist()
196 | ```
197 |
198 |
199 | ## 5. 大模型模块
200 |
201 | 那就来到了最后一个模块了,大模型模块。这个模块主要是用来根据检索出来的文档回答用户的问题。
202 |
203 | 一样的,我们还是先实现一个基类,这样我们在遇到其他的自己感兴趣的模型就可以快速的扩展了。
204 |
205 | ```python
206 | class BaseModel:
207 | def __init__(self, path: str = '') -> None:
208 | self.path = path
209 |
210 | def chat(self, prompt: str, history: List[dict], content: str) -> str:
211 | pass
212 |
213 | def load_model(self):
214 | pass
215 | ```
216 |
217 | `BaseModel` 包含了两个方法,`chat`和`load_model`,如果使用API模型,比如OpenAI的话,那就不需要`load_model`方法,如果你要本地化运行的话,那还是会选择使用开源模型,那就需要`load_model`方法发啦。
218 |
219 | 这里咱们以 ***[InternLM2-chat-7B](https://huggingface.co/internlm/internlm2-chat-7b)*** 模型为例,大家可以给 ***[InternLM](https://github.com/InternLM/InternLM)*** 仓库点个star哦,还有也给我点个star!
220 |
221 | ```python
222 | class InternLMChat(BaseModel):
223 | def __init__(self, path: str = '') -> None:
224 | super().__init__(path)
225 | self.load_model()
226 |
227 | def chat(self, prompt: str, history: List = [], content: str='') -> str:
228 | prompt = PROMPT_TEMPLATE['InternLM_PROMPT_TEMPALTE'].format(question=prompt, context=content)
229 | response, history = self.model.chat(self.tokenizer, prompt, history)
230 | return response
231 |
232 |
233 | def load_model(self):
234 | import torch
235 | from transformers import AutoTokenizer, AutoModelForCausalLM
236 | self.tokenizer = AutoTokenizer.from_pretrained(self.path, trust_remote_code=True)
237 | self.model = AutoModelForCausalLM.from_pretrained(self.path, torch_dtype=torch.float16, trust_remote_code=True).cuda()
238 | ```
239 |
240 | 可以用一个字典来保存所有的prompt,这样比较好维护。
241 |
242 | ```python
243 | PROMPT_TEMPLATE = dict(
244 | InternLM_PROMPT_TEMPALTE="""先对上下文进行内容总结,再使用上下文来回答用户的问题。如果你不知道答案,就说你不知道。总是使用中文回答。
245 | 问题: {question}
246 | 可参考的上下文:
247 | ···
248 | {context}
249 | ···
250 | 如果给定的上下文无法让你做出回答,请回答数据库中没有这个内容,你不知道。
251 | 有用的回答:"""
252 | )
253 | ```
254 |
255 | 那这样的话,我们就可以利用InternLM2模型来做RAG啦!
256 |
257 | ## 6. LLM Tiny-RAG Demo
258 |
259 | 那接下来,我们就来看一下Tiny-RAG的Demo吧!
260 |
261 | ```python
262 | from RAG.VectorBase import VectorStore
263 | from RAG.utils import ReadFiles
264 | from RAG.LLM import OpenAIChat, InternLMChat
265 | from RAG.Embeddings import JinaEmbedding, ZhipuEmbedding
266 |
267 |
268 | 没有保存数据库
269 | docs = ReadFiles('./data').get_content(max_token_len=600, cover_content=150) # 获得data目录下的所有文件内容并分割
270 | vector = VectorStore(docs)
271 | embedding = ZhipuEmbedding() # 创建EmbeddingModel
272 | vector.get_vector(EmbeddingModel=embedding)
273 | vector.persist(path='storage') # 将向量和文档内容保存到storage目录下,下次再用就可以直接加载本地的数据库
274 |
275 | question = 'git的原理是什么?'
276 |
277 | content = vector.query(question, model='zhipu', k=1)[0]
278 | chat = InternLMChat(path='model_path')
279 | print(chat.chat(question, [], content))
280 | ```
281 |
282 | 当然我们也可以从本地加载已经处理好的数据库,毕竟我们在上面的数据库环节已经写过这个功能啦。
283 |
284 | ```python
285 | from RAG.VectorBase import VectorStore
286 | from RAG.utils import ReadFiles
287 | from RAG.LLM import OpenAIChat, InternLMChat
288 | from RAG.Embeddings import JinaEmbedding, ZhipuEmbedding
289 |
290 | # 保存数据库之后
291 | vector = VectorStore()
292 |
293 | vector.load_vector('./storage') # 加载本地的数据库
294 |
295 | question = 'git的原理是什么?'
296 |
297 | embedding = ZhipuEmbedding() # 创建EmbeddingModel
298 |
299 | content = vector.query(question, EmbeddingModel=embedding, k=1)[0]
300 | chat = InternLMChat(path='model_path')
301 | print(chat.chat(question, [], content))
302 | ```
303 |
304 | ## 7. 总结
305 |
306 | 经过上面的学习,你是否学会了如何搭建一个最小RAG架构呢?相信你一定学会啦,哈哈哈。
307 |
308 | 那让我们再来复习一下,一个最小RAG应该包含哪些内容叭?(此处默写!)
309 |
310 | - 向量化模块
311 | - 文档加载和切分模块
312 | - 数据库
313 | - 向量检索
314 | - 大模型模块
315 |
316 | okk,你已经学会了,但别忘了给我的项目点个star哦!
--------------------------------------------------------------------------------
/RAG/Embeddings.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 | '''
4 | @File : Embeddings.py
5 | @Time : 2024/02/10 21:55:39
6 | @Author : 不要葱姜蒜
7 | @Version : 1.0
8 | @Desc : None
9 | '''
10 |
11 | import os
12 | from copy import copy
13 | from typing import Dict, List, Optional, Tuple, Union
14 | import numpy as np
15 |
16 | os.environ['CURL_CA_BUNDLE'] = ''
17 | from dotenv import load_dotenv, find_dotenv
18 | _ = load_dotenv(find_dotenv())
19 |
20 |
21 | class BaseEmbeddings:
22 | """
23 | Base class for embeddings
24 | """
25 | def __init__(self, path: str, is_api: bool) -> None:
26 | self.path = path
27 | self.is_api = is_api
28 |
29 | def get_embedding(self, text: str, model: str) -> List[float]:
30 | raise NotImplementedError
31 |
32 | @classmethod
33 | def cosine_similarity(cls, vector1: List[float], vector2: List[float]) -> float:
34 | """
35 | calculate cosine similarity between two vectors
36 | """
37 | dot_product = np.dot(vector1, vector2)
38 | magnitude = np.linalg.norm(vector1) * np.linalg.norm(vector2)
39 | if not magnitude:
40 | return 0
41 | return dot_product / magnitude
42 |
43 |
44 | class OpenAIEmbedding(BaseEmbeddings):
45 | """
46 | class for OpenAI embeddings
47 | """
48 | def __init__(self, path: str = '', is_api: bool = True) -> None:
49 | super().__init__(path, is_api)
50 | if self.is_api:
51 | from openai import OpenAI
52 | self.client = OpenAI()
53 | self.client.api_key = os.getenv("OPENAI_API_KEY")
54 | self.client.base_url = os.getenv("OPENAI_BASE_URL")
55 |
56 | def get_embedding(self, text: str, model: str = "text-embedding-3-large") -> List[float]:
57 | if self.is_api:
58 | text = text.replace("\n", " ")
59 | return self.client.embeddings.create(input=[text], model=model).data[0].embedding
60 | else:
61 | raise NotImplementedError
62 |
63 | class JinaEmbedding(BaseEmbeddings):
64 | """
65 | class for Jina embeddings
66 | """
67 | def __init__(self, path: str = 'jinaai/jina-embeddings-v2-base-zh', is_api: bool = False) -> None:
68 | super().__init__(path, is_api)
69 | self._model = self.load_model()
70 |
71 | def get_embedding(self, text: str) -> List[float]:
72 | return self._model.encode([text])[0].tolist()
73 |
74 | def load_model(self):
75 | import torch
76 | from transformers import AutoModel
77 | if torch.cuda.is_available():
78 | device = torch.device("cuda")
79 | else:
80 | device = torch.device("cpu")
81 | model = AutoModel.from_pretrained(self.path, trust_remote_code=True).to(device)
82 | return model
83 |
84 | class ZhipuEmbedding(BaseEmbeddings):
85 | """
86 | class for Zhipu embeddings
87 | """
88 | def __init__(self, path: str = '', is_api: bool = True) -> None:
89 | super().__init__(path, is_api)
90 | if self.is_api:
91 | from zhipuai import ZhipuAI
92 | self.client = ZhipuAI(api_key=os.getenv("ZHIPUAI_API_KEY"))
93 |
94 | def get_embedding(self, text: str) -> List[float]:
95 | response = self.client.embeddings.create(
96 | model="embedding-2",
97 | input=text,
98 | )
99 | return response.data[0].embedding
100 |
101 | class DashscopeEmbedding(BaseEmbeddings):
102 | """
103 | class for Dashscope embeddings
104 | """
105 | def __init__(self, path: str = '', is_api: bool = True) -> None:
106 | super().__init__(path, is_api)
107 | if self.is_api:
108 | import dashscope
109 | dashscope.api_key = os.getenv("DASHSCOPE_API_KEY")
110 | self.client = dashscope.TextEmbedding
111 |
112 | def get_embedding(self, text: str, model: str='text-embedding-v1') -> List[float]:
113 | response = self.client.call(
114 | model=model,
115 | input=text
116 | )
117 | return response.output['embeddings'][0]['embedding']
118 |
119 |
120 | class BgeEmbedding(BaseEmbeddings):
121 | """
122 | class for BGE embeddings
123 | """
124 |
125 | def __init__(self, path: str = 'BAAI/bge-base-zh-v1.5', is_api: bool = False) -> None:
126 | super().__init__(path, is_api)
127 | self._model, self._tokenizer = self.load_model(path)
128 |
129 | def get_embedding(self, text: str) -> List[float]:
130 | import torch
131 | encoded_input = self._tokenizer([text], padding=True, truncation=True, return_tensors='pt')
132 | encoded_input = {k: v.to(self._model.device) for k, v in encoded_input.items()}
133 | with torch.no_grad():
134 | model_output = self._model(**encoded_input)
135 | sentence_embeddings = model_output[0][:, 0]
136 | sentence_embeddings = torch.nn.functional.normalize(sentence_embeddings, p=2, dim=1)
137 | return sentence_embeddings[0].tolist()
138 |
139 | def load_model(self, path: str):
140 | import torch
141 | from transformers import AutoModel, AutoTokenizer
142 | if torch.cuda.is_available():
143 | device = torch.device("cuda")
144 | else:
145 | device = torch.device("cpu")
146 | tokenizer = AutoTokenizer.from_pretrained(path)
147 | model = AutoModel.from_pretrained(path).to(device)
148 | model.eval()
149 | return model, tokenizer
150 |
151 | # BGE SILICONFLOW API KEY
152 |
153 | class BgeWithAPIEmbedding(BaseEmbeddings):
154 | """
155 | class for SILICON API embeddings
156 | """
157 | def __init__(self, path: str = '', is_api: bool = True) -> None:
158 | super().__init__(path, is_api)
159 | if self.is_api:
160 | from openai import OpenAI
161 | self.client = OpenAI()
162 | self.client.api_key = os.getenv("SILICONFLOW_API_KEY")
163 | self.client.base_url = os.getenv("SILICONFLOW_BASE_URL")
164 |
165 | def get_embedding(self, text: str, model: str = "BAAI/bge-m3") -> List[float]:
166 | if self.is_api:
167 | text = text.replace("\n", " ")
168 | return self.client.embeddings.create(input=[text], model=model).data[0].embedding
169 | else:
170 | raise NotImplementedError
--------------------------------------------------------------------------------
/RAG/LLM.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 | '''
4 | @File : LLM.py
5 | @Time : 2024/02/12 13:50:47
6 | @Author : 不要葱姜蒜
7 | @Version : 1.0
8 | @Desc : None
9 | '''
10 | import os
11 | from typing import Dict, List, Optional, Tuple, Union
12 |
13 | PROMPT_TEMPLATE = dict(
14 | RAG_PROMPT_TEMPALTE="""使用以上下文来回答用户的问题。如果你不知道答案,就说你不知道。总是使用中文回答。
15 | 问题: {question}
16 | 可参考的上下文:
17 | ···
18 | {context}
19 | ···
20 | 如果给定的上下文无法让你做出回答,请回答数据库中没有这个内容,你不知道。
21 | 有用的回答:""",
22 | InternLM_PROMPT_TEMPALTE="""先对上下文进行内容总结,再使用上下文来回答用户的问题。如果你不知道答案,就说你不知道。总是使用中文回答。
23 | 问题: {question}
24 | 可参考的上下文:
25 | ···
26 | {context}
27 | ···
28 | 如果给定的上下文无法让你做出回答,请回答数据库中没有这个内容,你不知道。
29 | 有用的回答:"""
30 | )
31 |
32 |
33 | class BaseModel:
34 | def __init__(self, path: str = '') -> None:
35 | self.path = path
36 |
37 | def chat(self, prompt: str, history: List[dict], content: str) -> str:
38 | pass
39 |
40 | def load_model(self):
41 | pass
42 |
43 | class OpenAIChat(BaseModel):
44 | def __init__(self, path: str = '', model: str = "gpt-3.5-turbo-1106") -> None:
45 | super().__init__(path)
46 | self.model = model
47 |
48 | def chat(self, prompt: str, history: List[dict], content: str) -> str:
49 | from openai import OpenAI
50 | client = OpenAI()
51 | client.api_key = os.getenv("OPENAI_API_KEY")
52 | client.base_url = os.getenv("OPENAI_BASE_URL")
53 | history.append({'role': 'user', 'content': PROMPT_TEMPLATE['RAG_PROMPT_TEMPALTE'].format(question=prompt, context=content)})
54 | response = client.chat.completions.create(
55 | model=self.model,
56 | messages=history,
57 | max_tokens=150,
58 | temperature=0.1
59 | )
60 | return response.choices[0].message.content
61 |
62 | class InternLMChat(BaseModel):
63 | def __init__(self, path: str = '') -> None:
64 | super().__init__(path)
65 | self.load_model()
66 |
67 | def chat(self, prompt: str, history: List = [], content: str='') -> str:
68 | prompt = PROMPT_TEMPLATE['InternLM_PROMPT_TEMPALTE'].format(question=prompt, context=content)
69 | response, history = self.model.chat(self.tokenizer, prompt, history)
70 | return response
71 |
72 |
73 | def load_model(self):
74 | import torch
75 | from transformers import AutoTokenizer, AutoModelForCausalLM
76 | self.tokenizer = AutoTokenizer.from_pretrained(self.path, trust_remote_code=True)
77 | self.model = AutoModelForCausalLM.from_pretrained(self.path, torch_dtype=torch.float16, trust_remote_code=True).cuda()
78 |
79 | class DashscopeChat(BaseModel):
80 | def __init__(self, path: str = '', model: str = "qwen-turbo") -> None:
81 | super().__init__(path)
82 | self.model = model
83 |
84 | def chat(self, prompt: str, history: List[Dict], content: str) -> str:
85 | import dashscope
86 | dashscope.api_key = os.getenv("DASHSCOPE_API_KEY")
87 | history.append({'role': 'user', 'content': PROMPT_TEMPLATE['RAG_PROMPT_TEMPALTE'].format(question=prompt, context=content)})
88 | response = dashscope.Generation.call(
89 | model=self.model,
90 | messages=history,
91 | result_format='message',
92 | max_tokens=150,
93 | temperature=0.1
94 | )
95 | return response.output.choices[0].message.content
96 |
97 |
98 | class ZhipuChat(BaseModel):
99 | def __init__(self, path: str = '', model: str = "glm-4") -> None:
100 | super().__init__(path)
101 | from zhipuai import ZhipuAI
102 | self.client = ZhipuAI(api_key=os.getenv("ZHIPUAI_API_KEY"))
103 | self.model = model
104 |
105 | def chat(self, prompt: str, history: List[Dict], content: str) -> str:
106 | history.append({'role': 'user', 'content': PROMPT_TEMPLATE['RAG_PROMPT_TEMPALTE'].format(question=prompt, context=content)})
107 | response = self.client.chat.completions.create(
108 | model=self.model,
109 | messages=history,
110 | max_tokens=150,
111 | temperature=0.1
112 | )
113 | return response.choices[0].message
114 |
115 | class SiliconflowChat(BaseModel):
116 | def __init__(self, path: str = '', model: str = "Qwen/Qwen2.5-7B-Instruct") -> None:
117 | super().__init__(path)
118 | self.model = model
119 |
120 | def chat(self, prompt: str, history: List[dict], content: str) -> str:
121 | from openai import OpenAI
122 | client = OpenAI()
123 | client.api_key = os.getenv("SILICONFLOW_API_KEY")
124 | client.base_url = os.getenv("SILICONFLOW_BASE_URL")
125 | final_prompt={'role': 'user', 'content': PROMPT_TEMPLATE['RAG_PROMPT_TEMPALTE'].format(question=prompt, context=content)}
126 | print("---------------------input---------------------")
127 | print(final_prompt)
128 | history.append(final_prompt)
129 | response = client.chat.completions.create(
130 | model=self.model,
131 | messages=history,
132 | # max_tokens=150,
133 | temperature=0.1
134 | )
135 | return response.choices[0].message.content
--------------------------------------------------------------------------------
/RAG/Reranker.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 | '''
4 | @File : Reranker.py
5 | @Time : 2024/05/15 14:27:42
6 | @Author : YueZhengMeng
7 | @Version : 1.0
8 | @Desc : None
9 | '''
10 |
11 | from typing import List
12 | import numpy as np
13 |
14 |
15 | class BaseReranker:
16 | """
17 | Base class for reranker
18 | """
19 |
20 | def __init__(self, path: str) -> None:
21 | self.path = path
22 |
23 | def rerank(self, text: str, content: List[str], k: int) -> List[str]:
24 | raise NotImplementedError
25 |
26 |
27 | class BgeReranker(BaseReranker):
28 | """
29 | class for Bge reranker
30 | """
31 |
32 | def __init__(self, path: str = 'BAAI/bge-reranker-base') -> None:
33 | super().__init__(path)
34 | self._model, self._tokenizer = self.load_model(path)
35 |
36 | def rerank(self, text: str, content: List[str], k: int) -> List[str]:
37 | import torch
38 | pairs = [(text, c) for c in content]
39 | with torch.no_grad():
40 | inputs = self._tokenizer(pairs, padding=True, truncation=True, return_tensors='pt', max_length=512)
41 | inputs = {k: v.to(self._model.device) for k, v in inputs.items()}
42 | scores = self._model(**inputs, return_dict=True).logits.view(-1, ).float()
43 | index = np.argsort(scores.tolist())[-k:][::-1]
44 | return [content[i] for i in index]
45 |
46 | def load_model(self, path: str):
47 | import torch
48 | from transformers import AutoModelForSequenceClassification, AutoTokenizer
49 | if torch.cuda.is_available():
50 | device = torch.device("cuda")
51 | else:
52 | device = torch.device("cpu")
53 | tokenizer = AutoTokenizer.from_pretrained(path)
54 | model = AutoModelForSequenceClassification.from_pretrained(path).to(device)
55 | model.eval()
56 | return model, tokenizer
57 |
--------------------------------------------------------------------------------
/RAG/VectorBase.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 | '''
4 | @File : VectorBase.py
5 | @Time : 2024/02/12 10:11:13
6 | @Author : 不要葱姜蒜
7 | @Version : 1.0
8 | @Desc : None
9 | '''
10 |
11 | import os
12 | from typing import Dict, List, Optional, Tuple, Union
13 | import json
14 | from RAG.Embeddings import BaseEmbeddings, OpenAIEmbedding, JinaEmbedding, ZhipuEmbedding
15 | import numpy as np
16 | from tqdm import tqdm
17 |
18 |
19 | class VectorStore:
20 | def __init__(self, document: List[str] = ['']) -> None:
21 | self.document = document
22 |
23 | def get_vector(self, EmbeddingModel: BaseEmbeddings) -> List[List[float]]:
24 |
25 | self.vectors = []
26 | for doc in tqdm(self.document, desc="Calculating embeddings"):
27 | self.vectors.append(EmbeddingModel.get_embedding(doc))
28 | return self.vectors
29 |
30 | def persist(self, path: str = 'storage'):
31 | if not os.path.exists(path):
32 | os.makedirs(path)
33 | with open(f"{path}/doecment.json", 'w', encoding='utf-8') as f:
34 | json.dump(self.document, f, ensure_ascii=False)
35 | if self.vectors:
36 | with open(f"{path}/vectors.json", 'w', encoding='utf-8') as f:
37 | json.dump(self.vectors, f)
38 |
39 | def load_vector(self, path: str = 'storage'):
40 | with open(f"{path}/vectors.json", 'r', encoding='utf-8') as f:
41 | self.vectors = json.load(f)
42 | with open(f"{path}/doecment.json", 'r', encoding='utf-8') as f:
43 | self.document = json.load(f)
44 |
45 | def get_similarity(self, vector1: List[float], vector2: List[float]) -> float:
46 | return BaseEmbeddings.cosine_similarity(vector1, vector2)
47 |
48 | def query(self, query: str, EmbeddingModel: BaseEmbeddings, k: int = 1) -> List[str]:
49 | query_vector = EmbeddingModel.get_embedding(query)
50 | result = np.array([self.get_similarity(query_vector, vector)
51 | for vector in self.vectors])
52 | return np.array(self.document)[result.argsort()[-k:][::-1]].tolist()
53 |
--------------------------------------------------------------------------------
/RAG/utils.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 | '''
4 | @File : utils.py
5 | @Time : 2024/02/11 09:52:26
6 | @Author : 不要葱姜蒜
7 | @Version : 1.0
8 | @Desc : None
9 | '''
10 |
11 | import os
12 | from typing import Dict, List, Optional, Tuple, Union
13 |
14 | import PyPDF2
15 | import markdown
16 | import html2text
17 | import json
18 | from tqdm import tqdm
19 | import tiktoken
20 | from bs4 import BeautifulSoup
21 | import re
22 |
23 | enc = tiktoken.get_encoding("cl100k_base")
24 |
25 |
26 | class ReadFiles:
27 | """
28 | class to read files
29 | """
30 |
31 | def __init__(self, path: str) -> None:
32 | self._path = path
33 | self.file_list = self.get_files()
34 |
35 | def get_files(self):
36 | # args:dir_path,目标文件夹路径
37 | file_list = []
38 | for filepath, dirnames, filenames in os.walk(self._path):
39 | # os.walk 函数将递归遍历指定文件夹
40 | for filename in filenames:
41 | # 通过后缀名判断文件类型是否满足要求
42 | if filename.endswith(".md"):
43 | # 如果满足要求,将其绝对路径加入到结果列表
44 | file_list.append(os.path.join(filepath, filename))
45 | elif filename.endswith(".txt"):
46 | file_list.append(os.path.join(filepath, filename))
47 | elif filename.endswith(".pdf"):
48 | file_list.append(os.path.join(filepath, filename))
49 | return file_list
50 |
51 | def get_content(self, max_token_len: int = 600, cover_content: int = 150):
52 | docs = []
53 | # 读取文件内容
54 | for file in self.file_list:
55 | content = self.read_file_content(file)
56 | chunk_content = self.get_chunk(
57 | content, max_token_len=max_token_len, cover_content=cover_content)
58 | docs.extend(chunk_content)
59 | return docs
60 |
61 | @classmethod
62 | def get_chunk(cls, text: str, max_token_len: int = 600, cover_content: int = 150):
63 | chunk_text = []
64 |
65 | curr_len = 0
66 | curr_chunk = ''
67 |
68 | token_len = max_token_len - cover_content
69 | lines = text.splitlines() # 假设以换行符分割文本为行
70 |
71 | for line in lines:
72 | line = line.replace(' ', '')
73 | line_len = len(enc.encode(line))
74 | if line_len > max_token_len:
75 | # 如果单行长度就超过限制,则将其分割成多个块
76 | num_chunks = (line_len + token_len - 1) // token_len
77 | for i in range(num_chunks):
78 | start = i * token_len
79 | end = start + token_len
80 | # 避免跨单词分割
81 | while not line[start:end].rstrip().isspace():
82 | start += 1
83 | end += 1
84 | if start >= line_len:
85 | break
86 | curr_chunk = curr_chunk[-cover_content:] + line[start:end]
87 | chunk_text.append(curr_chunk)
88 | # 处理最后一个块
89 | start = (num_chunks - 1) * token_len
90 | curr_chunk = curr_chunk[-cover_content:] + line[start:end]
91 | chunk_text.append(curr_chunk)
92 |
93 | if curr_len + line_len <= token_len:
94 | curr_chunk += line
95 | curr_chunk += '\n'
96 | curr_len += line_len
97 | curr_len += 1
98 | else:
99 | chunk_text.append(curr_chunk)
100 | curr_chunk = curr_chunk[-cover_content:]+line
101 | curr_len = line_len + cover_content
102 |
103 | if curr_chunk:
104 | chunk_text.append(curr_chunk)
105 |
106 | return chunk_text
107 |
108 | @classmethod
109 | def read_file_content(cls, file_path: str):
110 | # 根据文件扩展名选择读取方法
111 | if file_path.endswith('.pdf'):
112 | return cls.read_pdf(file_path)
113 | elif file_path.endswith('.md'):
114 | return cls.read_markdown(file_path)
115 | elif file_path.endswith('.txt'):
116 | return cls.read_text(file_path)
117 | else:
118 | raise ValueError("Unsupported file type")
119 |
120 | @classmethod
121 | def read_pdf(cls, file_path: str):
122 | # 读取PDF文件
123 | with open(file_path, 'rb') as file:
124 | reader = PyPDF2.PdfReader(file)
125 | text = ""
126 | for page_num in range(len(reader.pages)):
127 | text += reader.pages[page_num].extract_text()
128 | return text
129 |
130 | @classmethod
131 | def read_markdown(cls, file_path: str):
132 | # 读取Markdown文件
133 | with open(file_path, 'r', encoding='utf-8') as file:
134 | md_text = file.read()
135 | html_text = markdown.markdown(md_text)
136 | # 使用BeautifulSoup从HTML中提取纯文本
137 | soup = BeautifulSoup(html_text, 'html.parser')
138 | plain_text = soup.get_text()
139 | # 使用正则表达式移除网址链接
140 | text = re.sub(r'http\S+', '', plain_text)
141 | return text
142 |
143 | @classmethod
144 | def read_text(cls, file_path: str):
145 | # 读取文本文件
146 | with open(file_path, 'r', encoding='utf-8') as file:
147 | return file.read()
148 |
149 |
150 | class Documents:
151 | """
152 | 获取已分好类的json格式文档
153 | """
154 | def __init__(self, path: str = '') -> None:
155 | self.path = path
156 |
157 | def get_content(self):
158 | with open(self.path, mode='r', encoding='utf-8') as f:
159 | content = json.load(f)
160 | return content
161 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Hands on TinyRAG
2 |
3 | ## 什么是RAG?
4 |
5 | LLM会产生误导性的 “幻觉”,依赖的信息可能过时,处理特定知识时效率不高,缺乏专业领域的深度洞察,同时在推理能力上也有所欠缺。
6 |
7 | 正是在这样的背景下,检索增强生成技术(Retrieval-Augmented Generation,RAG)应时而生,成为 AI 时代的一大趋势。
8 |
9 | RAG 通过在语言模型生成答案之前,先从广泛的文档数据库中检索相关信息,然后利用这些信息来引导生成过程,极大地提升了内容的准确性和相关性。RAG 有效地缓解了幻觉问题,提高了知识更新的速度,并增强了内容生成的可追溯性,使得大型语言模型在实际应用中变得更加实用和可信。
10 |
11 | 此仓库用于学习大模型RAG的相关内容,目前为手搓实现,主要是llama-index和langchain不太好魔改。此仓库可以方便看论文的时候,实现一些小的实验。以下为本仓库的RAG整体框架图。
12 |
13 | .png)
14 |
15 | 以下为笔者所构思的RAG实现过程,这里面主要包括包括三个基本步骤:
16 |
17 | 1. 索引 — 将文档库分割成较短的 Chunk,并通过编码器构建向量索引。
18 |
19 | 2. 检索 — 根据问题和 chunks 的相似度检索相关文档片段。
20 |
21 | 3. 生成 — 以检索到的上下文为条件,生成问题的回答。
22 |
23 |
24 |

25 |
26 |
27 | # QuickStrat
28 |
29 | 安装依赖,需要 Python 3.10 以上版本。
30 |
31 | ```bash
32 | pip install -r requirements.txt
33 | ```
34 |
35 | 导入所使用的包
36 |
37 | ```python
38 | from RAG.VectorBase import VectorStore
39 | from RAG.utils import ReadFiles
40 | from RAG.LLM import OpenAIChat
41 | ```
42 |
43 | 如果没有数据库那就按照如下代码:
44 |
45 | > 可以使用`VectorStore.persist()`保存到向量数据库。
46 |
47 | ```python
48 | # 没有保存数据库
49 | docs = ReadFiles('./data').get_content(max_token_len=600, cover_content=150) # 获得data目录下的所有文件内容并分割
50 | embedding = JinaEmbedding("your model path") # 创建EmbeddingModel
51 | vector = VectorStore(docs)
52 | vector.get_vector(EmbeddingModel=embedding)
53 | vector.persist(path='storage') # 将向量和文档内容保存到storage目录下,下次再用就可以直接加载本地的数据库
54 |
55 | question = 'git的分支原理?'
56 |
57 | content = vector.query(question, EmbeddingModel=embedding, k=1)[0]
58 | chat = OpenAIChat(model='gpt-3.5-turbo-1106')
59 | print(chat.chat(question, [], content))
60 | ```
61 |
62 | 如果有数据库那就按照如下代码:
63 |
64 | ```python
65 | vector = VectorStore()
66 |
67 | vector.load_vector('./storage') # 加载本地的数据库
68 |
69 | embedding = JinaEmbedding("your model path")
70 |
71 | question = 'git的分支原理?'
72 |
73 | content = vector.query(question, EmbeddingModel=embedding, k=1)[0]
74 |
75 | chat = OpenAIChat(model='gpt-3.5-turbo-1106')
76 | print(chat.chat(question, [], content))
77 | ```
78 |
79 | > 如果大家的文档有中文的话,不建议使用`openai`的向量接口,可以使用智谱AI或者Jina的向量模型或接口
80 |
81 | # 实现细节
82 |
83 | ## 向量化
84 |
85 | 在这一部分共使用了三种向量化的方法,分别是`zhipu`、`jina`和`openai`。大家可以在`Embedding`文中找到实现的方式。
86 |
87 | 如果你有兴趣想使用其他的向量模型可以继承`BaseEmbeddings`类,然后实现`get_embedding`方法。
88 |
89 | ```python
90 | class BaseEmbeddings:
91 | """
92 | Base class for embeddings
93 | """
94 | def __init__(self, path: str, is_api: bool) -> None:
95 | self.path = path
96 | self.is_api = is_api
97 |
98 | def get_embedding(self, text: str, model: str) -> List[float]:
99 | raise NotImplementedError
100 |
101 | @classmethod
102 | def cosine_similarity(cls, vector1: List[float], vector2: List[float]) -> float:
103 | """
104 | calculate cosine similarity between two vectors
105 | """
106 | dot_product = np.dot(vector1, vector2)
107 | magnitude = np.linalg.norm(vector1) * np.linalg.norm(vector2)
108 | if not magnitude:
109 | return 0
110 | return dot_product / magnitude
111 | ```
112 |
113 | ## 向量检索
114 |
115 | 这里未使用任何成熟的数据库,只是简单的使用`Json`保存了文档分割后的片段和对应的向量。大家可以在`VectorBase`中找到实现的方式。
116 |
117 | 在向量检索的时候仅使用`Numpy`进行加速,代码非常容易理解和修改。
118 |
119 | ```python
120 | def query(self, query: str, EmbeddingModel: BaseEmbeddings, k: int = 1) -> List[str]:
121 | query_vector = EmbeddingModel.get_embedding(query)
122 | result = np.array([self.get_similarity(query_vector, vector)
123 | for vector in self.vectors])
124 | return np.array(self.document)[result.argsort()[-k:][::-1]]
125 | ```
126 |
127 | > 没有考虑生产环境使用,仅供学习使用
128 |
129 | ## LLM 模型
130 |
131 | 这里支持了`openai`模型和`InternLM2`模型,如果想要用其他的模型,大家可以在`LLM`中找到实现的方式。继承以下基类,然后在此基础上进行修改即可。
132 |
133 | ```python
134 | class BaseModel:
135 | def __init__(self, path: str = '') -> None:
136 | self.path = path
137 |
138 | def chat(self, prompt: str, history: List[dict], content: str) -> str:
139 | pass
140 |
141 | def load_model(self):
142 | pass
143 | ```
144 |
145 |
146 | # 参考文献
147 |
148 | | Name | Paper Link |
149 | | ------------------------------------------------------------ | ----------------------------------------- |
150 | | When Large Language Models Meet Vector Databases: A Survey | [paper](http://arxiv.org/abs/2402.01763) |
151 | | Retrieval-Augmented Generation for Large Language Models: A Survey | [paper](https://arxiv.org/abs/2312.10997) |
152 | | Learning to Filter Context for Retrieval-Augmented Generation | [paper](http://arxiv.org/abs/2311.08377) |
153 | | In-Context Retrieval-Augmented Language Models | [paper](https://arxiv.org/abs/2302.00083) |
154 |
--------------------------------------------------------------------------------
/data/2024-01-23_10-07-23/Git教程.md:
--------------------------------------------------------------------------------
1 | # Git教程
2 |
3 |
4 | # 基础篇
5 |
6 | ## Git简介
7 |
8 | Git 是一个开源的分布式版本控制系统,用于敏捷高效地处理任何或小或大的项目。Git 由 Linus Torvalds 创建,最初目的是为更好地管理 Linux 内核开发而设计。它允许多个开发者在同一个项目上工作,而不必担心彼此的工作可能会发生冲突。
9 |
10 | ## 安装Git
11 |
12 | 在不同的操作系统上安装 Git 的步骤略有不同:
13 |
14 | - 在 Windows 上,可以从 [Git 官网](https://git-scm.com/) 下载安装程序并运行。
15 | - 在 Mac OS X 上,可以通过 Homebrew 安装 Git:
16 |
17 | ```bash
18 | brew install git
19 | ```
20 |
21 | - 在 Linux 上,可以使用包管理器安装 Git,例如在 Ubuntu 上:
22 |
23 | ```bash
24 | sudo apt-get update
25 | sudo apt-get install git
26 | ```
27 |
28 | ## Git基本配置
29 |
30 | 配置用户信息是使用 Git 的第一步。在提交时,这些信息会记录在提交历史中。
31 |
32 | ```bash
33 | git config --global user.name "你的名字"
34 | git config --global user.email "你的邮箱"
35 | ```
36 |
37 | 还可以检查所有配置信息:
38 |
39 | ```bash
40 | git config --list
41 | ```
42 |
43 | ## 创建仓库
44 |
45 | 要初始化一个新的 Git 仓库,使用 `git init` 命令:
46 |
47 | ```bash
48 | git init
49 | ```
50 |
51 | 这将创建一个名为 `.git` 的子目录,其中包含所有的仓库元数据。
52 |
53 | ## 版本控制流程
54 |
55 | Git 的版本控制流程通常包括:工作区的更改、暂存更改以及提交更改到仓库。
56 |
57 | 1. 查看文件状态:
58 |
59 | ```bash
60 | git status
61 | ```
62 |
63 | 2. 将文件添加到暂存区:
64 |
65 | ```bash
66 | git add <文件名>
67 | ```
68 |
69 | 3. 提交更改:
70 |
71 | ```bash
72 | git commit -m "提交信息"
73 | ```
74 |
75 | ## 文件状态与工作区
76 |
77 | Git 中的文件有三种状态:已提交(committed)、已修改(modified)和已暂存(staged)。一个工作区包含了实际的文件,而暂存区是一个准备好下次提交的文件列表。
78 |
79 | ## 提交更改
80 |
81 | 提交是 Git 中的基本操作,它会将暂存区的更改记录到仓库中。每次提交都会在仓库中创建一个快照,并允许之后恢复到该状态。
82 |
83 | ```bash
84 | git commit -m "描述性的提交信息"
85 | ```
86 |
87 | ## 查看提交历史
88 |
89 | 要查看提交历史,可以使用 `git log` 命令:
90 |
91 | ```bash
92 | git log
93 | ```
94 |
95 | 还可以使用多种选项来定制显示的日志输出。
96 |
97 | ## 撤销操作
98 |
99 | 如果需要撤销操作,Git 提供了几个命令:
100 |
101 | - 撤销工作区的修改:
102 |
103 | ```bash
104 | git checkout -- <文件名>
105 | ```
106 |
107 | - 撤销暂存区的文件:
108 |
109 | ```bash
110 | git reset HEAD <文件名>
111 | ```
112 |
113 | - 撤销提交(创建一个新的提交来撤销之前的提交):
114 |
115 | ```bash
116 | git revert <提交ID>
117 | ```
118 |
119 | ## 标签管理
120 |
121 | 标签是指向特定提交的引用,通常用于版本发布。创建一个新标签:
122 |
123 | ```bash
124 | git tag <标签名>
125 | ```
126 |
127 | 列出所有标签:
128 |
129 | ```bash
130 | git tag
131 | ```
132 |
133 | 删除标签:
134 |
135 | ```bash
136 | git tag -d <标签名>
137 | ```
138 |
139 | 查看标签信息:
140 |
141 | ```bash
142 | git show <标签名>
143 | ```
144 |
145 | 推送标签到远程仓库:
146 |
147 | ```bash
148 | git push origin <标签名>
149 | ```
150 |
151 |
152 | # 分支管理
153 |
154 | ## 分支的概念
155 |
156 | 在Git中,分支是用来隔离开发工作的。每个分支都是一个独立的开发环境,互不影响。分支可以很方便地被创建和合并,因此许多开发者使用分支来进行特性开发、修复bug或者尝试新想法。
157 |
158 | Git的一个核心概念是几乎所有操作都是本地执行的,分支也不例外。这意味着你在本地创建或切换分支,不需要与远程仓库进行通信。
159 |
160 | ## 创建与合并分支
161 |
162 | 在Git中创建新分支可以使用`git branch`命令,合并分支则使用`git merge`命令。
163 |
164 | ```bash
165 | # 创建新分支
166 | git branch
167 |
168 | # 切换到新分支
169 | git checkout
170 |
171 | # 创建新分支并立即切换到该分支
172 | git checkout -b
173 |
174 | # 合并指定分支到当前分支
175 | git merge
176 | ```
177 |
178 | ## 分支策略
179 |
180 | 合理的分支策略可以帮助团队更有效地协作。一种常见的策略是Git Flow,它定义了一个围绕项目发布的分支模型,包括功能分支、发布分支、维护分支等。
181 |
182 | 另一种策略是GitHub Flow,它更加简单灵活,适合持续交付的项目。在GitHub Flow中,`master`分支通常是稳定的,并且随时可以部署。所有新的开发都在基于`master`的特性分支上进行,一旦完成就可以合并回`master`。
183 |
184 | ## 解决冲突
185 |
186 | 当两个分支修改了同一部分代码并尝试合并时,就可能会出现冲突。Git无法自动合并这些更改,需要人工介入解决。
187 |
188 | 解决冲突的过程通常包括以下步骤:
189 |
190 | 1. 运行`git merge`,Git会提示冲突发生。
191 | 2. 打开冲突文件,查找所有标记为冲突的地方,这些地方会被特殊的标记符号包围。
192 | 3. 编辑文件,解决所有冲突。
193 | 4. 使用`git add`命令标记冲突已解决。
194 | 5. 完成合并操作,如果需要,可以通过`git commit`命令提交更改。
195 |
196 | ```bash
197 | # 解决冲突后,添加文件标记冲突已解决
198 | git add
199 |
200 | # 提交解决冲突后的合并
201 | git commit -m "Resolve merge conflict"
202 | ```
203 |
204 | ## 分支合并策略
205 |
206 | Git提供了不同的分支合并策略,例如默认的`merge`策略,它会创建一个新的合并提交来合并两个分支的历史。
207 |
208 | 另一种策略是`rebase`,它会将一个分支的提交重新应用到另一个分支上。这样可以创建一个更线性的提交历史。
209 |
210 | ```bash
211 | # 使用rebase合并分支
212 | git checkout
213 | git rebase
214 |
215 | # 如果在rebase过程中遇到冲突,解决冲突后
216 | git add
217 | git rebase --continue
218 |
219 | # 完成rebase后,切换回基础分支并合并特性分支
220 | git checkout
221 | git merge
222 | ```
223 |
224 | 使用`rebase`的好处是可以避免不必要的合并提交,但它会改变历史,因此在共享的分支上使用时需要谨慎。
225 |
226 |
227 | # 远程仓库
228 |
229 | ## 远程仓库的作用
230 |
231 | 远程仓库是位于互联网或其他网络中的服务器上的 Git 仓库。它可以让多个开发者共享一个项目,而不必将所有的文件和版本历史存储在本地计算机上。远程仓库的主要作用包括:
232 |
233 | - **版本控制**:帮助团队成员之间同步和管理代码变更。
234 | - **备份**:防止本地数据丢失后可以从远程仓库恢复。
235 | - **协作**:多人可以同时工作在同一个项目上,提高开发效率。
236 | - **代码审查**:通过 Pull Requests (PRs) 等机制可以进行代码审查。
237 |
238 | ## 添加远程仓库
239 |
240 | 要添加新的远程仓库,可以使用 `git remote add` 命令。该命令需要两个参数:远程仓库的名称和远程仓库的 URL。
241 |
242 | ```bash
243 | git remote add
244 | ```
245 |
246 | 例如,添加一个名为 `origin` 的远程仓库:
247 |
248 | ```bash
249 | git remote add origin https://github.com/username/repository.git
250 | ```
251 |
252 | ## 推送到远程仓库
253 |
254 | 将本地的更改推送到远程仓库,可以使用 `git push` 命令。通常,这个命令后面会跟远程仓库的名称和要推送的分支名称。
255 |
256 | ```bash
257 | git push
258 | ```
259 |
260 | 例如,将本地的 `master` 分支推送到 `origin` 远程仓库:
261 |
262 | ```bash
263 | git push origin master
264 | ```
265 |
266 | ## 从远程仓库拉取
267 |
268 | 从远程仓库获取最新的更改并合并到本地分支,可以使用 `git pull` 命令。这个命令会将远程仓库的指定分支的更改拉取到当前分支。
269 |
270 | ```bash
271 | git pull
272 | ```
273 |
274 | 例如,从 `origin` 远程仓库的 `master` 分支拉取最新更改:
275 |
276 | ```bash
277 | git pull origin master
278 | ```
279 |
280 | ## 远程分支管理
281 |
282 | 查看远程分支,可以使用 `git branch` 命令加上 `-r` 选项。
283 |
284 | ```bash
285 | git branch -r
286 | ```
287 |
288 | 删除远程分支,可以使用 `git push` 命令加上 `--delete` 选项。
289 |
290 | ```bash
291 | git push --delete
292 | ```
293 |
294 | 例如,删除 `origin` 远程仓库的 `feature` 分支:
295 |
296 | ```bash
297 | git push origin --delete feature
298 | ```
299 |
300 | ## 远程仓库的协作与贡献
301 |
302 | 协作和贡献通常涉及以下步骤:
303 |
304 | 1. **Fork** 远程仓库。
305 | 2. **Clone** Fork 后的仓库到本地。
306 | 3. 创建新的**分支**进行开发。
307 | 4. 完成开发后,将分支**推送**到自己的 Fork 仓库。
308 | 5. 在原仓库发起 **Pull Request** (PR)。
309 | 6. 维护者**审查代码**,并将其**合并**到主仓库。
310 |
311 | 例如,将本地分支 `feature` 推送到自己 Fork 的远程仓库:
312 |
313 | ```bash
314 | git push origin feature
315 | ```
316 |
317 | 之后,在 GitHub 或其他托管服务上发起 Pull Request。
318 |
319 |
320 | # 高级篇
321 |
322 | ## 变基
323 |
324 | 变基(Rebase)是Git中用于整理提交历史的一种工具。它的主要作用是将一系列的提交按照原有顺序复制到另一个基底上。
325 |
326 | ### 基本原理
327 |
328 | 当你进行变基操作时,Git会找到这些提交和目标基底(即你想要变基到的提交)的最近共同祖先,然后将每个提交从这个共同祖先开始重新应用。这样,你的提交历史就会看起来像是从目标基底直接分支出来的。
329 |
330 | ### 使用变基
331 |
332 | ```bash
333 | # 将当前分支变基到指定的
334 | git rebase
335 | ```
336 |
337 | ## 暂存区管理
338 |
339 | 暂存区(Staging Area)是Git中的一个概念,它是一个准备提交的更改列表。
340 |
341 | ### 基本原理
342 |
343 | 当你执行`git add`命令时,更改就会被添加到暂存区。然后你可以使用`git commit`将这些更改提交到仓库。
344 |
345 | ### 操作暂存区
346 |
347 | ```bash
348 | # 添加文件到暂存区
349 | git add
350 |
351 | # 查看暂存区状态
352 | git status
353 |
354 | # 取消暂存
355 | git reset HEAD
356 | ```
357 |
358 | ## Git钩子
359 |
360 | Git钩子(Hooks)是在Git执行特定事件(如提交和合并)时触发的脚本。
361 |
362 | ### 基本原理
363 |
364 | Git钩子存放在仓库的`.git/hooks`目录下。当触发相应的事件时,Git会执行这个目录下的脚本。
365 |
366 | ### 使用Git钩子
367 |
368 | ```bash
369 | # 编辑钩子脚本
370 | vim .git/hooks/
371 |
372 | # 使钩子脚本可执行
373 | chmod +x .git/hooks/
374 | ```
375 |
376 | ## 子模块
377 |
378 | 子模块(Submodules)允许你将一个Git仓库作为另一个Git仓库的子目录。
379 |
380 | ### 基本原理
381 |
382 | 使用子模块可以帮助你管理项目中的第三方代码库。
383 |
384 | ### 使用子模块
385 |
386 | ```bash
387 | # 添加子模块
388 | git submodule add
389 |
390 | # 初始化子模块
391 | git submodule init
392 |
393 | # 更新子模块
394 | git submodule update
395 | ```
396 |
397 | ## Git LFS(大文件存储)
398 |
399 | Git LFS(Large File Storage)是一个Git扩展,用于改善大文件的存储和访问。
400 |
401 | ### 基本原理
402 |
403 | Git LFS 通过将大文件的内容替换为指针,实际内容存储在服务器上,从而避免了大文件在仓库中的直接存储。
404 |
405 | ### 使用Git LFS
406 |
407 | ```bash
408 | # 安装Git LFS
409 | git lfs install
410 |
411 | # 跟踪大文件
412 | git lfs track "*.psd"
413 |
414 | # 提交更改
415 | git add .gitattributes
416 | git commit -m "Track .psd files using Git LFS"
417 | ```
418 |
419 |
420 | # 实用技巧
421 |
422 | ## 撤销与重做
423 |
424 | 在使用Git时,我们有时会需要撤销之前的操作或者重做操作。以下是一些常用的撤销与重做操作命令:
425 |
426 | ### 撤销工作目录中的修改
427 |
428 | 如果你对文件进行了修改,但是还没有进行提交,你可以使用以下命令来撤销工作目录中的修改:
429 |
430 | ```bash
431 | git checkout --
432 | ```
433 |
434 | ### 撤销暂存区的文件
435 |
436 | 如果你已经使用`git add`将文件添加到暂存区,但是想要撤销这一操作,可以使用以下命令:
437 |
438 | ```bash
439 | git reset HEAD
440 | ```
441 |
442 | ### 撤销提交
443 |
444 | 如果你已经进行了提交,但是想要撤销这次提交,可以使用以下命令:
445 |
446 | ```bash
447 | git revert
448 | ```
449 |
450 | 其中``是你想要撤销的提交的哈希值。
451 |
452 | ### 重做提交
453 |
454 | 如果你撤销了某次提交,但是后来又决定这次提交是正确的,想要重新应用这次提交,可以使用以下命令:
455 |
456 | ```bash
457 | git reset --hard
458 | ```
459 |
460 | 这将会重置当前分支到指定的提交。
461 |
462 | ## 日志搜索技巧
463 |
464 | Git提供了强大的日志搜索功能,可以帮助我们快速找到特定的提交信息。
465 |
466 | ### 搜索提交日志
467 |
468 | 使用以下命令可以搜索提交日志:
469 |
470 | ```bash
471 | git log --grep=
472 | ```
473 |
474 | 其中``是你想要搜索的关键词或正则表达式。
475 |
476 | ### 查看特定文件的变更记录
477 |
478 | 如果你只对某个特定文件的变更记录感兴趣,可以使用以下命令:
479 |
480 | ```bash
481 | git log -p
482 | ```
483 |
484 | 这将显示该文件的每次提交差异。
485 |
486 | ### 查看某个范围内的提交
487 |
488 | 你也可以指定查看某个时间范围内的提交:
489 |
490 | ```bash
491 | git log --since="2 weeks ago" --until="3 days ago"
492 | ```
493 |
494 | 这将显示从两周前到三天前的所有提交。
495 |
496 | ## 搭建Git服务器
497 |
498 | 搭建Git服务器可以让团队成员共享代码库和协作开发。以下是搭建Git服务器的基本步骤:
499 |
500 | ### 安装Git
501 |
502 | 首先确保服务器上安装了Git:
503 |
504 | ```bash
505 | sudo apt-get install git
506 | ```
507 |
508 | ### 创建一个裸仓库
509 |
510 | 在服务器上创建一个裸仓库:
511 |
512 | ```bash
513 | git init --bare
514 | ```
515 |
516 | ### 设置SSH访问
517 |
518 | 确保团队成员的SSH公钥被添加到服务器的`~/.ssh/authorized_keys`文件中,以便他们可以通过SSH访问仓库。
519 |
520 | ## Git与持续集成
521 |
522 | Git可以与持续集成(CI)系统结合使用,以自动化代码的构建、测试和部署流程。
523 |
524 | ### 集成CI服务
525 |
526 | 你可以选择一个CI服务,如Jenkins、Travis CI或CircleCI,并按照服务提供商的指南将其与你的Git仓库集成。
527 |
528 | ### 配置构建脚本
529 |
530 | 在你的项目中添加一个构建脚本,例如`.travis.yml`或`Jenkinsfile`,并配置构建、测试和部署的命令。
531 |
532 | ### 自动触发构建
533 |
534 | 每当有新的提交推送到仓库时,CI服务会自动触发构建流程,并反馈构建结果。
535 |
536 | ## Git工作流程
537 |
538 | Git工作流程是指团队使用Git进行协作开发的一系列规范流程。以下是一些常见的Git工作流程:
539 |
540 | ### Feature Branch Workflow
541 |
542 | 特性分支工作流程中,每个新功能都在独立的分支上开发,完成后再合并到主分支:
543 |
544 | ```bash
545 | git checkout -b feature_branch
546 | # 开发新功能
547 | git commit -am "Add new feature"
548 | git checkout master
549 | git merge feature_branch
550 | ```
551 |
552 | ### Gitflow Workflow
553 |
554 | Gitflow工作流程定义了一个围绕项目发布的严格分支模型,包括功能分支、发布分支和维护分支。
555 |
556 | ### Forking Workflow
557 |
558 | 在Forking工作流程中,每个贡献者都有自己的服务器端仓库,他们可以自由地推送提交,然后通过拉取请求来贡献代码。
559 |
560 | 以上是对实用技巧模块的详细介绍。
561 |
562 |
563 | # 附录
564 |
565 | ## 常用Git命令清单
566 |
567 | 在使用Git进行版本控制时,以下是一些常用的命令:
568 |
569 | - `git init`:在当前目录中初始化一个新的Git仓库。
570 | - `git clone [url]`:克隆一个仓库到本地目录。
571 | - `git add [file]`:将文件添加到暂存区。
572 | - `git commit -m "[commit message]"`:将暂存区的内容提交到仓库。
573 | - `git status`:查看仓库当前的状态,显示有变更的文件。
574 | - `git push [alias] [branch]`:将本地分支的更新推送到远程仓库。
575 | - `git pull [alias] [branch]`:从远程仓库获取最新版本并合并到本地。
576 | - `git branch`:列出所有本地分支。
577 | - `git branch -a`:列出所有本地分支和远程分支。
578 | - `git branch [branch-name]`:创建新分支。
579 | - `git checkout [branch-name]`:切换到指定分支。
580 | - `git merge [branch]`:合并指定分支到当前分支。
581 | - `git log`:查看提交历史。
582 | - `git diff`:查看未暂存的文件更新了哪些部分。
583 | - `git reset`:重置当前HEAD到指定状态。
584 |
585 | ## Git配置文件解析
586 |
587 | Git配置文件`.gitconfig`通常位于用户主目录下,用于配置用户级别的Git选项。
588 |
589 | ```ini
590 | [user]
591 | name = Your Name
592 | email = you@example.com
593 | [alias]
594 | co = checkout
595 | br = branch
596 | ci = commit
597 | st = status
598 | ```
599 |
600 | - `[user]`部分用于设置提交代码时的用户信息。
601 | - `[alias]`部分可以设置命令的别名,简化命令输入。
602 |
603 | ## Git错误处理
604 |
605 | 处理Git错误时,首先应该使用`git status`和`git log`检查当前状态和历史提交。以下是一些常见的Git错误处理方法:
606 |
607 | - 当遇到合并冲突时,需要手动编辑文件解决冲突,然后使用`git add [file]`标记为已解决,最后提交。
608 | - 如果需要撤销最近的提交,可以使用`git reset --hard HEAD^`回退到上一个提交状态。
609 | - 当本地分支落后于远程分支,需要合并远程变更时,可以使用`git pull`来更新本地分支。
610 |
611 | ## 参考资料与进阶阅读
612 |
613 | 以下是一些推荐的参考资料和进阶阅读:
614 |
615 | - Pro Git书籍:深入理解Git的原理和使用方法。
616 | - Git官方文档:提供详细的命令参考和使用场景。
617 | - Git社区论坛:在社区中与其他开发者交流心得和技巧。
--------------------------------------------------------------------------------
/data/2024-01-23_10-10-05/Git教程.md:
--------------------------------------------------------------------------------
1 | # Git教程
2 |
3 |
4 | # Git简介
5 |
6 | ## 什么是Git
7 |
8 | Git是一种分布式版本控制系统,用于跟踪文件的变化并协作开发。它可以记录文件的修改历史,并允许多人在同一项目上进行协作开发。
9 |
10 | ## Git的优势
11 |
12 | - 分布式:每个开发者都拥有整个代码库的完整历史记录,无需依赖中央服务器。
13 | - 高效:Git的分支和合并操作非常快速,使得并行开发变得更加容易。
14 | - 强大的支持:Git支持大型项目、快速的存储和高效的处理能力。
15 |
16 | ```bash
17 | # 创建一个新的Git仓库
18 | git init
19 | ```
20 |
21 | ```bash
22 | # 克隆一个现有的Git仓库
23 | git clone <仓库地址>
24 | ```
25 |
26 | ```bash
27 | # 将文件添加到暂存区
28 | git add <文件名>
29 | ```
30 |
31 | ```bash
32 | # 提交文件
33 | git commit -m "提交说明"
34 | ```
35 |
36 |
37 | # Git基础
38 |
39 | ## Git的安装
40 |
41 | 首先,您需要下载适用于您操作系统的Git安装程序。然后,按照安装向导的步骤进行安装。
42 |
43 | ## 创建仓库
44 |
45 | 要在Git中创建一个新的仓库,可以使用以下命令:
46 |
47 | ```bash
48 | git init
49 | ```
50 |
51 | 这将在当前目录中创建一个新的Git仓库。
52 |
53 | ## 添加文件
54 |
55 | 要将文件添加到Git仓库,可以使用以下命令:
56 |
57 | ```bash
58 | git add <文件名>
59 | ```
60 |
61 | 这将把指定的文件添加到暂存区。
62 |
63 | ## 提交更改
64 |
65 | 一旦您对文件进行了修改并将其添加到暂存区,您可以使用以下命令提交更改:
66 |
67 | ```bash
68 | git commit -m "提交说明"
69 | ```
70 |
71 | 这将提交您所做的更改并将其保存到仓库中。
72 |
73 | ## 查看提交历史
74 |
75 | 要查看Git仓库的提交历史,可以使用以下命令:
76 |
77 | ```bash
78 | git log
79 | ```
80 |
81 | 这将显示所有的提交历史记录,包括提交者信息、提交时间和提交说明。
82 |
83 | 以上就是Git基础模块的内容。
84 |
85 |
86 | # 分支管理
87 |
88 | ## 创建分支
89 |
90 | 要创建一个新的分支,可以使用以下命令:
91 |
92 | ```bash
93 | git branch
94 | ```
95 |
96 | 这将创建一个名为``的新分支,但并不会自动切换到这个分支。
97 |
98 | ## 切换分支
99 |
100 | 要切换到已经存在的分支,可以使用以下命令:
101 |
102 | ```bash
103 | git checkout
104 | ```
105 |
106 | 这将使当前工作目录切换到名为``的分支上。
107 |
108 | ## 合并分支
109 |
110 | 要将一个分支的更改合并到当前分支,可以使用以下命令:
111 |
112 | ```bash
113 | git merge
114 | ```
115 |
116 | 这将把名为``的分支合并到当前分支上。
117 |
118 | ## 解决冲突
119 |
120 | 在合并分支时,如果发生冲突,需要手动解决冲突。可以通过编辑文件来解决冲突,然后使用以下命令标记文件为已解决冲突的状态:
121 |
122 | ```bash
123 | git add
124 | ```
125 |
126 | 解决完所有冲突后,可以继续合并分支。
127 |
128 | 以上是关于Git分支管理的基本操作。
129 |
130 |
131 | # 远程仓库
132 |
133 | ## 添加远程仓库
134 |
135 | 要将本地仓库与远程仓库关联,可以使用以下命令:
136 |
137 | ```bash
138 | git remote add origin 远程仓库地址
139 | ```
140 |
141 | 其中,`origin`是远程仓库的别名,可以根据实际情况自行命名。
142 |
143 | ## 推送到远程仓库
144 |
145 | 将本地提交推送到远程仓库可以使用以下命令:
146 |
147 | ```bash
148 | git push origin 分支名
149 | ```
150 |
151 | 例如,将本地的`master`分支推送到远程仓库可以使用:
152 |
153 | ```bash
154 | git push origin master
155 | ```
156 |
157 | ## 从远程仓库拉取
158 |
159 | 从远程仓库拉取最新代码到本地可以使用以下命令:
160 |
161 | ```bash
162 | git pull origin 分支名
163 | ```
164 |
165 | 例如,从远程仓库拉取`master`分支的最新代码可以使用:
166 |
167 | ```bash
168 | git pull origin master
169 | ```
170 |
171 | ## 解决冲突
172 |
173 | 在拉取或合并代码时,如果出现冲突,需要手动解决冲突并提交。可以通过编辑文件解决冲突后,再执行以下命令提交解决:
174 |
175 | ```bash
176 | git add .
177 | git commit -m "解决冲突"
178 | git push origin 分支名
179 | ```
180 |
181 | 以上是关于远程仓库操作的基本内容。
182 |
183 |
184 | ### 高级主题
185 |
186 | #### 标签
187 |
188 | 在Git中,标签是用来标记特定提交的版本号的。通过给提交打上标签,可以方便地在需要的时候找到该提交。创建标签可以使用`git tag`命令,例如:
189 |
190 | ```bash
191 | git tag v1.0.0
192 | ```
193 |
194 | #### 忽略文件
195 |
196 | 有时候我们希望Git在进行版本控制时忽略某些文件,比如临时文件或者编译生成的文件。可以通过在项目根目录下创建一个名为`.gitignore`的文件,并在其中指定需要忽略的文件模式,例如:
197 |
198 | ```plaintext
199 | *.log
200 | build/
201 | ```
202 |
203 | #### 撤销操作
204 |
205 | 在Git中,有时候我们需要撤销之前的操作,比如撤销暂存的文件或者撤销已提交的修改。可以使用`git reset`命令来撤销暂存的文件,使用`git revert`命令来撤销已提交的修改。
206 |
207 | #### Git工作流
208 |
209 | Git工作流是指团队协作时如何使用Git进行版本控制和代码管理的一种约定。常见的Git工作流包括集中式工作流、特性分支工作流、Gitflow工作流等。选择合适的工作流对团队的协作效率有很大的影响。
210 |
211 |
212 | # 实用技巧
213 |
214 | ## 查看差异
215 |
216 | 要查看文件的差异,可以使用以下命令:
217 |
218 | ```bash
219 | git diff
220 | ```
221 |
222 | ## 修改最后一次提交
223 |
224 | 如果需要修改最后一次提交的信息,可以使用以下命令:
225 |
226 | ```bash
227 | git commit --amend
228 | ```
229 |
230 | ## 临时存储修改
231 |
232 | 使用以下命令可以将当前工作目录中的修改临时存储起来:
233 |
234 | ```bash
235 | git stash
236 | ```
237 |
238 | ## 重写提交历史
239 |
240 | 如果需要重写提交历史,可以使用以下命令:
241 |
242 | ```bash
243 | git rebase -i HEAD~n
244 | ```
245 |
246 | 以上是关于Git实用技巧的详细内容。
--------------------------------------------------------------------------------
/data/2024-01-23_10-14-41/Github Api 使用.md:
--------------------------------------------------------------------------------
1 | # Github Api 使用
2 |
3 |
4 | ### Github Api 简介
5 |
6 | #### 什么是Github Api
7 |
8 | Github Api 是 Github 提供的一组用于访问和操作 Github 数据的接口。通过 Github Api,用户可以实现对仓库、提交、用户等资源的管理和操作。
9 |
10 | #### Github Api 的优势
11 |
12 | - **灵活性**:Github Api 提供了丰富的接口,可以满足各种不同的需求,用户可以根据自身需求进行定制化开发。
13 | - **整合性**:Github Api 可以与其他服务和工具进行无缝整合,例如持续集成工具、项目管理工具等,提高工作效率。
14 | - **实时性**:通过 Github Api,可以实时获取最新的仓库、提交等信息,帮助用户及时了解和响应变化。
15 |
16 | 以上是 Github Api 的简要介绍和优势。
17 |
18 |
19 | # Github Api 的基本用法
20 |
21 | ## 认证与权限
22 |
23 | 在使用 Github Api 之前,我们需要进行认证以获取相应的权限。Github Api 使用 OAuth 2.0 进行认证,我们可以通过申请一个个人访问令牌(Personal Access Token)来进行认证。
24 |
25 | ### 申请个人访问令牌
26 |
27 | 1. 登录 Github,点击头像进入 Settings。
28 | 2. 在左侧菜单中选择 Developer settings,然后点击 Personal access tokens。
29 | 3. 点击 Generate new token,填写 Token description,并勾选需要的权限。
30 | 4. 点击 Generate token,将生成的访问令牌保存好,之后将用于认证。
31 |
32 | ### 使用个人访问令牌进行认证
33 |
34 | 在进行数据获取与操作时,需要在请求的 Header 中添加 Authorization 字段,其值为 "token \"。
35 |
36 | ## 数据获取与操作
37 |
38 | Github Api 提供了丰富的接口来获取和操作数据,包括获取仓库信息、提交记录、问题等。
39 |
40 | ### 获取仓库信息
41 |
42 | 我们可以使用 Github Api 来获取特定用户或组织的仓库信息,例如:
43 |
44 | ```python
45 | import requests
46 |
47 | url = 'https://api.github.com/users/octocat/repos'
48 | headers = {'Authorization': 'token '}
49 | response = requests.get(url, headers=headers)
50 |
51 | print(response.json())
52 | ```
53 |
54 | ### 提交操作
55 |
56 | 我们可以使用 Github Api 来创建、更新和删除提交,例如:
57 |
58 | ```python
59 | import requests
60 |
61 | url = 'https://api.github.com/repos/octocat/Hello-World/contents/test.txt'
62 | headers = {'Authorization': 'token '}
63 | data = {
64 | "message": "my commit message",
65 | "content": "bXkgbmV3IGZpbGUgY29udGVudHM=" # base64 encoded content
66 | }
67 | response = requests.put(url, headers=headers, json=data)
68 |
69 | print(response.json())
70 | ```
71 |
72 | 以上就是 Github Api 的基本用法,包括认证与权限以及数据获取与操作。通过这些基本用法,我们可以在自己的应用中使用 Github Api 来实现丰富的功能。
73 |
74 |
75 | # Github Api 的高级应用
76 |
77 | ## Webhooks
78 |
79 | Webhooks 是 Github Api 中的一项高级功能,它允许用户在特定事件发生时自动触发自定义的 HTTP 回调。通过配置 Webhooks,您可以实现对代码仓库中的各种事件进行监控和自动化处理,例如代码提交、Issue 创建等。
80 |
81 | ### 配置 Webhooks
82 |
83 | 要配置 Webhooks,您可以通过 Github 仓库的设置页面进行操作。在 Webhooks 页面,您可以添加新的 Webhook,并指定触发 Webhook 的事件类型和回调 URL。
84 |
85 | ### Webhooks 的工作原理
86 |
87 | 当配置的事件类型在仓库中发生时,Github 会向指定的回调 URL 发送 HTTP POST 请求,请求中包含有关事件的详细信息。您可以编写自定义的服务器端代码来处理这些请求,实现自动化的业务逻辑。
88 |
89 | ### 示例代码
90 |
91 | 以下是一个简单的 Node.js Express 服务器端代码示例,用于处理 Github Webhooks 的 HTTP POST 请求:
92 |
93 | ```javascript
94 | const express = require('express');
95 | const bodyParser = require('body-parser');
96 |
97 | const app = express();
98 | app.use(bodyParser.json());
99 |
100 | app.post('/webhook', (req, res) => {
101 | const event = req.get('X-GitHub-Event');
102 | // 根据 event 类型处理业务逻辑
103 | res.sendStatus(200);
104 | });
105 |
106 | app.listen(3000, () => {
107 | console.log('Webhook 服务器已启动');
108 | });
109 | ```
110 |
111 | ## Github Actions
112 |
113 | Github Actions 是 Github 提供的持续集成和持续部署(CI/CD)工具,它允许您在代码仓库中配置自定义的工作流程,以实现自动化的构建、测试和部署。
114 |
115 | ### 配置 Github Actions
116 |
117 | 要配置 Github Actions,您可以在仓库中创建一个名为 `.github/workflows` 的目录,并在该目录中添加 YAML 格式的工作流程配置文件。在配置文件中,您可以定义工作流程的触发条件、执行步骤和环境。
118 |
119 | ### Github Actions 的工作原理
120 |
121 | 当配置的触发条件满足时,Github 会自动执行相应的工作流程。您可以在工作流程中使用 Github 提供的预定义动作(actions),也可以编写自定义的脚本来实现特定的构建、测试和部署操作。
122 |
123 | ### 示例代码
124 |
125 | 以下是一个简单的 Github Actions 配置文件示例,用于在代码提交后自动运行测试并部署到服务器:
126 |
127 | ```yaml
128 | name: CI/CD
129 |
130 | on:
131 | push:
132 | branches: [ main ]
133 |
134 | jobs:
135 | build:
136 | runs-on: ubuntu-latest
137 |
138 | steps:
139 | - name: Checkout code
140 | uses: actions/checkout@v2
141 |
142 | - name: Run tests
143 | run: npm test
144 |
145 | - name: Deploy to server
146 | run: |
147 | ssh user@server 'cd /path/to/app && git pull'
148 | ```
149 |
150 | 以上是 Github Api 的高级应用中 Webhooks 和 Github Actions 的详细内容。
--------------------------------------------------------------------------------
/data/2024-01-23_11-59-03/Github Api 使用.md:
--------------------------------------------------------------------------------
1 | # Github Api 使用
2 |
3 |
4 | # Github API 简介
5 |
6 | Github API 是 Github 提供的一组接口,允许用户通过编程方式与 Github 进行交互。通过这些接口,用户可以获取 Github 仓库的信息、创建和修改仓库、管理 issue 和 pull request 等。
7 |
8 | Github API 支持多种编程语言,包括 Python、Java、Ruby 等。用户可以通过这些语言编写程序,调用 Github API 接口,实现自动化操作。
9 |
10 | # Github API 功能
11 |
12 | Github API 提供了丰富的功能,包括但不限于:
13 |
14 | - 获取仓库信息
15 | - 创建和修改仓库
16 | - 管理 issue 和 pull request
17 | - 获取用户信息
18 | - 管理用户权限
19 | - 搜索仓库和用户
20 |
21 | 以下是一个简单的示例代码,演示如何使用 Python 调用 Github API 获取仓库信息:
22 |
23 | ```python
24 | import requests
25 |
26 | def get_repo_info(owner, repo):
27 | url = f"https://api.github.com/repos/{owner}/{repo}"
28 | response = requests.get(url)
29 | if response.status_code == 200:
30 | return response.json()
31 | else:
32 | return None
33 |
34 | # 调用函数获取仓库信息
35 | repo_info = get_repo_info("octocat", "Hello-World")
36 | if repo_info:
37 | print(repo_info)
38 | else:
39 | print("获取仓库信息失败")
40 | ```
41 |
42 | 以上代码中,我们使用 `requests` 库发送 HTTP 请求,获取仓库信息。如果请求成功,则返回 JSON 格式的仓库信息;如果请求失败,则返回 None。
43 |
44 | 需要注意的是,在使用 Github API 时,需要先进行身份验证,可以通过在请求头中添加 `Authorization` 字段来实现。
45 |
46 |
47 | 目录 2
48 | ======
49 |
50 | Github Api 使用方法
51 | ------
52 |
53 | Github Api 是一种用于
54 |
55 |
56 | # Github API 常见问题
57 |
58 | 在使用 Github API 时,可能会遇到一些常见问题,以下是一些可能遇到的问题及其解决方法。
59 |
60 | ## 问题 1:无法获取
--------------------------------------------------------------------------------
/data/2024-01-23_12-01-19/Github Api 使用.md:
--------------------------------------------------------------------------------
1 | # Github Api 使用
2 |
3 |
4 | 目录 1
5 | ======
6 |
7 | Github Api 简介
8 | ------------
9 |
10 | Github API 是 Github 提供的一组接口,用于通过编程方式
11 |
12 |
13 | ## Github Api 使用方法
14 |
15 | Github Api 是一种基于RESTful架构的API,它允许用户通过HTTP请求与Github进行交互。以下是使用Github Api的基本步骤:
16 |
17 | ### 1. 获取
--------------------------------------------------------------------------------
/example.py:
--------------------------------------------------------------------------------
1 | from RAG.VectorBase import VectorStore
2 | from RAG.utils import ReadFiles
3 | from RAG.LLM import OpenAIChat, InternLMChat
4 | from RAG.Embeddings import JinaEmbedding, ZhipuEmbedding
5 |
6 |
7 | # 没有保存数据库
8 | # docs = ReadFiles('./data').get_content(max_token_len=600, cover_content=150) # 获得data目录下的所有文件内容并分割
9 | # vector = VectorStore(docs)
10 | # embedding = ZhipuEmbedding() # 创建EmbeddingModel
11 | # vector.get_vector(EmbeddingModel=embedding)
12 | # vector.persist(path='storage') # 将向量和文档内容保存到storage目录下,下次再用就可以直接加载本地的数据库
13 |
14 | # # vector.load_vector('./storage') # 加载本地的数据库
15 |
16 | # question = '正向扫描的原理是什么?'
17 |
18 | # content = vector.query(question, EmbeddingModel=embedding, k=1)[0]
19 | # chat = OpenAIChat(model='gpt-3.5-turbo-1106')
20 | # print(chat.chat(question, [], content))
21 |
22 |
23 | # 保存数据库之后
24 | vector = VectorStore()
25 |
26 | vector.load_vector('./storage') # 加载本地的数据库
27 |
28 | question = '逆向纠错的原理是什么?'
29 |
30 | embedding = ZhipuEmbedding() # 创建EmbeddingModel
31 |
32 | content = vector.query(question, EmbeddingModel=embedding, k=1)[0]
33 | chat = OpenAIChat(model='gpt-3.5-turbo-1106')
34 | print(chat.chat(question, [], content))
35 |
36 |
--------------------------------------------------------------------------------
/example_with_reranker.py:
--------------------------------------------------------------------------------
1 | import os
2 | from RAG.VectorBase import VectorStore
3 | from RAG.utils import ReadFiles
4 | from RAG.LLM import ZhipuChat
5 | from RAG.Embeddings import BgeEmbedding
6 | from RAG.Reranker import BgeReranker
7 |
8 | # 未创建向量数据库、更换数据集、或更换其他Embeddings模型后将have_created_db设置为False
9 | # 运行一次成功创建向量数据库后可以将have_created_db设置为True
10 | have_created_db = True
11 | # 请将*替换为自己的API_KEY
12 | os.environ['ZHIPUAI_API_KEY'] = "*"
13 |
14 | # 创建EmbeddingModel
15 | embedding = BgeEmbedding()
16 |
17 | # 创建RerankerModel
18 | reranker = BgeReranker()
19 |
20 | if have_created_db:
21 | # 保存数据库之后
22 | vector = VectorStore()
23 | vector.load_vector('./storage') # 加载本地的数据库
24 | else:
25 | # 没有保存数据库
26 | docs = ReadFiles('./data').get_content(max_token_len=600, cover_content=150) # 获得data目录下的所有文件内容并分割
27 | vector = VectorStore(docs)
28 | vector.get_vector(EmbeddingModel=embedding)
29 | vector.persist(path='storage') # 将向量和文档内容保存到storage目录下,下次再用就可以直接加载本地的数据库
30 |
31 | question = '远程仓库的协作与贡献有哪些?'
32 |
33 | # 从向量数据库中查询出最相似的3个文档
34 | content = vector.query(question, EmbeddingModel=embedding, k=3)
35 | # 从一阶段查询结果中用Reranker再次筛选出最相似的2个文档
36 | rerank_content = reranker.rerank(question, content, k=2)
37 | # 最后选择最相似的文档, 交给LLM作为可参考上下文
38 | best_content = rerank_content[0]
39 | chat = ZhipuChat()
40 | print(chat.chat(question, [], best_content))
41 |
--------------------------------------------------------------------------------
/images/RAG.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KMnO4-zx/TinyRAG/a0e7b40c06c49cfea9e2247b94e08dc05c051c62/images/RAG.png
--------------------------------------------------------------------------------
/images/Retrieval-Augmented Generation(RAG-Learning).png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KMnO4-zx/TinyRAG/a0e7b40c06c49cfea9e2247b94e08dc05c051c62/images/Retrieval-Augmented Generation(RAG-Learning).png
--------------------------------------------------------------------------------
/paper.md:
--------------------------------------------------------------------------------
1 | # RAG (Retrieved-Augmented Generation) for LLM:A Curated Collection
2 |
3 | This Markdown is dedicated to curating high-quality papers, resources, and tools related to RAG in the context of Large Language Models (LLM). RAG bridges the gap between retrieval-based and generation-based methods, offering a promising approach for knowledge-intensive tasks.
4 |
5 | | Name | Paper Link |
6 | | ------------------------------------------------------------ | ----------------------------------------- |
7 | | When Large Language Models Meet Vector Databases: A Survey | [paper](http://arxiv.org/abs/2402.01763) |
8 | | Retrieval-Augmented Generation for Large Language Models: A Survey | [paper](https://arxiv.org/abs/2312.10997) |
9 | | Learning to Filter Context for Retrieval-Augmented Generation | [paper](http://arxiv.org/abs/2311.08377) |
10 | | In-Context Retrieval-Augmented Language Models | [paper](https://arxiv.org/abs/2302.00083) |
11 |
12 |
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | openai
2 | zhipuai
3 | numpy
4 | python-dotenv
5 | torch
6 | torchvision
7 | torchaudio
8 | transformers
9 | tqdm
10 | PyPDF2
11 | markdown
12 | html2text
13 | tiktoken
14 | beautifulsoup4
15 |
--------------------------------------------------------------------------------
/storage/doecment.json:
--------------------------------------------------------------------------------
1 | ["Git教程\n基础篇\nGit简介\nGit是一个开源的分布式版本控制系统,用于敏捷高效地处理任何或小或大的项目。Git由LinusTorvalds创建,最初目的是为更好地管理Linux内核开发而设计。它允许多个开发者在同一个项目上工作,而不必担心彼此的工作可能会发生冲突。\n安装Git\n在不同的操作系统上安装Git的步骤略有不同:\n\n在Windows上,可以从Git官网下载安装程序并运行。\n在MacOSX上,可以通过Homebrew安装Git:\n\nbash\nbrewinstallgit\n\n在Linux上,可以使用包管理器安装Git,例如在Ubuntu上:\n\nbash\nsudoapt-getupdate\nsudoapt-getinstallgit\nGit基本配置\n配置用户信息是使用Git的第一步。在提交时,这些信息会记录在提交历史中。\nbash\ngitconfig--globaluser.name\"你的名字\"\ngitconfig--globaluser.email\"你的邮箱\"\n还可以检查所有配置信息:\nbash\ngitconfig--list\n创建仓库\n要初始化一个新的Git仓库,使用gitinit命令:\nbash\ngitinit\n这将创建一个名为.git的子目录,其中包含所有的仓库元数据。\n版本控制流程\nGit的版本控制流程通常包括:工作区的更改、暂存更改以及提交更改到仓库。\n\n查看文件状态:\n\nbash\ngitstatus\n\n将文件添加到暂存区:\n\nbash\ngitadd<文件名>\n\n提交更改:\n\nbash\ngitcommit-m\"提交信息\"\n文件状态与工作区\n", "含所有的仓库元数据。\n版本控制流程\nGit的版本控制流程通常包括:工作区的更改、暂存更改以及提交更改到仓库。\n\n查看文件状态:\n\nbash\ngitstatus\n\n将文件添加到暂存区:\n\nbash\ngitadd<文件名>\n\n提交更改:\n\nbash\ngitcommit-m\"提交信息\"\n文件状态与工作区\nGit中的文件有三种状态:已提交(committed)、已修改(modified)和已暂存(staged)。一个工作区包含了实际的文件,而暂存区是一个准备好下次提交的文件列表。提交更改\n提交是Git中的基本操作,它会将暂存区的更改记录到仓库中。每次提交都会在仓库中创建一个快照,并允许之后恢复到该状态。\nbash\ngitcommit-m\"描述性的提交信息\"\n查看提交历史\n要查看提交历史,可以使用gitlog命令:\nbash\ngitlog\n还可以使用多种选项来定制显示的日志输出。\n撤销操作\n如果需要撤销操作,Git提供了几个命令:\n\n撤销工作区的修改:\n\nbash\ngitcheckout--<文件名>\n\n撤销暂存区的文件:\n\nbash\ngitresetHEAD<文件名>\n\n撤销提交(创建一个新的提交来撤销之前的提交):\n\nbash\ngitrevert<提交ID>\n标签管理\n", "\n撤销操作\n如果需要撤销操作,Git提供了几个命令:\n\n撤销工作区的修改:\n\nbash\ngitcheckout--<文件名>\n\n撤销暂存区的文件:\n\nbash\ngitresetHEAD<文件名>\n\n撤销提交(创建一个新的提交来撤销之前的提交):\n\nbash\ngitrevert<提交ID>\n标签管理\n标签是指向特定提交的引用,通常用于版本发布。创建一个新标签:bash\ngittag<标签名>\n列出所有标签:\nbash\ngittag\n删除标签:\nbash\ngittag-d<标签名>\n查看标签信息:\nbash\ngitshow<标签名>\n推送标签到远程仓库:\nbash\ngitpushorigin<标签名>\n分支管理\n分支的概念\n在Git中,分支是用来隔离开发工作的。每个分支都是一个独立的开发环境,互不影响。分支可以很方便地被创建和合并,因此许多开发者使用分支来进行特性开发、修复bug或者尝试新想法。\nGit的一个核心概念是几乎所有操作都是本地执行的,分支也不例外。这意味着你在本地创建或切换分支,不需要与远程仓库进行通信。\n创建与合并分支\n", "是用来隔离开发工作的。每个分支都是一个独立的开发环境,互不影响。分支可以很方便地被创建和合并,因此许多开发者使用分支来进行特性开发、修复bug或者尝试新想法。\nGit的一个核心概念是几乎所有操作都是本地执行的,分支也不例外。这意味着你在本地创建或切换分支,不需要与远程仓库进行通信。\n创建与合并分支\n在Git中创建新分支可以使用gitbranch命令,合并分支则使用gitmerge命令。```bash\n创建新分支\ngitbranch\n切换到新分支\ngitcheckout\n创建新分支并立即切换到该分支\ngitcheckout-b\n合并指定分支到当前分支\ngitmerge\n```\n分支策略\n合理的分支策略可以帮助团队更有效地协作。一种常见的策略是GitFlow,它定义了一个围绕项目发布的分支模型,包括功能分支、发布分支、维护分支等。\n另一种策略是GitHubFlow,它更加简单灵活,适合持续交付的项目。在GitHubFlow中,master分支通常是稳定的,并且随时可以部署。所有新的开发都在基于master的特性分支上进行,一旦完成就可以合并回master。\n解决冲突\n", "绕项目发布的分支模型,包括功能分支、发布分支、维护分支等。\n另一种策略是GitHubFlow,它更加简单灵活,适合持续交付的项目。在GitHubFlow中,master分支通常是稳定的,并且随时可以部署。所有新的开发都在基于master的特性分支上进行,一旦完成就可以合并回master。\n解决冲突\n当两个分支修改了同一部分代码并尝试合并时,就可能会出现冲突。Git无法自动合并这些更改,需要人工介入解决。解决冲突的过程通常包括以下步骤:\n\n运行gitmerge,Git会提示冲突发生。\n打开冲突文件,查找所有标记为冲突的地方,这些地方会被特殊的标记符号包围。\n编辑文件,解决所有冲突。\n使用gitadd命令标记冲突已解决。\n完成合并操作,如果需要,可以通过gitcommit命令提交更改。\n\n```bash\n解决冲突后,添加文件标记冲突已解决\ngitadd\n提交解决冲突后的合并\ngitcommit-m\"Resolvemergeconflict\"\n```\n分支合并策略\nGit提供了不同的分支合并策略,例如默认的merge策略,它会创建一个新的合并提交来合并两个分支的历史。\n", "令提交更改。\n\n```bash\n解决冲突后,添加文件标记冲突已解决\ngitadd\n提交解决冲突后的合并\ngitcommit-m\"Resolvemergeconflict\"\n```\n分支合并策略\nGit提供了不同的分支合并策略,例如默认的merge策略,它会创建一个新的合并提交来合并两个分支的历史。\n另一种策略是rebase,它会将一个分支的提交重新应用到另一个分支上。这样可以创建一个更线性的提交历史。```bash\n使用rebase合并分支\ngitcheckout\ngitrebase\n如果在rebase过程中遇到冲突,解决冲突后\ngitadd\ngitrebase--continue\n完成rebase后,切换回基础分支并合并特性分支\ngitcheckout\ngitmerge\n```\n使用rebase的好处是可以避免不必要的合并提交,但它会改变历史,因此在共享的分支上使用时需要谨慎。\n远程仓库\n远程仓库的作用\n远程仓库是位于互联网或其他网络中的服务器上的Git仓库。它可以让多个开发者共享一个项目,而不必将所有的文件和版本历史存储在本地计算机上。远程仓库的主要作用包括:\n\n版本控制:帮助团队成员之间同步和管理代码变更。\n", "合并提交,但它会改变历史,因此在共享的分支上使用时需要谨慎。\n远程仓库\n远程仓库的作用\n远程仓库是位于互联网或其他网络中的服务器上的Git仓库。它可以让多个开发者共享一个项目,而不必将所有的文件和版本历史存储在本地计算机上。远程仓库的主要作用包括:\n\n版本控制:帮助团队成员之间同步和管理代码变更。\n备份:防止本地数据丢失后可以从远程仓库恢复。协作:多人可以同时工作在同一个项目上,提高开发效率。\n代码审查:通过PullRequests(PRs)等机制可以进行代码审查。\n\n添加远程仓库\n要添加新的远程仓库,可以使用gitremoteadd命令。该命令需要两个参数:远程仓库的名称和远程仓库的URL。\nbash\ngitremoteadd\n例如,添加一个名为origin的远程仓库:\nbash\ngitremoteaddorigin\n推送到远程仓库\n将本地的更改推送到远程仓库,可以使用gitpush命令。通常,这个命令后面会跟远程仓库的名称和要推送的分支名称。\nbash\ngitpush\n例如,将本地的master分支推送到origin远程仓库:\nbash\ngitpushoriginmaster\n从远程仓库拉取\n", "远程仓库,可以使用gitpush命令。通常,这个命令后面会跟远程仓库的名称和要推送的分支名称。\nbash\ngitpush\n例如,将本地的master分支推送到origin远程仓库:\nbash\ngitpushoriginmaster\n从远程仓库拉取\n从远程仓库获取最新的更改并合并到本地分支,可以使用gitpull命令。这个命令会将远程仓库的指定分支的更改拉取到当前分支。bash\ngitpull\n例如,从origin远程仓库的master分支拉取最新更改:\nbash\ngitpulloriginmaster\n远程分支管理\n查看远程分支,可以使用gitbranch命令加上-r选项。\nbash\ngitbranch-r\n删除远程分支,可以使用gitpush命令加上--delete选项。\nbash\ngitpush--delete\n例如,删除origin远程仓库的feature分支:\nbash\ngitpushorigin--deletefeature\n远程仓库的协作与贡献\n协作和贡献通常涉及以下步骤:\n\nFork远程仓库。\nCloneFork后的仓库到本地。\n创建新的分支进行开发。\n完成开发后,将分支推送到自己的Fork仓库。\n", "如,删除origin远程仓库的feature分支:\nbash\ngitpushorigin--deletefeature\n远程仓库的协作与贡献\n协作和贡献通常涉及以下步骤:\n\nFork远程仓库。\nCloneFork后的仓库到本地。\n创建新的分支进行开发。\n完成开发后,将分支推送到自己的Fork仓库。\n在原仓库发起PullRequest(PR)。维护者审查代码,并将其合并到主仓库。\n\n例如,将本地分支feature推送到自己Fork的远程仓库:\nbash\ngitpushoriginfeature\n之后,在GitHub或其他托管服务上发起PullRequest。\n高级篇\n变基\n变基(Rebase)是Git中用于整理提交历史的一种工具。它的主要作用是将一系列的提交按照原有顺序复制到另一个基底上。\n基本原理\n当你进行变基操作时,Git会找到这些提交和目标基底(即你想要变基到的提交)的最近共同祖先,然后将每个提交从这个共同祖先开始重新应用。这样,你的提交历史就会看起来像是从目标基底直接分支出来的。\n使用变基\n```bash\n将当前分支变基到指定的\ngitrebase\n```\n暂存区管理\n", "底上。\n基本原理\n当你进行变基操作时,Git会找到这些提交和目标基底(即你想要变基到的提交)的最近共同祖先,然后将每个提交从这个共同祖先开始重新应用。这样,你的提交历史就会看起来像是从目标基底直接分支出来的。\n使用变基\n```bash\n将当前分支变基到指定的\ngitrebase\n```\n暂存区管理\n暂存区(StagingArea)是Git中的一个概念,它是一个准备提交的更改列表。基本原理\n当你执行gitadd命令时,更改就会被添加到暂存区。然后你可以使用gitcommit将这些更改提交到仓库。\n操作暂存区\n```bash\n添加文件到暂存区\ngitadd\n查看暂存区状态\ngitstatus\n取消暂存\ngitresetHEAD\n```\nGit钩子\nGit钩子(Hooks)是在Git执行特定事件(如提交和合并)时触发的脚本。\n基本原理\nGit钩子存放在仓库的.git/hooks目录下。当触发相应的事件时,Git会执行这个目录下的脚本。\n使用Git钩子\n```bash\n编辑钩子脚本\nvim.git/hooks/\n使钩子脚本可执行\nchmod+x.git/hooks/\n```\n子模块\n子模块(Submodules)允许你将一个Git仓库作为另一个Git仓库的子目录。\n基本原理\n", "录下。当触发相应的事件时,Git会执行这个目录下的脚本。\n使用Git钩子\n```bash\n编辑钩子脚本\nvim.git/hooks/\n使钩子脚本可执行\nchmod+x.git/hooks/\n```\n子模块\n子模块(Submodules)允许你将一个Git仓库作为另一个Git仓库的子目录。\n基本原理\n使用子模块可以帮助你管理项目中的第三方代码库。使用子模块\n```bash\n添加子模块\ngitsubmoduleadd\n初始化子模块\ngitsubmoduleinit\n更新子模块\ngitsubmoduleupdate\n```\nGitLFS(大文件存储)\nGitLFS(LargeFileStorage)是一个Git扩展,用于改善大文件的存储和访问。\n基本原理\nGitLFS通过将大文件的内容替换为指针,实际内容存储在服务器上,从而避免了大文件在仓库中的直接存储。\n使用GitLFS\n```bash\n安装GitLFS\ngitlfsinstall\n跟踪大文件\ngitlfstrack\"*.psd\"\n提交更改\ngitadd.gitattributes\ngitcommit-m\"Track.psdfilesusingGitLFS\"\n```\n实用技巧\n撤销与重做\n在使用Git时,我们有时会需要撤销之前的操作或者重做操作。以下是一些常用的撤销与重做操作命令:\n撤销工作目录中的修改\n", "ack\"*.psd\"\n提交更改\ngitadd.gitattributes\ngitcommit-m\"Track.psdfilesusingGitLFS\"\n```\n实用技巧\n撤销与重做\n在使用Git时,我们有时会需要撤销之前的操作或者重做操作。以下是一些常用的撤销与重做操作命令:\n撤销工作目录中的修改\n如果你对文件进行了修改,但是还没有进行提交,你可以使用以下命令来撤销工作目录中的修改:bash\ngitcheckout--\n撤销暂存区的文件\n如果你已经使用gitadd将文件添加到暂存区,但是想要撤销这一操作,可以使用以下命令:\nbash\ngitresetHEAD\n撤销提交\n如果你已经进行了提交,但是想要撤销这次提交,可以使用以下命令:\nbash\ngitrevert\n其中是你想要撤销的提交的哈希值。\n重做提交\n如果你撤销了某次提交,但是后来又决定这次提交是正确的,想要重新应用这次提交,可以使用以下命令:\nbash\ngitreset--hard\n这将会重置当前分支到指定的提交。\n日志搜索技巧\nGit提供了强大的日志搜索功能,可以帮助我们快速找到特定的提交信息。\n搜索提交日志\n使用以下命令可以搜索提交日志:\nbash\ngitlog--grep=\n", "交,可以使用以下命令:\nbash\ngitreset--hard\n这将会重置当前分支到指定的提交。\n日志搜索技巧\nGit提供了强大的日志搜索功能,可以帮助我们快速找到特定的提交信息。\n搜索提交日志\n使用以下命令可以搜索提交日志:\nbash\ngitlog--grep=\n其中是你想要搜索的关键词或正则表达式。查看特定文件的变更记录\n如果你只对某个特定文件的变更记录感兴趣,可以使用以下命令:\nbash\ngitlog-p\n这将显示该文件的每次提交差异。\n查看某个范围内的提交\n你也可以指定查看某个时间范围内的提交:\nbash\ngitlog--since=\"2weeksago\"--until=\"3daysago\"\n这将显示从两周前到三天前的所有提交。\n搭建Git服务器\n搭建Git服务器可以让团队成员共享代码库和协作开发。以下是搭建Git服务器的基本步骤:\n安装Git\n首先确保服务器上安装了Git:\nbash\nsudoapt-getinstallgit\n创建一个裸仓库\n在服务器上创建一个裸仓库:\nbash\ngitinit--bare\n设置SSH访问\n", "可以让团队成员共享代码库和协作开发。以下是搭建Git服务器的基本步骤:\n安装Git\n首先确保服务器上安装了Git:\nbash\nsudoapt-getinstallgit\n创建一个裸仓库\n在服务器上创建一个裸仓库:\nbash\ngitinit--bare\n设置SSH访问\n确保团队成员的SSH公钥被添加到服务器的~/.ssh/authorized_keys文件中,以便他们可以通过SSH访问仓库。Git与持续集成\nGit可以与持续集成(CI)系统结合使用,以自动化代码的构建、测试和部署流程。\n集成CI服务\n你可以选择一个CI服务,如Jenkins、TravisCI或CircleCI,并按照服务提供商的指南将其与你的Git仓库集成。\n配置构建脚本\n在你的项目中添加一个构建脚本,例如.travis.yml或Jenkinsfile,并配置构建、测试和部署的命令。\n自动触发构建\n每当有新的提交推送到仓库时,CI服务会自动触发构建流程,并反馈构建结果。\nGit工作流程\nGit工作流程是指团队使用Git进行协作开发的一系列规范流程。以下是一些常见的Git工作流程:\nFeatureBranchWorkflow\n", "Jenkinsfile,并配置构建、测试和部署的命令。\n自动触发构建\n每当有新的提交推送到仓库时,CI服务会自动触发构建流程,并反馈构建结果。\nGit工作流程\nGit工作流程是指团队使用Git进行协作开发的一系列规范流程。以下是一些常见的Git工作流程:\nFeatureBranchWorkflow\n特性分支工作流程中,每个新功能都在独立的分支上开发,完成后再合并到主分支:```bash\ngitcheckout-bfeature_branch\n开发新功能\ngitcommit-am\"Addnewfeature\"\ngitcheckoutmaster\ngitmergefeature_branch\n```\nGitflowWorkflow\nGitflow工作流程定义了一个围绕项目发布的严格分支模型,包括功能分支、发布分支和维护分支。\nForkingWorkflow\n在Forking工作流程中,每个贡献者都有自己的服务器端仓库,他们可以自由地推送提交,然后通过拉取请求来贡献代码。\n以上是对实用技巧模块的详细介绍。\n附录\n常用Git命令清单\n在使用Git进行版本控制时,以下是一些常用的命令:\n\ngitinit:在当前目录中初始化一个新的Git仓库。\ngitclone[url]:克隆一个仓库到本地目录。\ngitadd[file]:将文件添加到暂存区。\n", "后通过拉取请求来贡献代码。\n以上是对实用技巧模块的详细介绍。\n附录\n常用Git命令清单\n在使用Git进行版本控制时,以下是一些常用的命令:\n\ngitinit:在当前目录中初始化一个新的Git仓库。\ngitclone[url]:克隆一个仓库到本地目录。\ngitadd[file]:将文件添加到暂存区。\ngitcommit-m\"[commitmessage]\":将暂存区的内容提交到仓库。gitstatus:查看仓库当前的状态,显示有变更的文件。\ngitpush[alias][branch]:将本地分支的更新推送到远程仓库。\ngitpull[alias][branch]:从远程仓库获取最新版本并合并到本地。\ngitbranch:列出所有本地分支。\ngitbranch-a:列出所有本地分支和远程分支。\ngitbranch[branch-name]:创建新分支。\ngitcheckout[branch-name]:切换到指定分支。\ngitmerge[branch]:合并指定分支到当前分支。\ngitlog:查看提交历史。\ngitdiff:查看未暂存的文件更新了哪些部分。\ngitreset:重置当前HEAD到指定状态。\n\nGit配置文件解析\nGit配置文件.gitconfig通常位于用户主目录下,用于配置用户级别的Git选项。\nini\n[user]\nname=YourName\nemail=you@example.com\n[alias]\nco=checkout\nbr=branch\nci=commit\nst=status\n\n", "t配置文件解析\nGit配置文件.gitconfig通常位于用户主目录下,用于配置用户级别的Git选项。\nini\n[user]\nname=YourName\nemail=you@example.com\n[alias]\nco=checkout\nbr=branch\nci=commit\nst=status\n\n[user]部分用于设置提交代码时的用户信息。[alias]部分可以设置命令的别名,简化命令输入。\n\nGit错误处理\n处理Git错误时,首先应该使用gitstatus和gitlog检查当前状态和历史提交。以下是一些常见的Git错误处理方法:\n\n当遇到合并冲突时,需要手动编辑文件解决冲突,然后使用gitadd[file]标记为已解决,最后提交。\n如果需要撤销最近的提交,可以使用gitreset--hardHEAD^回退到上一个提交状态。\n当本地分支落后于远程分支,需要合并远程变更时,可以使用gitpull来更新本地分支。\n\n参考资料与进阶阅读\n以下是一些推荐的参考资料和进阶阅读:\n\nProGit书籍:深入理解Git的原理和使用方法。\nGit官方文档:提供详细的命令参考和使用场景。\nGit社区论坛:在社区中与其他开发者交流心得和技巧。\n", "Git教程\nGit简介\n什么是Git\nGit是一种分布式版本控制系统,用于跟踪文件的变化并协作开发。它可以记录文件的修改历史,并允许多人在同一项目上进行协作开发。\nGit的优势\n\n分布式:每个开发者都拥有整个代码库的完整历史记录,无需依赖中央服务器。\n高效:Git的分支和合并操作非常快速,使得并行开发变得更加容易。\n强大的支持:Git支持大型项目、快速的存储和高效的处理能力。\n\n```bash\n创建一个新的Git仓库\ngitinit\n```\n```bash\n克隆一个现有的Git仓库\ngitclone<仓库地址>\n```\n```bash\n将文件添加到暂存区\ngitadd<文件名>\n```\n```bash\n提交文件\ngitcommit-m\"提交说明\"\n```\nGit基础\nGit的安装\n首先,您需要下载适用于您操作系统的Git安装程序。然后,按照安装向导的步骤进行安装。\n创建仓库\n要在Git中创建一个新的仓库,可以使用以下命令:\nbash\ngitinit\n这将在当前目录中创建一个新的Git仓库。\n添加文件\n要将文件添加到Git仓库,可以使用以下命令:\nbash\ngitadd<文件名>\n这将把指定的文件添加到暂存区。\n提交更改\n一旦您对文件进行了修改并将其添加到暂存区,您可以使用以下命令提交更改:\nbash\ngitcommit-m\"提交说明\"\n", "nit\n这将在当前目录中创建一个新的Git仓库。\n添加文件\n要将文件添加到Git仓库,可以使用以下命令:\nbash\ngitadd<文件名>\n这将把指定的文件添加到暂存区。\n提交更改\n一旦您对文件进行了修改并将其添加到暂存区,您可以使用以下命令提交更改:\nbash\ngitcommit-m\"提交说明\"\n这将提交您所做的更改并将其保存到仓库中。查看提交历史\n要查看Git仓库的提交历史,可以使用以下命令:\nbash\ngitlog\n这将显示所有的提交历史记录,包括提交者信息、提交时间和提交说明。\n以上就是Git基础模块的内容。\n分支管理\n创建分支\n要创建一个新的分支,可以使用以下命令:\nbash\ngitbranch\n这将创建一个名为的新分支,但并不会自动切换到这个分支。\n切换分支\n要切换到已经存在的分支,可以使用以下命令:\nbash\ngitcheckout\n这将使当前工作目录切换到名为的分支上。\n合并分支\n要将一个分支的更改合并到当前分支,可以使用以下命令:\nbash\ngitmerge\n这将把名为的分支合并到当前分支上。\n解决冲突\n", "checkout\n这将使当前工作目录切换到名为的分支上。\n合并分支\n要将一个分支的更改合并到当前分支,可以使用以下命令:\nbash\ngitmerge\n这将把名为的分支合并到当前分支上。\n解决冲突\n在合并分支时,如果发生冲突,需要手动解决冲突。可以通过编辑文件来解决冲突,然后使用以下命令标记文件为已解决冲突的状态:bash\ngitadd\n解决完所有冲突后,可以继续合并分支。\n以上是关于Git分支管理的基本操作。\n远程仓库\n添加远程仓库\n要将本地仓库与远程仓库关联,可以使用以下命令:\nbash\ngitremoteaddorigin远程仓库地址\n其中,origin是远程仓库的别名,可以根据实际情况自行命名。\n推送到远程仓库\n将本地提交推送到远程仓库可以使用以下命令:\nbash\ngitpushorigin分支名\n例如,将本地的master分支推送到远程仓库可以使用:\nbash\ngitpushoriginmaster\n从远程仓库拉取\n从远程仓库拉取最新代码到本地可以使用以下命令:\nbash\ngitpullorigin分支名\n", "本地提交推送到远程仓库可以使用以下命令:\nbash\ngitpushorigin分支名\n例如,将本地的master分支推送到远程仓库可以使用:\nbash\ngitpushoriginmaster\n从远程仓库拉取\n从远程仓库拉取最新代码到本地可以使用以下命令:\nbash\ngitpullorigin分支名\n例如,从远程仓库拉取master分支的最新代码可以使用:bash\ngitpulloriginmaster\n解决冲突\n在拉取或合并代码时,如果出现冲突,需要手动解决冲突并提交。可以通过编辑文件解决冲突后,再执行以下命令提交解决:\nbash\ngitadd.\ngitcommit-m\"解决冲突\"\ngitpushorigin分支名\n以上是关于远程仓库操作的基本内容。\n高级主题\n标签\n在Git中,标签是用来标记特定提交的版本号的。通过给提交打上标签,可以方便地在需要的时候找到该提交。创建标签可以使用gittag命令,例如:\nbash\ngittagv1.0.0\n忽略文件\n有时候我们希望Git在进行版本控制时忽略某些文件,比如临时文件或者编译生成的文件。可以通过在项目根目录下创建一个名为.gitignore的文件,并在其中指定需要忽略的文件模式,例如:\nplaintext\n*.log\n", "标签可以使用gittag命令,例如:\nbash\ngittagv1.0.0\n忽略文件\n有时候我们希望Git在进行版本控制时忽略某些文件,比如临时文件或者编译生成的文件。可以通过在项目根目录下创建一个名为.gitignore的文件,并在其中指定需要忽略的文件模式,例如:\nplaintext\n*.log\nbuild/撤销操作\n在Git中,有时候我们需要撤销之前的操作,比如撤销暂存的文件或者撤销已提交的修改。可以使用gitreset命令来撤销暂存的文件,使用gitrevert命令来撤销已提交的修改。\nGit工作流\nGit工作流是指团队协作时如何使用Git进行版本控制和代码管理的一种约定。常见的Git工作流包括集中式工作流、特性分支工作流、Gitflow工作流等。选择合适的工作流对团队的协作效率有很大的影响。\n实用技巧\n查看差异\n要查看文件的差异,可以使用以下命令:\nbash\ngitdiff\n修改最后一次提交\n如果需要修改最后一次提交的信息,可以使用以下命令:\nbash\ngitcommit--amend\n临时存储修改\n使用以下命令可以将当前工作目录中的修改临时存储起来:\nbash\ngitstash\n重写提交历史\n", "\n查看差异\n要查看文件的差异,可以使用以下命令:\nbash\ngitdiff\n修改最后一次提交\n如果需要修改最后一次提交的信息,可以使用以下命令:\nbash\ngitcommit--amend\n临时存储修改\n使用以下命令可以将当前工作目录中的修改临时存储起来:\nbash\ngitstash\n重写提交历史\n如果需要重写提交历史,可以使用以下命令:bash\ngitrebase-iHEAD~n\n以上是关于Git实用技巧的详细内容。\n", "GithubApi使用\nGithubApi简介\n什么是GithubApi\nGithubApi是Github提供的一组用于访问和操作Github数据的接口。通过GithubApi,用户可以实现对仓库、提交、用户等资源的管理和操作。\nGithubApi的优势\n\n灵活性:GithubApi提供了丰富的接口,可以满足各种不同的需求,用户可以根据自身需求进行定制化开发。\n整合性:GithubApi可以与其他服务和工具进行无缝整合,例如持续集成工具、项目管理工具等,提高工作效率。\n实时性:通过GithubApi,可以实时获取最新的仓库、提交等信息,帮助用户及时了解和响应变化。\n\n以上是GithubApi的简要介绍和优势。\nGithubApi的基本用法\n认证与权限\n在使用GithubApi之前,我们需要进行认证以获取相应的权限。GithubApi使用OAuth2.0进行认证,我们可以通过申请一个个人访问令牌(PersonalAccessToken)来进行认证。\n申请个人访问令牌\n\n登录Github,点击头像进入Settings。\n在左侧菜单中选择Developersettings,然后点击Personalaccesstokens。\n点击Generatenewtoken,填写Tokendescription,并勾选需要的权限。\n点击Generatetoken,将生成的访问令牌保存好,之后将用于认证。\n\n使用个人访问令牌进行认证\n在进行数据获取与操作时,需要在请求的Header中添加Authorization字段,其值为\"token\\\"。\n数据获取与操作\n", "需要的权限。\n点击Generatetoken,将生成的访问令牌保存好,之后将用于认证。\n\n使用个人访问令牌进行认证\n在进行数据获取与操作时,需要在请求的Header中添加Authorization字段,其值为\"token\\\"。\n数据获取与操作\nGithubApi提供了丰富的接口来获取和操作数据,包括获取仓库信息、提交记录、问题等。获取仓库信息\n我们可以使用GithubApi来获取特定用户或组织的仓库信息,例如:\n```python\nimportrequests\nurl='\nheaders={'Authorization':'token'}\nresponse=requests.get(url,headers=headers)\nprint(response.json())\n```\n提交操作\n我们可以使用GithubApi来创建、更新和删除提交,例如:\n```python\nimportrequests\nurl='\nheaders={'Authorization':'token'}\ndata={\n\"message\":\"mycommitmessage\",\n\"content\":\"bXkgbmV3IGZpbGUgY29udGVudHM=\"#base64encodedcontent\n}\nresponse=requests.put(url,headers=headers,json=data)\nprint(response.json())\n```\n以上就是GithubApi的基本用法,包括认证与权限以及数据获取与操作。通过这些基本用法,我们可以在自己的应用中使用GithubApi来实现丰富的功能。\nGithubApi的高级应用\nWebhooks\n", "rs=headers,json=data)\nprint(response.json())\n```\n以上就是GithubApi的基本用法,包括认证与权限以及数据获取与操作。通过这些基本用法,我们可以在自己的应用中使用GithubApi来实现丰富的功能。\nGithubApi的高级应用\nWebhooks\nWebhooks是GithubApi中的一项高级功能,它允许用户在特定事件发生时自动触发自定义的HTTP回调。通过配置Webhooks,您可以实现对代码仓库中的各种事件进行监控和自动化处理,例如代码提交、Issue创建等。配置Webhooks\n要配置Webhooks,您可以通过Github仓库的设置页面进行操作。在Webhooks页面,您可以添加新的Webhook,并指定触发Webhook的事件类型和回调URL。\nWebhooks的工作原理\n当配置的事件类型在仓库中发生时,Github会向指定的回调URL发送HTTPPOST请求,请求中包含有关事件的详细信息。您可以编写自定义的服务器端代码来处理这些请求,实现自动化的业务逻辑。\n示例代码\n以下是一个简单的Node.jsExpress服务器端代码示例,用于处理GithubWebhooks的HTTPPOST请求:\n```javascript\nconstexpress=require('express');\nconstbodyParser=require('body-parser');\nconstapp=express();\napp.use(bodyParser.json());\napp.post('/webhook',(req,res)=>{\nconstevent=req.get('X-GitHub-Event');\n", "Parser=require('body-parser');\nconstapp=express();\napp.use(bodyParser.json());\napp.post('/webhook',(req,res)=>{\nconstevent=req.get('X-GitHub-Event');\n//根据event类型处理业务逻辑res.sendStatus(200);\n});\napp.listen(3000,()=>{\nconsole.log('Webhook服务器已启动');\n});\n```\nGithubActions\nGithubActions是Github提供的持续集成和持续部署(CI/CD)工具,它允许您在代码仓库中配置自定义的工作流程,以实现自动化的构建、测试和部署。\n配置GithubActions\n要配置GithubActions,您可以在仓库中创建一个名为.github/workflows的目录,并在该目录中添加YAML格式的工作流程配置文件。在配置文件中,您可以定义工作流程的触发条件、执行步骤和环境。\nGithubActions的工作原理\n当配置的触发条件满足时,Github会自动执行相应的工作流程。您可以在工作流程中使用Github提供的预定义动作(actions),也可以编写自定义的脚本来实现特定的构建、测试和部署操作。\n示例代码\n", "在配置文件中,您可以定义工作流程的触发条件、执行步骤和环境。\nGithubActions的工作原理\n当配置的触发条件满足时,Github会自动执行相应的工作流程。您可以在工作流程中使用Github提供的预定义动作(actions),也可以编写自定义的脚本来实现特定的构建、测试和部署操作。\n示例代码\n以下是一个简单的GithubActions配置文件示例,用于在代码提交后自动运行测试并部署到服务器:```yaml\nname:CI/CD\non:\npush:\nbranches:[main]\njobs:\nbuild:\nruns-on:ubuntu-latest\nsteps:\n-name:Checkoutcode\nuses:actions/checkout@v2\n\n-name:Runtests\nrun:npmtest\n\n-name:Deploytoserver\nrun:|\nsshuser@server'cd/path/to/app&&gitpull'\n\n```\n以上是GithubApi的高级应用中Webhooks和GithubActions的详细内容。\n", "GithubApi使用\n#GithubAPI简介\nGithubAPI是Github提供的一组接口,允许用户通过编程方式与Github进行交互。通过这些接口,用户可以获取Github仓库的信息、创建和修改仓库、管理issue和pullrequest等。\nGithubAPI支持多种编程语言,包括Python、Java、Ruby等。用户可以通过这些语言编写程序,调用GithubAPI接口,实现自动化操作。\nGithubAPI功能\nGithubAPI提供了丰富的功能,包括但不限于:\n\n获取仓库信息\n创建和修改仓库\n管理issue和pullrequest\n获取用户信息\n管理用户权限\n搜索仓库和用户\n\n以下是一个简单的示例代码,演示如何使用Python调用GithubAPI获取仓库信息:\n```python\nimportrequests\ndefget_repo_info(owner,repo):\nurl=f\"\nresponse=requests.get(url)\nifresponse.status_code==200:\nreturnresponse.json()\nelse:\nreturnNone\n调用函数获取仓库信息\nrepo_info=get_repo_info(\"octocat\",\"Hello-World\")\nifrepo_info:\nprint(repo_info)\nelse:\nprint(\"获取仓库信息失败\")\n```\n以上代码中,我们使用requests库发送HTTP请求,获取仓库信息。如果请求成功,则返回JSON格式的仓库信息;如果请求失败,则返回None。\n需要注意的是,在使用GithubAPI时,需要先进行身份验证,可以通过在请求头中添加Authorization字段来实现。\n目录2\nGithubApi使用方法\nGithubApi是一种用于\n#GithubAPI常见问题\n在使用GithubAPI时,可能会遇到一些常见问题,以下是一些可能遇到的问题及其解决方法。\n问题1:无法获取\n", "GithubApi使用\n目录1\nGithubApi简介\nGithubAPI是Github提供的一组接口,用于通过编程方式\n##GithubApi使用方法\nGithubApi是一种基于RESTful架构的API,它允许用户通过HTTP请求与Github进行交互。以下是使用GithubApi的基本步骤:\n1.获取\n"]
--------------------------------------------------------------------------------
/test.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "code",
5 | "execution_count": 3,
6 | "metadata": {},
7 | "outputs": [],
8 | "source": [
9 | "from RAG.VectorBase import VectorStore\n",
10 | "from RAG.utils import ReadFiles\n",
11 | "from RAG.LLM import OpenAIChat\n",
12 | "from RAG.Embeddings import JinaEmbedding"
13 | ]
14 | },
15 | {
16 | "cell_type": "code",
17 | "execution_count": 5,
18 | "metadata": {},
19 | "outputs": [],
20 | "source": [
21 | "vector = VectorStore()\n",
22 | "\n",
23 | "vector.load_vector('./storage') # 加载本地的数据库\n",
24 | "\n",
25 | "embedding = JinaEmbedding()\n",
26 | "\n",
27 | "question = 'git的分支原理?'\n",
28 | "\n",
29 | "content = vector.query(question, EmbeddingModel=embedding, k=1)[0]\n",
30 | "\n",
31 | "chat = OpenAIChat(model='gpt-3.5-turbo-1106')\n",
32 | "print(chat.chat(question, [], content))"
33 | ]
34 | },
35 | {
36 | "cell_type": "code",
37 | "execution_count": null,
38 | "metadata": {},
39 | "outputs": [],
40 | "source": []
41 | }
42 | ],
43 | "metadata": {
44 | "kernelspec": {
45 | "display_name": "base",
46 | "language": "python",
47 | "name": "python3"
48 | },
49 | "language_info": {
50 | "codemirror_mode": {
51 | "name": "ipython",
52 | "version": 3
53 | },
54 | "file_extension": ".py",
55 | "mimetype": "text/x-python",
56 | "name": "python",
57 | "nbconvert_exporter": "python",
58 | "pygments_lexer": "ipython3",
59 | "version": "3.9.19"
60 | }
61 | },
62 | "nbformat": 4,
63 | "nbformat_minor": 2
64 | }
65 |
--------------------------------------------------------------------------------