当前位置: 首页 > news >正文

用FastAPI和Streamlit实现一个ChatBot

前言

本文使用FastAPI+Streamlit实现一个流式响应类ChatGPT的LLM应用,这里只是一个demo,后续会基于此实现一个完整的MCP Client + MCP Server的MCP应用。

Streamlit是专为机器学习和数据科学项目打造的开源Python库,它允许开发者快速创建美观的交互式Web应用,而无需前端开发经验。通过简单的Python脚本,就能构建出功能丰富的数据应用界面。而且官方文档就有ChatBot的示例,直接拿过来稍微修改下就能使用了,上手起来非常简单。

之所以不直接在Streamlit实现MCP Client,是因为MCP SDK的方法几乎都是异步方法,而Streamlit仅支持同步方法,因此我们需要一个中间层来集成MCP Client,而这个中间层我用的就是FastAPI。通过FastAPI实现流式响应,然后在Streamlit再进行流式处理。

用Streamlit实现一个简单的ChatBot

本文大部分基于Streamit的chatbot示例,没做什么改动,只是先尝试下如何使用streamlit。其中pkg.cfg模块提供一些配置信息,后面也都会用到,逻辑比较简单,所以这里就不贴上了,最后的补充部分再贴上。

import streamlit as st
from langchain_openai import ChatOpenAIfrom pkg.config import cfgwith st.sidebar:st.button("Clear Chat", on_click=lambda: st.session_state.pop("messages", None), width="stretch")st.title("MCP Chatbot")
st.caption("🚀 A Streamlit chatbot powered by Qwen")llm = ChatOpenAI(base_url=cfg.llm_base_url,model=cfg.llm_model,api_key=cfg.llm_api_key,temperature=0.3,
)# Initialize chat history
if "messages" not in st.session_state:st.session_state["messages"] = []# Display chat messages from history on app rerun
for msg in st.session_state.messages:st.chat_message(msg["role"]).markdown(msg["content"])# React to user input
if prompt := st.chat_input(placeholder="What's up?"):st.session_state.messages.append({"role": "user", "content": prompt})# st.chat_message("user").write(prompt)with st.chat_message("user"):st.markdown(prompt)def steam_llm():for chunk in llm.stream(input=st.session_state.messages):yield chunk.contentwith st.chat_message("assistant"):msg = st.write_stream(steam_llm())st.session_state.messages.append({"role": "assistant", "content": msg})

在上述代码中,我们创建了一个基础的聊天机器人应用:

  1. 使用Streamlit的侧边栏添加了清除聊天记录的按钮
  2. 初始化了Qwen大语言模型
  3. 实现了聊天历史记录的存储和显示
  4. 通过llm.stream方法实现了流式响应,在用户界面上逐字显示AI回复

FastAPI实现流式响应和客户端流式处理

FastAPI的StreamingResponse实现了流式响应,requests、httpx、aiohttp等http客户端模块都支持流式处理,这里以httpx为例

服务端

from http import HTTPStatus
from typing import Sequenceimport uvicorn
from fastapi import FastAPI
from fastapi.responses import (JSONResponse, PlainTextResponse,StreamingResponse)
from langchain_core.messages import AIMessage, HumanMessage
from langchain_openai import ChatOpenAI
from pydantic import BaseModelfrom pkg.config import cfg
from pkg.log import loggerapp = FastAPI()class Message(BaseModel):role: strcontent: strclass UserAsk(BaseModel):thread_id: strmessages: Sequence[Message]llm = ChatOpenAI(model=cfg.llm_model,api_key=cfg.llm_api_key,base_url=cfg.llm_base_url,temperature=0.3,
)async def generate_response(messages: Sequence[Message]):"""一个异步生成器,用于实时生成文本"""msgs = []for m in messages:if m.role in ("human", "user"):msgs.append(HumanMessage(content=m.content))elif m.role in ("ai", "assistant"):msgs.append(AIMessage(content=m.content))else:print(f"Unknown role: {m.role}")async for chunk in llm.astream(msgs):# Ensure only string is yieldedif hasattr(chunk, "content"):yield str(chunk.content)else:yield str(chunk)@app.get("/health")
async def health():return PlainTextResponse(content="ok", status_code=HTTPStatus.OK)@app.post("/stream")
async def post_ask_stream(user_ask: UserAsk):logger.info(f"user_ask: {user_ask}")if not user_ask.messages:return JSONResponse(content={"error": "query is empty"}, status_code=HTTPStatus.BAD_REQUEST)generator = generate_response(user_ask.messages)return StreamingResponse(generator, media_type="text/event-stream")if __name__ == "__main__":uvicorn.run(app, host="127.0.0.1", port=8000)

