├── .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 | ![](../images/Retrieval-Augmented%20Generation(RAG-Learning).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 | ![](../images/RAG.png) 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 | ![alt text](images/Retrieval-Augmented%20Generation(RAG-Learning).png) 14 | 15 | 以下为笔者所构思的RAG实现过程,这里面主要包括包括三个基本步骤: 16 | 17 | 1. 索引 — 将文档库分割成较短的 Chunk,并通过编码器构建向量索引。 18 | 19 | 2. 检索 — 根据问题和 chunks 的相似度检索相关文档片段。 20 | 21 | 3. 生成 — 以检索到的上下文为条件,生成问题的回答。 22 | 23 |
24 | RAG 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 | --------------------------------------------------------------------------------