容器网络篇一:单机网络方案

安装工具: apt install bridge-utils net-tools 容器与宿主机的通信 创建一个新的网络命名空间,这里模拟容器内部的网络 $ ip netns add net1 # net1为该网络空间(容器内部网络空间)的名称 查看命名空间的iptable, 路由表,设备 $ ip netns exec net1 route # 查看容器内部路由表 Kernel IP routing table Destination Gateway Genmask Flags Metric Ref Use Iface $ ip netns exec net1 iptables -L # 查看容器内部iptable Chain INPUT (policy ACCEPT) target prot opt source destination Chain FORWARD (policy ACCEPT) target prot opt source destination Chain OUTPUT (policy ACCEPT) target prot opt source destination $ ip netns exec net1 ip link list # 查看容器内部设备 1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN mode DEFAULT group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 # 目前只有本地回环设备, 并且状态为DOWN(未启动) 创建一对veth,并将veth的一头添加到net1中...

February 28, 2024 · 4 min · 李昌

容器网络篇二:跨主机通信之Flannel

flannel项目本身只是一个框架,真正实现容器网络容器功能的,是Flannel的后端实现,目前,Flannel推荐的后端实现有四种,分别是: VXLAN host-gw WireGuard UDP 此外还有一些实验性的后端实现 UDP模式 UDP 模式,是最直接、也是最容易理解的容器跨主网络实现。 假设有两台宿主机: 宿主机 Node 1 上有一个容器 container-1,它的 IP 地址是 100.96.1.2,对应的 docker0 网桥的地址是:100.96.1.1/24。 宿主机 Node 2 上有一个容器 container-2,它的 IP 地址是 100.96.2.3,对应的 docker0 网桥的地址是:100.96.2.1/24。 现在的任务是:让container-1访问container-2。此时访问container-2的这个IP包的源地址为100.96.1.2,目的地址为100.96.2.1。按照上篇所述,首先这个IP包会通过veth对来到docker0网桥,而此时docker0网桥上并没有插入IP为100.96.1.2的设备,因此会走默认路由规则,出现在宿主机上。此时如果机器上已经安装了flannel,那么flannel会为宿主机创建出一系列路由规则,如: # 在Node 1上 $ ip route default via 10.168.0.1 dev eth0 100.96.0.0/16 dev flannel0 proto kernel scope link src 100.96.1.0 100.96.1.0/24 dev docker0 proto kernel scope link src 100.96.1.1 10.168.0.0/24 dev eth0 proto kernel scope link src 10....

February 28, 2024 · 2 min · 李昌

拥抱大模型(三):OutputParser,格式化输出

大模型可以回答你的任何问题,但有时我们需要将大模型的回复进行格式化解析以便进行后续的处理,此时就需要我们使用一些特殊的技巧提示大模型:你应该如此如此,这般这般返回一个简单的例子(文心一言):可以看到,我们在prompt中告诉大模型,你应该以如下json格式返回,大模型按照我们的要求,切实返回了我们要求的json格式。这样,我们就可以把大模型的输出进行解析,大模型的输出,不再是无法解析的数据。langchain为我们提供了一系列工具来为prompt添加输出格式指令,解析输出,重试机制等等。 使用LangChain工具 PydanticOutputParser(json输出解析) from pydantic import BaseModel, Field from langchain.output_parsers import PydanticOutputParser, OutputFixingParser class FlowerDescription(BaseModel): title: str = Field(description="这本书的标题") author: int = Field(description="这本书的作者") words: str = Field(description="这本书的字数") description: str = Field(description="这本书的主要情节") # 定义输出解析器 output_parser = PydanticOutputParser(pydantic_object=FlowerDescription) # 获取输出格式指示 format_instructions = output_parser.get_format_instructions() print(format_instructions) The output should be formatted as a JSON instance that conforms to the JSON schema below. As an example, for the schema {"properties": {"foo": {"title": "Foo", "description": "a list of strings", "type": "array", "items": {"type": "string"}}}, "required": ["foo"]}} the object {"foo": ["bar", "baz"]} is a well-formatted instance of the schema....

February 4, 2024 · 2 min · 李昌

拥抱大模型(二):Prompt,给大模型有用的提示