在服务端代码中:

  1. 我们定义了两个数据模型:Message,用于处理聊天消息的格式
  2. 使用ChatOpenAI初始化语言模型
  3. generate_response函数是一个异步生成器,将聊天历史转换为LangChain消息格式并流式生成回复
  4. /stream端点接收用户消息并返回流式响应
  5. /health端点用于健康检查

客户端流式处理示例

import asyncioimport httpxdef test_sync_stream():"""同步方式测试流式响应"""print("=== 同步方式测试流式响应 ===")with httpx.stream("POST", "http://127.0.0.1:8000/stream", json={"thread_id": "test_thread_1","messages":[{"role": "user", "content": "你好,请介绍一下你自己"}],}) as response:print("响应状态码:", response.status_code)for chunk in response.iter_text():if chunk:print(chunk, end='', flush=True)print("\n" + "="*50 + "\n")async def test_async_stream():"""异步方式测试流式响应"""print("=== 异步方式测试流式响应 ===")async with httpx.AsyncClient() as client:async with client.stream("POST", "http://127.0.0.1:8000/stream",json={"thread_id": "test_thread_2","messages": [{"role": "user", "content": "写一首关于夏天雨天的现代诗"}]}) as response:print("响应状态码:", response.status_code)async for chunk in response.aiter_text():if chunk:print(chunk, end='', flush=True)print("\n" + "="*50 + "\n")def test_health_endpoint():"""测试健康检查端点"""print("=== 测试健康检查端点 ===")response = httpx.get("http://127.0.0.1:8000/health")print("健康检查响应:", response.text)print("状态码:", response.status_code)print("="*50 + "\n")if __name__ == "__main__":test_health_endpoint()test_sync_stream()asyncio.run(test_async_stream())

客户端示例展示了如何使用httpx处理流式响应:

  1. test_sync_stream函数演示了同步方式处理流式响应
  2. test_async_stream函数演示了异步方式处理流式响应
  3. 两种方式都使用了httpx的流式API逐块处理响应内容

Streamlit集成

import httpx
import streamlit as stdef stream_llm(messages: list = []):with httpx.stream("POST", "http://127.0.0.1:8000/stream", json={"thread_id": "test_thread_1", "messages": messages}) as resp:for chunk in resp.iter_text():if chunk:yield chunkwith st.sidebar:st.button("Clear Chat", on_click=lambda: st.session_state.pop("messages", None), width="stretch")st.title("MCP Chatbot")
st.caption("🚀 A Streamlit chatbot powered by Qwen")# Initialize chat history
if "messages" not in st.session_state:st.session_state["messages"] = []# Display chat messages from history on app rerun
for msg in st.session_state.messages:st.chat_message(msg["role"]).markdown(msg["content"])# React to user input
if prompt := st.chat_input(placeholder="What's up?"):st.session_state.messages.append({"role": "user", "content": prompt})with st.chat_message("user"):st.markdown(prompt)with st.chat_message("assistant"):msg = st.write_stream(stream_llm(st.session_state.messages))st.session_state.messages.append({"role": "assistant", "content": msg})

集成代码中,我们创建了一个函数stream_llm来通过httpx连接FastAPI后端,并将流式响应传递给Streamlit前端显示。这样就实现了从前端到后端的完整流式处理链路。

