初识RAG

初识RAG RAG: Retrieval Augmented Generation检索增强生成 任务说明:了解到现有大模型的缺陷和RAG的优点和流程 任务要求: 了解大模型现有的缺点 理解RAG的流程和实现步骤 清楚RAG的需要的技术 打卡要求:阅读LangChain与RAG的文章 579和LangChain的官方文档 228,列举LangChain能实现的功能。 ...

<span title='2024-10-02 23:11:05 +0800 +0800'>October 2, 2024</span>&nbsp;·&nbsp;5 min&nbsp;·&nbsp;LingZihuan

vagrant + centos7创建3节点集群

vagrant + centos7创建3节点集群 坑 设置节点的网络的时候,需要给一个属性name​,确保节点启动的时候,集群里面的节点会绑定到同一个网络平面:**node.vm.network "private_network", name: "VirtualBox Host-Only Enthernet Adapter"**​ 为了防止节点启动的时候,22端口被随机分配绑定宿主机端口,我们可以配置将其转发到一个固定的端口:node.vm.network "forwarded_port", guest: 22, host: "230#{i}"​,需要注意的是,需要先将原来的ssh转发端口禁用掉:node.vm.network "forwarded_port", guest: 22, host: 2222, id: "ssh", disabled: "true"​ 配置文件: ...

<span title='2023-01-15 21:33:12 +0000 UTC'>January 15, 2023</span>&nbsp;·&nbsp;1 min&nbsp;·&nbsp;LingZihuan

Argparse Entrance Like Click

使用python argparse实现简单的click python3 argparse 文档 python3 ArgParse教程 需求 实现一个类似click command的类,支持将函数作为命令注册进去,调用这个类的时候,解析命令行参数,执行对应的注册函数。 可以用装饰器的方法进行函数注册以及参数添加 类名: Entrance 方法: 注册: Entrance.register 参数:Entrance.option 实现 entrance.py # encoding: utf-8 """the only entrance for the program""" import argparse class EntranceConflict(Exception): pass class Entrance: def __init__(self): self.parser = argparse.ArgumentParser() self.sub_parser = self.parser.add_subparsers() self.entrances = {} def register(self, name=None): """ 注册一个函数作为入口 可以指定name,否则默认使用函数的名字 """ def decorator(f): entrance_name = name or f.__name__ if entrance_name in self.entrances: raise EntranceConflict(f"entrance {entrance_name} already registered.") # make parser _parser = self.sub_parser.add_parser(name=entrance_name) _params = f.__entrance_params__ for _args, _kwargs in _params: _parser.add_argument(*_args, **_kwargs) _parser.set_defaults(processor=f) # add parser to entrances self.entrances[entrance_name] = _parser return f return decorator def option(self, *args, **kwargs): """ 注册一个函数的参数 参数格式参考 argparse.ArgumentParser.add_argument """ def decorator(f): # set tmp attrs for f if not hasattr(f, '__entrance_params__'): f.__entrance_params__ = [] f.__entrance_params__.append((args, kwargs)) return f return decorator def __call__(self, *args, **kwargs): args = self.parser.parse_args() # extrac args params = vars(args) processor = params.get('processor') if processor: del params['processor'] return processor(**params) else: print('un processable entrance: {}'.format(args)) self.parser.print_help() entrance = Entrance() 调用 写一个简单的调用demo ...

<span title='2022-09-19 00:30:54 +0800 +0800'>September 19, 2022</span>&nbsp;·&nbsp;2 min&nbsp;·&nbsp;LingZihuan

使用mongodb自带的ObjectID获取记录生成时间