极客时间《LangChain实战课》学习笔记 构建prompt的原则 原则(吴恩达版) 写出清晰而具体的提示 给模型思考的时间 原则(OpenAI版) 写清晰的指示 给模型提供参考(也就是示例) 将复杂任务拆分成子任务 给 GPT 时间思考 使用外部工具 反复迭代问题 prompt的基本结构 一个prompt主要包含四块内容: instruction(指令):告诉大模型要做什么,一个常见且有效的例子是,告诉大模型“你是一个XX专家” context(上下文):充当模型的额外知识来源,这些知识可以从矢量数据库中得来或通过其他方式拉入 prompt input (提示输入):具体的问题或大模型做的具体事情 output indicator(标记要生成的文本的开始):用一个明显的提示词让大模型开始回答,这一部分不是必须的 使用langchain构建prompt from langchain import PromptTemplate template = """\ 你是业务咨询顾问。 你给一个销售{product}的电商公司,起一个好的名字? """ prompt = PromptTemplate.from_template(template) print(prompt.format(product="鲜花")) prompt = PromptTemplate( input_variables=["product", "market"], template="你是业务咨询顾问。对于一个面向{market}市场的,专注于销售{product}的公司,你会推荐哪个名字?" ) print(prompt.format(product="鲜花", market="高端")) 二者效果相同构建chat prompt对于像ChatGPT这种聊天模型,langchain提供了ChatPromptTemplate,其中有多种角色类型: import openai openai.ChatCompletion.create( model="gpt-3.5-turbo", messages=[ {"role": "system", "content": "You are a helpful assistant....

February 4, 2024 · 2 min · 李昌

拥抱大模型(五):Memory,让大模型拥有记忆

要让大模型有记忆也很简单,你只需要把之前的对话传递给他就行,在ConversationChain中,就使用了这一技巧: from langchain import OpenAI from langchain.chains import ConversationChain # 初始化大语言模型 llm = OpenAI( temperature=0.5, model_name="text-davinci-003" ) # 初始化对话链 conv_chain = ConversationChain(llm=llm) # 打印对话的模板 print(conv_chain.prompt.template) 来看下模板: The following is a friendly conversation between a human and an AI. The AI is talkative and provides lots of specific details from its context. If the AI does not know the answer to a question, it truthfully says it does not know. Current conversation: {history} Human: {input} AI: 可以看到,在模板里又一个history字段,这里存储了之前对话的上下文信息。当有了 {history} 参数,以及 Human 和 AI 这两个前缀,我们就能够把历史对话信息存储在提示模板中,并作为新的提示内容在新一轮的对话过程中传递给模型。—— 这就是记忆机制的原理。 langchain中提供的记忆机制 ConversationBufferMemory 在 LangChain 中,通过 ConversationBufferMemory(缓冲记忆)可以实现最简单的记忆机制。下面,我们就在对话链中引入 ConversationBufferMemory。...

February 4, 2024 · 2 min · 李昌

拥抱大模型(四):Chain,像人类一样思考

什么叫Chain,从字面意思理解,Chain是一个链,我们可以通过Chain来链接LangChain的各个组件和功能-模型之间彼此链接,或模型与其他组件链接。这种将多个组件相互链接,组合成一个链的想法简单但很强大。它简化了复杂应用程序的实现,并使之更加模块化,能够创建出单一的、连贯的应用程序,从而使调试、维护和改进应用程序变得容易。 我们可以简单的把Chain理解为通过设计好的一些链路去调用大模型,从而获取我们想要的结果。下面是一个例子: 首先我们让大模型扮演产品经理,给出小说推荐网站的产品设计。 有了产品设计后,由架构师进行初步的架构设计 现在架构设计也有了,来个程序员写SQL: 那,上面的这种promot链,我们用langchain怎么实现呢? 使用langchain实现 Sequential Chain 首先,导入所有需要的库 # 设置OpenAI API密钥 import os os.environ["OPENAI_API_KEY"] = '你的OpenAI API Key' from langchain.llms import OpenAI from langchain.chains import LLMChain from langchain.prompts import PromptTemplate from langchain.chains import SequentialChain 添加第一个LLMChain,生成小说网站的产品设计。LLMChain可以看作是链条的一个环节 # 这是第一个LLMChain,用于生成鲜花的介绍,输入为花的名称和种类 llm = OpenAI(temperature=.7) template = """ 你是一个产品经理,请你对{product}给出一个设计想法。""" prompt_template = PromptTemplate(input_variables=["product"], template=template) introduction_chain = LLMChain(llm=llm, prompt=prompt_template, output_key="introduction") 添加第二个LLMChain,根据产品设计生成软件架构 # 这是第二个LLMChain,用于根据鲜花的介绍写出鲜花的评论 llm = OpenAI(temperature=.7) template = """ 你是一位软件架构师。给定一个{product}的设计,你需要给出产品软件架构说明和技术栈选型。 产品设计: {introduction} 软件架构说明:""" prompt_template = PromptTemplate(input_variables=["product", "introduction"], template=template) review_chain = LLMChain(llm=llm, prompt=prompt_template, output_key="framwork") 第三个Chain,根据产品架构生成SQL语句...

February 4, 2024 · 5 min · 李昌

Function as a Method Receiver

通常来说,我们会使用某个具体的对象(struct)来作为receiver实现接口,但有时候,使用函数作为receiver可以起到不一样的效果。 使用函数作为receiver一个最常见的例子是HandleFunc: type HandlerFunc func(ResponseWriter, *Request) func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) { f(w, r) } 这里将HandleFunc作为接收器,实现了ServeHTTP方法,同时也实现了http.Handler接口 type Handler interface { ServeHTTP(ResponseWriter, *Request) } 代码注释中对与HandleFunc的解释如下: // The HandlerFunc type is an adapter to allow the use of // ordinary functions as HTTP handlers. If f is a function // with the appropriate signature, HandlerFunc(f) is a // Handler that calls f. HandleFunc的定位是:适配器。为什么这么说?有了这个适配器,我们就可以这样完成一个http server: func main() { http.HandleFunc("/echo", func(w http.ResponseWriter, r *http....

November 26, 2023 · 1 min · 李昌

Linux命令之nc

nc: 任意的TCP/UDP连接和监听 It can open TCP connections, send UDP packets, listen on arbitrary TCP and UDP ports, do port scanning, and deal with both IPv4 and IPv6. 使用case 快速创建client/server对 nc -l 1234 nc 127.0.0.1 1234 任何在client端的输出都将在server端显示 端口扫描 nc -zv 127.0.0.1 8885-8889 其他例子 nc -p 31337 -w 5 abc.com 42 nc -u abc.com 53 nc -s 10.1.2.3 abc.com 42 nc -lU /var/tmp/dsocket

November 26, 2023 · 1 min · 李昌

创建Linux新分区,并挂载

要创建一个新的 Linux 文件系统分区并进行挂载,您可以按照以下步骤进行操作: 首先,使用以下命令之一来查看系统中已连接的磁盘和分区: sudo fdisk -l 或者 sudo lsblk 这将显示系统中的磁盘和分区列表。找到您要创建分区的磁盘。 使用以下命令打开磁盘分区工具(例如 fdisk): sudo fdisk /dev/<disk_name> 将 <disk_name> 替换为您要创建分区的磁盘的名称,例如 /dev/sda。 在磁盘分区工具中,使用以下命令创建新的分区: n 然后按照提示选择分区类型、起始扇区和结束扇区。对于 Linux 文件系统,通常选择默认选项即可。 设置分区的文件系统类型为 Linux。使用以下命令: t 然后选择新创建的分区编号,并选择 Linux 文件系统类型(例如 83)。 保存并退出磁盘分区工具。使用以下命令: w 使用以下命令创建文件系统: sudo mkfs.ext4 /dev/<partition> 将 替换为您刚刚创建的分区设备名称,例如 /dev/sda1。 创建一个目录,用于挂载文件系统。使用以下命令: sudo mkdir /mnt/<mount_point> 将 <mount_point> 替换为您希望挂载文件系统的目录路径。 使用以下命令将文件系统挂载到目标目录: sudo mount /dev/<partition> /mnt/<mount_point> 将 替换为您刚刚创建的分区设备名称,<mount_point> 替换为您在第 7 步中创建的目录路径。 挂载成功后,您可以使用以下命令来验证文件系统是否已挂载: df -h 这将显示已挂载的文件系统列表,包括挂载点和可用空间。...

November 26, 2023 · 1 min · 李昌

容器网络实验

安装工具: apt install bridge-utils net-tools 创建一个新的网络命名空间 $ ip netns add net1 # net1为该网络空间的名称 查看命名空间的iptable, 路由表,设备 $ ip netns exec net1 route # 查看路由表 Kernel IP routing table Destination Gateway Genmask Flags Metric Ref Use Iface $ ip netns exec net1 iptables -L # 查看iptable Chain INPUT (policy ACCEPT) target prot opt source destination Chain FORWARD (policy ACCEPT) target prot opt source destination Chain OUTPUT (policy ACCEPT) target prot opt source destination $ ip netns exec net1 ip link list # 查看设备 1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN mode DEFAULT group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 # 目前只有本地回环设备, 并且状态为DOWN(未启动) 创建一对veth,并将veth的一头添加到net1中...

November 26, 2023 · 4 min · 李昌