补充

  • pkg/config.py
import json
from pathlib import Pathclass Config:def __init__(self):p = Path(__file__).parent.parent / "conf" / "config.json"if not p.exists():raise FileNotFoundError(f"Config file not found: {p}")self.data = self.read_json(str(p))def read_json(self, filepath: str) -> dict:with open(filepath, "r") as f:return json.load(f)@propertydef llm_model(self) -> str:return self.data["llm"]["model"]@propertydef llm_api_key(self):return self.data["llm"]["api_key"]@propertydef llm_base_url(self) -> str:return self.data["llm"]["base_url"]@propertydef server_host(self) -> str:return self.data["server"]["host"]@propertydef server_port(self) -> int:return self.data["server"]["port"]cfg = Config()
  • pkg/log.py
import logging
import sysdef set_formatter():"""设置formatter"""fmt = "%(asctime)s | %(name)s | %(levelname)s | %(filename)s:%(lineno)d | %(funcName)s | %(message)s"datefmt = "%Y-%m-%d %H:%M:%S"return logging.Formatter(fmt, datefmt=datefmt)def set_stream_handler():return logging.StreamHandler(sys.stdout)def set_file_handler():return logging.FileHandler("app.log", mode="a", encoding="utf-8")def get_logger(name: str = "mylogger", level=logging.DEBUG):logger = logging.getLogger(name)formatter = set_formatter()# handler = set_stream_handler()handler = set_file_handler()handler.setFormatter(formatter)logger.addHandler(handler)logger.setLevel(level)return loggerlogger = get_logger()

相关文章:

用FastAPI和Streamlit实现一个ChatBot

用FastAPI+Streamlit实现一个流式响应的ChatBot前言 本文使用FastAPI+Streamlit实现一个流式响应类ChatGPT的LLM应用,这里只是一个demo,后续会基于此实现一个完整的MCP Client + MCP Server的MCP应用。 Streamlit是专为机器学习和数据科学项目打造的开源Python库,它允许开发…...

搜索百科(2):Apache Solr — 企业级搜索的开源先锋

大家好,我是 INFINI Labs 的石阳。 欢迎回到 《搜索百科》 专栏!每天 5 分钟,带你速览一款搜索相关的技术或产品,同时还会带你探索它们背后的技术原理、发展故事及上手体验等。 上一篇我们认识了搜索技术的基石 Apache Lucene,今天我们将继续这个旅程,了解基于 Lucene 构…...

Markbook Day03

如何打开CMDWindows+系统+终端右键+在终端打开Windows+R,输入CMD打开某个盘,在地址前输入cmd空格,然后回车 选择以管理员方式运行常用DOS命令 盘符切换 查看当前目录下所有文件dir 切换目录cd change directory cd..回到上一个...

re分区为y盘,efi分区为z盘

re分区为y盘,efi分区为z盘...

数组,java学习第五天

数组 数组的定义 数组是相同类型数据的有序集合 数组描述的是相同类型的若干个数据,按照一定的先后次序排列组合而成 其中,每一个数据称作一个数组元素,每个数组元素可以通过一个下标来访问它们,数组的下标是从0开始的 数组声明创建、三种初始化及内存分析 首先必须声明数组…...

文件结构与数据分析专项-解析

在https://exam.didctf.com/practice/questions可以找到题目出这套题主要是想鼓励大家在遇到陌生的文件时,可以主动地去对这类文件进行分析(尤其是将多个文件打包在一起),希望能通过专项练习得到这方面的提升。 源码 这边先给出源码,先是main.go package mainimport (&quo…...

销售能力——Steam平台我们应该做什么游戏?

最近刚看一个视频,李亚鹏卖酒的故事挺有意思,分享一下 https://www.bilibili.com/video/BV1CXkuY2EXk/?spm_id_from=333.1391.0.0&vd_source=106601ca71b1d910c1ac4aa2466b744c 这里李亚鹏卖酒卖不出去,和我们独立游戏作者游戏卖不出去,我觉得是一个原理。 就是完全没…...