有些时候,我们在写入mongo数据的时候,可能需要记录这条数据的插入时间,我们一般情况下回给记录增加一个 create_time。 实际上,如果我们插入的数据含有 ObjectId 的话,那么其实这个id是包含了生成时间的,同时也可以作为记录的主键,一举多得。 以python为例,我们有这样一条记录: document = { "_id": ObjectId("5dfc8ac5d3fa12967b8888ec"), "user": "mike", "age": 19, } 这时候,我们可以使用ObjectId自带的generation_time属性,获取这条记录的插入时间: time = ObjectId("5dfc8ac5d3fa12967b8888ec").generation_time print(time) 输出: datetime.datetime(2019, 12, 20, 8, 48, 5, tzinfo=<bson.tz_util.FixedOffset object at 0x7f874030f9a0>) 需要注意到的是,里面的时区信息,显示的是一个 FixedOffset,即固定偏移,我们看 generation_time 属性的定义: utc = FixedOffset(0, "UTC") """Fixed offset timezone representing UTC.""" class ObjectId(object): # ... 省略其他代码 ... @property def generation_time(self): """A :class:`datetime.datetime` instance representing the time of generation for this :class:`ObjectId`. The :class:`datetime.datetime` is timezone aware, and represents the generation time in UTC. It is precise to the second. """ timestamp = struct.unpack(">I", self.__id[0:4])[0] return datetime.datetime.fromtimestamp(timestamp, utc) 可以看到这个属性是从一个时间戳生成的,并且生成的时候指定了固定的 UTC-0 时区,而我们是处于东八区,因此,如果直接使用 generation_time 属性的话,得到的时间并非我们当前时区的时间,还需要做一个转化,只需要简单的对 datetime.datetime 对象调用astimezone方法,即可: ...

<span title='2022-06-01 14:02:38 +0800 +0800'>June 1, 2022</span>&nbsp;·&nbsp;1 min&nbsp;·&nbsp;LingZihuan

使用Pip Tools生成好看的依赖文件

项目地址: https://pypi.org/project/pip-tools/ pip-tools 是一个命令行工具集合,主要有两个命令: pip-compile,pip-sync,现在主要用的是 pip-compile 在写python项目的时候,我们通常会依赖到其他的包,比如写一个后端的服务,我们可能会依赖到flask/pymysql这些基础的包,随着开发的进行,我们还可能会引入更多的依赖。 这些python依赖包构成了一个完整的服务,开发完成后,我们将这些服务部署到服务器上时,只需要安装好对应的依赖,便可以直接运行服务。 但是,如果我们不将生产环境的依赖固定下来的话,整个服务可能会因为某一次服务更新,其中某个的更新带来的不兼容导致整个服务崩溃。比如pyjwt,在1.7.1版本之前生成的jwt-token是一个bytes类型,我们将其转换成为字符串需要使用到decode()方法。但是在更新到2.0之后,生成的jwt-token是一个字符串类型,如果我们对其再调用decode方法的话,就会发生错误。 这就显现出了固定依赖的重要性了。 通常,固定依赖,我们可以在开发环境使用 pip freeze命令,直接将开发环境的所有版本固定下来到一个 requirements.txt 文件里面,这是懒人做法,当然也很有效。但是文件里面会带有一些系统的依赖版本,比如urllib 之类的,这些我们是不需要再次安装的,所以,如果这些依赖出现在 requirements.txt 文件里面,就会显得不那么干净。 这时,我们可以使用 pip-tools里面的 pip-compile 工具,对依赖进行编译,生成一份漂亮的依赖文件。 直接生成最新依赖 首先,我们将项目中直接依赖的包写到requirements.in文件里面 requirements.in pymysql flask 使用 pip-compile 自动使用最新依赖版本生成依赖文件 命令: pip-compile, 输出requirements.txt文件: requirements.txt # # This file is autogenerated by pip-compile with python 3.8 # To update, run: # # pip-compile # --index-url https://pypi.doubanio.com/simple --trusted-host pypi.doubanio.com click==8.1.3 # via flask flask==2.1.2 # via -r requirements.in importlib-metadata==4.11.4 # via flask itsdangerous==2.1.2 # via flask jinja2==3.1.2 # via flask markupsafe==2.1.1 # via jinja2 pymysql==1.0.2 # via -r requirements.in werkzeug==2.1.2 # via flask zipp==3.8.0 # via importlib-metadata 这样,我们就得到了一份漂亮的依赖文件,我们还可以清晰的看到某一个依赖包是哪个包的依赖。 ...

<span title='2022-05-24 14:16:18 +0800 +0800'>May 24, 2022</span>&nbsp;·&nbsp;1 min&nbsp;·&nbsp;LingZihuan