平静

也许我该试着让自己的心灵安静下来。 隐入世俗的境地,好好和身边的人聊聊天。 从合租的房子里搬出去,自己一个人独居。如此渴望孤独的星空,又渴望与群星作伴。...

2025.9.18总结

内容:回顾web学习路线 从最开始的1.黑框增删改查 2.连上数据库,但依旧黑框增删改查 3.网页界面增删改查 4.使用springboot+vue3增删改查。 现在回头看使用ai能够轻松的完成一个表的小项目。 不过对于存粹的技术上面没有掌握更多的知识。打算看一看苍穹外卖看一看除增删改查。…...

Codeforces 2144F Bracket Groups 题解 [ 紫 ] [ AC 自动机 ] [ DP ] [ 构造 ]

Bracket Groups:赛时猜出来用 ACAM,结果没猜到结论,我是糖比。 首先判掉一些 corner,如果出现了 \(\texttt{()}\) 为单个字符串,则一定无解。 发现后面不太好做,所以可以套路地猜一猜答案上界,发现最多只需要分成两组。具体地,考虑往极端情况构造,弄出下面两种括号串:…...

Java进制,数据类型拓展Unicode编码学习

今日学习Java 进制 int i = 10; //十进制,结果为10 int i2 = 010; //八进制,结果为8 int i3 = 0x10; //十六进制,结果为16 二进制符号为0b; float j = 0.1f; 数据类型拓展 银行业务用数据类型BigDecimal,可以进行精确比较。 银行业务不用浮点型来表示是因为浮点型都是有精…...

9月18日总结

9月18日,勿忘国耻!!! 激战了三天三夜,Hadoop和Hbase终于配置完成了,但是还没有学会连接hbase学习进度表body { font-family: Arial, sans-serif; margin: 15px } table { width: 100%; border-collapse: collapse } th, td { border: 1px solid rgba(221, 221, 221, 1); …...

【转】[IDEA] 调试时怎么判断使用哪个配置文件

【转】[IDEA] 调试时怎么判断使用哪个配置文件转自:豆包 在 IntelliJ IDEA 中调试 Spring 项目时,如果发现加载的配置文件不是预期的,通常是由于配置文件加载优先级、启动参数或项目结构问题导致的。以下是具体原因和解决方法: 1. 确认 Spring 配置文件的加载优先级 Spring…...

U3D动作游戏开发读书笔记--3.1 物理系统详解(上)

第三章 物理系统详解 3.1 物理系统的基本梳理 3.1.1 系统参数设置 了解物理配置:打开Project Settings设置Gravity:重力,常用范围是60~80 Queries Hit Backfaces :进行背面查询,如果需要查询MeshCollider背面的情况,可开启 Layer Collision Matrix :物理相交矩阵,确定…...

一个联名款电子产品的技术实现和诞生

@目录项目核心亮点(“老年人”非得在地上穿梭也行,恐高嘛)核心技术(技术实现,欢迎各抒己见)市场分析基础核心创新点 项目核心亮点(“老年人”非得在地上穿梭也行,恐高嘛) 欢迎各位青少年小伙伴参与评论互动,设计图不是最终设计稿,希望你们能多提意见和建议。😄😄…...

20250918 之所思 - 人生如梦

20250918 之所思为了改善专注力,到网上找了不少方法,按照教程学习了冥想,但可能是境界不够,效果一直不太好,容易分心,注意力拉不回来,挺沮丧;昨天试验了番茄钟,开始一个任务,接着开始倒计时,发现注意力非常集中,处理事情的效率非常高,今天事情一多没有使用番茄钟接…...

初赛知识点复盘

前言 作者觉得自己太菜了,就开始复盘初赛知识点了 接下来是CSP-S/J,虽然在HN很容易进复赛但是还是稳健一点 正文 1.计算机内部结构1.冯诺依曼计算机结构,分为 输入设备,存储器,输出设备,运算器,控制器,其中1.运算器目的:进行加减乘除和逻辑运算 2.控制器目的:协调其他…...

WPF使用Cef加载Vue3页面问题

在WPF中使用CefSharp时遇到两个问题:1.Vue3中使用Ant Design Vue时,table不显示数据 由于之前的老项目用的Vue2框架,数据接口是一样的,页面的功能是差不多的,就把table的columns复制了过来,结果显示不出字段; 数据是可以打印出来的,说明赋值是成功了,查资料了解到,An…...

IP子网划分

概念 将一个大的网络划分成几个不同的较小的网络 子网掩码与IP地址 子网掩码与IP地址都是32位二进制数,分为4段,通常用十进制数表示 常见的子网掩码:255.255.255.0/24,即前24位全为1,该子网掩码对应的IP,前24位为网络位,后八位为主机位 由此引申一个判断两个IP是否属于同…...

curl与wget

wget 和 curl 不是替代关系,而是互补工具。wget 更“傻瓜式”,curl 更“灵活”。 但是curl 支持 40+ 协议,是 API 调试、RESTful 接口测试 的首选工具。HTTP 方法与 API 调用(curl 强项) curl 无法原生实现递归下载,需配合 find/xargs 脚本。而递归下载(wget 强项)。 二…...

用 Go 语言与 Tesseract OCR 实现英文数字验证码识别

Go 语言本身不直接支持图像识别,但可以通过调用 Tesseract OCR 引擎来进行图像识别。我们可以使用 Go 的 tesseract 包来实现这一功能。 一、安装与配置 安装 Tesseract OCR 首先,你需要在系统中安装 Tesseract OCR。安装方法和前面一样: Ubuntu(Linux): sudo apt-get up…...

lc1031-两个非重叠子数组的最大和

难度:中等(中期)题目描述给定一个数组和两个长度,找到两个符合长度的不重合的连续子数组,使其和最大示例 输入:nums = [0,6,5,2,2,5,1,9,4], firstLen = 1, secondLen = 2 输出:20 解释:[6, 5] + [9]输入:nums = [3,8,1,3,2,1,8,9,0], firstLen = 3, secondLen = 2 输…...

Segment Analytics-iOS SDK - 专业用户行为追踪解决方案

Segment Analytics-iOS SDK 是一个专业的iOS用户行为分析库,提供完整的事件追踪、用户识别、屏幕浏览统计等功能,支持多种数据集成方式,帮助开发者高效收集和分析用户行为数据。Segment Analytics-iOS SDK Analytics-iOS 是 Segment 官方推出的 iOS 客户端库,帮助开发者轻松…...

我对 WPF 动摇时的选择:.NET Framework 4.6.2+WPF+Islands+UWP+CompostionApi - 行人-

我使用佳能相机,以60FPS高帧率录制视频,来比对 WPF 和 UWP 的动画流畅度,结果: WPF表现吃力和卡顿,UWP表现丝滑和高级。文章是我对.NET Framework 4.6.2框架下的动画方案的选型进行的一些探索和记录。NET Framework 4.6.2的最大亮点 安全性能大提升: 默认启用TLS1.2协议,…...

使用 Rust 与 Tesseract OCR 识别英文数字验证码

一、安装与配置 安装 Tesseract OCR Ubuntu: 更多内容访问ttocr.com或联系1436423940 sudo apt-get update sudo apt-get install tesseract-ocr macOS: brew install tesseract Windows: 从 Tesseract 官方 GitHub 下载并安装 Windows 版本。 安装 Rust 的 tesseract 库 我…...

别迷茫了!计算机大一新生这样做,四年后远超同龄人 - 编程实战派

本文是一份专为计算机专业大一新生打造的终极学习指南。文章打破迷茫,从心态重置、学习攻略、实践真知、视野规划四大维度,提供切实可行的建议。强调从“被动学习”转向“主动探索”的思维模式,死磕数学、英语、C语言与算法等核心基础,并通过动手做项目、参与开源来积累经验…...

解决ifconfig命令没有显示ens33 finalshell连接不上虚拟机

停止并关闭NetworkManager systemctl stop NetworkManagersystemctl disable NetworkManager重启网络服务 systemctl start network...

什么情况下需要用到xargs

它是 find、grep、ls 等输出类命令的“桥梁”,连接“查找”和“执行”​ xargs 核心作用是:将标准输入(stdin)中的数据转换为命令行参数,并传递给其他命令执行。 总结:当你需要把“文本流”变成“命令参数”时,就该用 xargs。 一:为什么要用xargs? 示例: 在当前目录下…...

Office 2024安装包专业增强版超详细下载安装教程

在数字化办公浪潮中,Office 2024 专业增强版成为提升办公效率的得力助手。这款功能强大的办公套件,集成了 Word、Excel、PowerPoint、Access、Outlook、OneNote 等多个组件,能够全方位满足日常办公中的文本处理、表格制作、演示文稿设计、数据库管理、邮件收发以及数字笔记记…...

你好

<script>window.location.href="https://www.baidu.com";</script>...

关于 pdfminer 的安装 - 指南

关于 pdfminer 的安装 - 指南pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", monospace !important; font-s…...

c/c++实现有栈协程

有栈协程 有栈协程通过切换执行上下文实现,核心是切换栈寄存器和跳转ip代码地址,同时需要保存切换当前编译器ABI规定的 非易失寄存器。 System V AMD64 ABI 和 MSVC x64 ABI 的非易失性寄存器RBX、RBP、RSP、R12、R13、R14、R15 XMM6-XMM15RDI、RSI、仅MSVCMSVC比GCC多了两个…...

Day17冒泡排序

package com.cc.array;import java.util.Arrays;public class ArrayDemo7 {public static void main(String[] args) {int [] a = {21,4,5,6,35,65,23,34,53,5};Arrays.sort(a);System.out.println(Arrays.toString(a));}//冒泡排序//1,比较数组中,两个相邻的元素,如果第一个…...

高阶 INTJ 5w4 整合到 8,是完整的过程,从研究到实用(豆包)

高阶INTJ 5w4整合到8的完整过程,是一个从认知重构、情感突破到行为落地的系统性进化,需要经历理论奠基→动态转化→实践固化三个阶段。以下结合九型人格整合机制、INTJ发展规律及5w4的特质矛盾,展开从研究到实用的全链条解析: 一、理论奠基:理解整合的底层逻辑(研究阶段)…...

几B大模型的空间存储大小

1. 前言砚上三五笔,落墨鹧鸪啼关于大模型总是会出现几B,然后想知道他们的存储空间大小分别是多少。还有描述一些显卡的TFLOPS是怎么计算的。这里做一个简单的记录。 如有不对,欢迎评论区指正! 2. 正文 2.1 精度类型 包括FP64:64位双精度浮点型 8字节 double FP32:32位单…...

hbase安装与配置

解压文件改名配置环境变量配置文件(忘记截图了,问ai即可) cd $HBASE_HOME/conf hbase-env.sh,hbase-site.xml, regionservers 启动前准备 hdfs dfs -mkdir -p /hbase hdfs dfs -chown hadoop:hadoop /hbase 如果各种配置都配好了却一直有问题(我是报server is not runnin…...

发喷山火(volcano)+CF2119F Volcanic Eruptions 解题报告

发喷山火 神题 先来初步挖掘一下这个走路过程的性质:初始时 \(S=1\),且 \(S\le 0\) 就死了,所以在没有走到 \((1,1)\) 之前,只能走 \((1,-1)\) 的边。 由于你和岩浆走路速度相同,所以一旦路径中你已经触碰到岩浆,那么你无论如何都逃不出去了,所以触碰过岩浆等价于最后停…...

matlab免费下载安装激活教程(附安装包下载)MATLAB R2025a超详细下载安装教程

MATLAB R2025a是2025年工科必备的工程计算软件,不管是大学生做课程设计、研究生写论文,还是工程师搞项目研发,用它处理矩阵运算、建模仿真都特别方便。新版本运算速度比上一代快35%,还新增了新能源、自动驾驶专用工具箱,功能更全。很多人觉得安装难,其实分三步就能搞定,…...

Spring Boot + flowable 完美结合,快速实现工作流 - 教程

Spring Boot + flowable 完美结合,快速实现工作流 - 教程pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", m…...

Pyfluent 执行Meshing工作流

1. 部署安装pyfluent Pyfluent支持Fluent 2022R2或更高版本,PyFluent支持Python 3.10~3.13版本,点击 此处 即可下载。 安装核心依赖需使用pip命令,如若详细了解该命令的使用,详见 此处 pip install ansys-fluent-core pip install pyfluent //如有需要可进一步安装 pip ins…...

EF Core 与 MySQL:日志和调试详解

本文将详细讲解EF Core与MySQL的日志和调试,分为三个部分:EF Core日志配置、MySQL日志查看以及使用调试工具分析查询性能。 1. 配置 EF Core 日志 基本日志配置// 在DbContext配置中启用日志记录 protected override void OnConfiguring(DbContextOptionsBuilder optionsBuil…...

使用镜像源解决github拉取代码问题 - GD

命令行输入以下语句: git config --global url."https://gitclone.com/github.com/".insteadOf "https://github.com/" 取消设置: git config --global --unset url."https://gitclone.com/github.com/".insteadOf 参考:[https://www.cnblogs…...

日记

redis的运行指令 redis-server.exe redis.windows.conf 开始大创的实施...

主机连接虚拟机和hbase的命令

telnet+ip+端口号 主机hbase...

类和面向对象

概述:语言特性有二,其一为既面向过程又面向对象,其二为用类和对象表示数据和操作数据的,c++将操作和数据汇聚成类和对象何为对象?即世间的一切事物。假如一个对象为feijib,则可以说这个为类feijib,难道类是对象的别名?按下不表。类具有一些属性和方法,即feijjib是硅胶…...

PHP转Go系列 | PHP8 这些新函数让你眼前一亮

说实话,PHP8 中的这三个新函数让字符串检查,变得非常直观,就像让代码说人话一样。这对我们程序员来说是一件大好事,提升可读性,减少 Bug 量,升级到 PHP8 之后,再也不用维护类似的屎山代码了。大家好,我是码农先森。 在 PHP8 之前做字符串相关的检查操作比较麻烦,可读性…...

代码随想录算法训练营第二天 |209.长度最小的子数组,59. 螺旋矩阵 II

209.长度最小的子数组 思路:快慢指针的思想,当快指针一直移动的时候,那么数列一定是递增的,且我们要求的是连续的数组,所以我们其实可以一次性用一个for就给全部遍历完成。当我们这个区间的值大于了target,我们就可以开始移动我们的慢指针了,直到我们的慢指针到达快指针…...

mac更新or安装homebrew失败

错误信息:fatal: unable to access https://github.com/Homebrew/brew/: LibreSSL SSL_read: error:02FFF03C:system library:func(4095):Operation timed out, errno 60可以用命令:/bin/zsh -c "$(curl -fsSL https://gitee.com/cunkai/HomebrewCN/raw/master/Homebrew…...

Typescript中闭包的原理 - 教程

Typescript中闭包的原理 - 教程pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", monospace !important; font…...

CF2048H Kevin and Strange Operation

操作的自由度很大,打表可以发现限制操作的位置只增不减也是对的。 考虑怎么判断一个串 \(t\) 是否合法。 观察到对于一个位置 \(i\) 满足 \(s_i=0\),想要通过操作使 \(s_i\) 变为 \(1\),只需要 \(>i\) 的位置删掉了 \(\ge c_i\) 个数。其中 \(c_i\) 为 \(>i\) 的第一个…...