AI算法工程师实习周记(二)

总结:

代码报错搜了很多知识,然后按照搜到的一个个去尝试能否解决,结果越搞越乱,不如重新梳理代码逻辑和思路,系统地掌握架构,这样能找到报错关键点。

本周知识清单:

  • python装饰器
  • fastAPI使用
  • 利用FunASR和fastapi创建一个语音识别的接口
  • 千问1.5代码生成微调

下周任务:

  • 千问代码微调复现
  • 千问代码微调技术分享
  • 千问代码对外提供服务

目录

总结:

本周知识清单:

下周任务:

关键记录

python装饰器

fastAPI使用

1.路径参数

2.里面的2-2节中的async def 是用于定义异步函数的关键字

3.如果路径参数设置成整数:def read_item(item_id: int):

4.枚举类enum

5.查询参数:

6.请求体和响应体

7.刚刚指明参数类为int等类型,还可以自己定义类:

8.参数排序技巧:

9.还可以给item_id做验证

10.各种参数的总理解

11.使用Body方法定义单值的请求体参数

12.第九节的Body - Nested Models(嵌套模型)

13.Response Model(响应模型)

最终操作:

实现能上传文件并保存到本地:

利用FunASR和fastapi创建一个语音识别的接口

每天一些linux操作小知识

零散记录:


关键记录

python装饰器

参考:【Python】一文弄懂python装饰器(附源码例子)_python 装饰器-CSDN博客

装饰器,就是可以让我们拓展一些原有函数没有的功能。

装饰器的语法糖@
简单的装饰器还是可以通过语法糖来实现的,这样就可以省去

原函数 = 装饰器(原函数)

这一句代码,而直接调用原函数()这个函数就可以运行装饰器函数

fastAPI使用

第一个 FastAPI 应用 | 菜鸟教程 (runoob.com)

下载地址:tiangolo/fastapi:FastAPI 框架,高性能,简单易学,快速编码,准备生产 (github.com)

上传文件:

FastAPI(24)- 详解 File,上传文件 - 小菠萝测试笔记 - 博客园 (cnblogs.com)

实现上传一个文件之后读取文件名称、文件类型、文件大小

1.建立一个main.py文件

超全面整理fastAPI(从入门到运用),进来看十秒钟再走不迟-CSDN博客

里面的一些理解:

1.路径参数

就是比如访问127.0.0.1:8000/items/bsy的后面那段“/bsy"

也是代码里的:{item_id},可以随意变化

from fastapi import FastAPI

app = FastAPI()

@app.get("/items/{item_id}") 
def read_item(item_id):
    return {"item_id": item_id}
2.里面的2-2节中的async def 是用于定义异步函数的关键字

异步函数是 Python 异步编程的核心组成部分,它们允许代码在等待某些操作完成时(例如 I/O 操作)释放控制权,这样可以在单个线程内同时处理多个任务。

异步函数的定义如下:

async def function_name(parameters):
    # 函数体
    # 可以包含异步操作,如 await some_async_function()

以下是一些关于异步函数的要点:

  1. 异步函数返回一个协程(coroutine)对象:这意味着异步函数在调用时不会立即执行,而是返回一个可以等待的对象。

  2. 使用 await 关键字:在异步函数内部,可以使用 await 关键字来调用其他异步函数或协程。await 会挂起当前协程的执行,直到被调用的协程完成。

  3. 事件循环:异步函数需要一个事件循环来运行。事件循环负责调度和执行协程,以及处理 I/O 事件。

  4. 不能在同步代码中直接调用异步函数:异步函数只能从另一个异步函数中使用 await 调用,或者通过事件循环的 run_until_complete() 方法运行。

以下是一个简单的异步函数示例:

import asyncio

async def hello_world():
    print("Hello")
    await asyncio.sleep(1)  # 模拟 I/O 操作
    print("World")

# 在事件循环中运行异步函数
asyncio.run(hello_world())
在这个例子中,hello_world 是一个异步函数,它打印 “Hello”,然后等待 1 秒(模拟 I/O 操作),最后打印 “World”。使用 asyncio.run() 函数来运行这个异步函数,它会创建一个新的事件循环,运行传入的协程,并在协程完成后关闭事件循环。
3.如果路径参数设置成整数:def read_item(item_id: int):

但是地址对应的不是整数的话会显示:

{
    "detail": [
        {
            "type": "int_parsing",
            "loc": [
                "path",
                "item_id"
            ],
            "msg": "Input should be a valid integer, unable to parse string as an integer",
            "input": "时代光华"
        }
    ]
}

终端会显示:422 Unprocessable Entity

4.枚举类enum
from enum import Enum
from fastapi import FastAPI


class Hjx_Class_name(str, Enum):
    Name = 'huangjunx'
    Year = 18
    Id = '20153201072'
    student = True


app = FastAPI()


@app.get('/hjx/{hjx_man}')
def root(hjx_man: Hjx_Class_name):
    return {'status': hjx_man}

例如你访问http://127.0.0.1:8001/hjx/20153201072,得到的会是:{“status”:“20153201072”}

例如你访问http://127.0.0.1:8001/hjx/True,得到的会是:{“status”:“True”}

这样我们就能做到给某个路径参数传递某几个固定的有效值了。

进一步,我们还可以在root函数里面调用这个类的类属性。通过Hjx_Class_name.Name进行调用。下面例子无论你使用哪个类属性的值访问,结果都是{"status":"huangjunx"}

4.2-4节中路径参数的值是路径类型变量的意思是
假设现在你有一个路径操作:/files/{file_path},但是你需要 file_path 本身包含一个 路径, 比如 home/johndoe/myfile.txt.

因此, 文件路径可能是: /files/home/johndoe/myfile.txt

在这种情况,我们使用Path转换器就可以进行转换了。使用以下方法声明值是路径的路径参数。

from fastapi import FastAPI

app = FastAPI()


@app.get("/files/{file_path:path}")
def read_user_me(file_path):
    return {"file_path": file_path}

语句表示的意思是:参数的名字是 file_path:path说明参数file_path对应的类型是 path 类型

5.查询参数:

当你声明不属于路径参数的其他函数参数时,它们将自动解释为“Query”参数,也就是查询参数。

查询参数就是一系列在URL?之后的key-value键值对,每对键值对用 & 分割开来

from fastapi import FastAPI

app = FastAPI()


@app.get("/files/")
def add(num1: int=2, num2 int=8):
    return {"num1 + num2 = ": num1 + num2}#默认输出结果是10

当你使用浏览器访问http://127.0.0.1:8001/files/?num1=2&num2=3,你会得到:{"num1 + num2 = ":5}

声明可选的Query参数,只需要将他们的默认值设置为None即可。

关于查询参数还需要注意以下几点:

  • 如果设置的查询参数没有默认值不是None,那么这个查询参数就是必需查询参数,必须要传入,否则会报错
  • 查询参数可以和路径参数结合使用
6.请求体和响应体

请求体是客户端发送到您的API的数据。 响应体是您的API发送给客户端的数据。

API几乎总是必须发送一个响应体,但是客户端并不需要一直发送请求体。

定义请求体,需要使用 Pydantic 模型。注意以下几点

  • 不能通过GET请求发送请求体
  • 发送请求体数据,必须使用以下几种方法之一:POST(最常见)、PUT、DELETE、PATCH
7.刚刚指明参数类为int等类型,还可以自己定义类:
from fastapi import FastAPI
from pydantic import BaseModel

#声明了一个JSON对象
class Item(BaseModel):
    name: str
    description: str = None
    price: float
    tax: float = None


app = FastAPI()


@app.post("/items/")
async def create_item(item: Item):
    return item

定义了一个Item类,和查询参数一样:数据类型的属性如果不是必须的话,可以拥有一个默认值或者是可选None。否则,该属性就是必须的。

所以访问的请求体就可以是:

{
    "name": "Foo",
    "description": "An optional description",
    "price": 45.2,
    "tax": 3.5
}

或者

{
    "name": "Foo",
    "price": 45.2
}
8.参数排序技巧:
from fastapi import FastAPI, Path

app = FastAPI()

@app.get("/items/{item_id}")
async def read_items(
 *, item_id: int = Path(..., title="The ID of the item to get"), q: str ):
    results = {"item_id": item_id}
    if q:
        results.update({"q": q})
    return results

此时输入的网址就可以是http://127.0.0.1:8000/items/434?q=9

网址就会输出

{
    "item_id": 434,
    "q": "9"
}
9.还可以给item_id做验证

改变这一行:

*, item_id: int = Path(..., title="The ID of the item to get")

*, item_id: int = Path(..., title="The ID of the item to get", ge=1)

意思是大于或者等于ge,只能比较整数。例如大于等于1

item_id: int = Path(..., title="The ID of the item to get", gt=0, le=1000)

小于或者等于le,只能比较整数。例如大于等于0小于等于1000

item_id: int = Path(..., title="The ID of the item to get", ge=0, le=1000)

大于gt, 小于lt,可以比较浮点数和整数

10.各种参数的总理解

这里混合使用了路径参数item_id,查询参数q,请求体参数item。第一个参数星号表示星号之后所有参数都应称为关键字参数(键-值对),即使它们没有默认值。这是一种有效的写法。

from fastapi import FastAPI, Path
from pydantic import BaseModel

app = FastAPI()


class Item(BaseModel):
    name: str
    description: str = None
    price: float
    tax: float = None


@app.put("/items/{item_id}")
async def update_item(
    *,
    item_id: int = Path(..., title="The ID of the item to get", ge=0, le=1000),
    q: str = None,
    item: Item = None,
):
    results = {"item_id": item_id}
    if q:
        results.update({"q": q})
    if item:
        results.update({"item": item})
    return results
11.使用Body方法定义单值的请求体参数

例如,扩展之前的模型,之前的模型还需要额外增加一个参数:除去item和user这两个字段之外,还需要importance在请求体中,如果你直接定义它,因为他是一个单值,FastAPI会默认将其定义为query参数。

但是你可以使用Body方法,让FastAPI将其视为请求体的key:

 importance: int = Body(...)

注意一点:Schema与 QueryPathBody的工作方式相同,具有相同的参数

schema是定义类属性里参数的范围,跟刚刚path函数语法一样不过需要导入

from pydantic import BaseModel, Schema 

8-2节还可以给请求体展示示例,在声明函数输入的时候加上

 example={ "name": "Foo", "description": "A very nice Item", "price": 35.4, "tax": 3.2, }, 

当我们访问/docs,我们将看到如下:Example Value | Schema 数据示例,告诉用户,这个api想要什么样格式的请求体格式数据。

12.第九节的Body - Nested Models(嵌套模型)

其实就是类似于集合里面的元素也可以是集合

==我们可以将请求体的属性值类型设置为列表、元组,列表里面的元素可以是正常的数据类型,也可以是请求体模型。当然,请求体的属性值也可以设置为请求体模型。==这种现象我们称之为模型的嵌套。

from typing import List,Set

from fastapi import FastAPI
from pydantic import BaseModel

app = FastAPI()


#嵌套的类:
class Image(BaseModel):
     url: UrlStr
    name: str

class Item(BaseModel):
    name: str
    description: str = None
    price: float
    tax: float = None
#将属性值的类型定义为列表
#   tags: list = [] 
#进一步定义列表里面元素的类型为整数
 #  tags: List[int] = [] 
    tags: Set[str] = []  # 表示属性值的类型为元组,元组中元素的类型为字符串
#表示类型是image
    images: List[Image] = None

@app.put("/items/{item_id}")
async def update_item(*, item_id: int, item: Item):
    results = {"item_id": item_id, "item": item}
    return results

UrlStr表示url格式类型的字符串。

例如"http://example.com/baz.jpg",“http://example.com/dave.jpg”

此时期望的请求体格式为:

{
    "name": "Foo",
    "description": "The pretender",
    "price": 42.0,
    "tax": 3.2,
    "tags": [
        "rock",
        "metal",
        "bar"
    ],
    "images": [
        {
            "url": "http://example.com/baz.jpg",
            "name": "The Foo live"
        },
        {
            "url": "http://example.com/dave.jpg",
            "name": "The Baz"
        }
    ]
}

小结:

我们可以为请求体的属性值定义不同的类型,可以是列表,可以是元组,列表或者元组里面的元素可以是字符串或者是数值,还可以是请求体模型。这种结构给fastAPi传递参数带来很大的方便性。

13.Response Model(响应模型)

可以在任何路径操作中使用参数 response_model 声明用于响应的模型:

  • @app.get():会向数据库发索取数据的请求,从而来获取信息,该请求就像数据库的select操作一样,只是用来查询一下数据,不会修改、增加数据,不会影响资源的内容,即该请求不会产生副作用。无论进行多少次操作,结果都是一样的。
  • @app.post():POST请求同PUT请求类似,都是向服务器端发送数据的,但是该请求会改变数据的种类等资源,就像数据库的insert操作一样,会创建新的内容。几乎目前所有的提交操作都是用POST请求的。
  • @app.put():PUT请求是向服务器端发送数据的,从而改变信息,该请求就像数据库的update操作一样,用来修改数据的内容,但是不会增加数据的种类等,也就是说无论进行多少次PUT操作,其结果并没有不同。
  • @app.delete():用来删除某一个资源的,该请求就像数据库的delete操作

浅谈HTTP中Get、Post、Put与Delete的区别_联想如何跳过联网-CSDN博客

既然PUT和POST操作都是向服务器端发送数据的,那么两者有什么区别呢。。。POST主要作用在一个集合资源之上的(url),而PUT主要作用在一个具体资源之上的(url/xxx),通俗一下讲就是,如URL可以在客户端确定,那么可使用PUT,否则用POST。

综上所述,我们可理解为以下:

1、POST /url 创建  
2、DELETE /url/xxx 删除 
3、PUT /url/xxx 更新
4、GET /url/xxx 查看

在 FastAPI 中,app.get() 、app.post()等方法用于定义 HTTP 请求的路由。这些方法接受多个参数,用于指定路由的路径、请求处理函数、依赖项等。

以下是主要参数:

path(必填):用于指定路由的路径。这是一个字符串,表示 URL 路径,可以包含路径参数和查询参数。
response_model:用于指定响应模型。响应模型是响应数据的数据结构,通常使用 Pydantic 模型来定义。
summary:一个简短的字符串,用于描述路由的目的或功能。
description:用于提供更详细的路由说明。
tags:一个字符串列表,用于标记路由,以便在文档中分类和组织路由。
dependencies:一个列表,指定在路由处理函数中需要注入的依赖项。
response_description:用于指定响应的描述信息。
deprecated:一个布尔值,表示路由是否已被弃用。
status_code:用于指定响应的 HTTP 状态码。
response_model_include 和 response_model_exclude:用于指定在响应模型中包含或排除的字段。
response_model_by_alias:一个布尔值,表示是否使用 Pydantic 模型中的别名来序列化响应。
response_model_exclude_unset:一个布尔值,表示在响应中排除未设置的字段。
response_model_exclude_defaults:一个布尔值,表示在响应中排除具有默认值的字段。
response_model_exclude_none:一个布尔值,表示在响应中排除值为 None 的字段。
operation_id:用于指定操作的唯一标识符。
deprecated:一个布尔值,表示路由是否已被弃用。
callbacks:一个字典,用于指定回调函数。
这些参数可以根据需求来灵活配置。一般来说,path 参数是必需的,而其他参数则根据需要来选择性地使用。
原文链接:https://blog.csdn.net/footless_bird/article/details/134242229

最终操作:

(1)创建main.py文件:(这里有多个接口)

###############################参数排序技巧:此时输入的网址就可以是http://127.0.0.1:8000/items/434?q=9
from fastapi import FastAPI, Path
from pydantic import BaseModel

app = FastAPI()

@app.get("/items2/{item_id}")
async def read_items(
 *, item_id: int = Path(..., title="The ID of the item to get"), q: str ):
    results = {"item_id": item_id}
    if q:
        results.update({"q": q})
    return results

###############################使用请求体,关键是app.post,不过这个之后网页就输出:没有细节了,是post的原因
# from fastapi import FastAPI
# from pydantic import BaseModel


class Item(BaseModel):
    name: str
    description: str = None
    price: float
    tax: float = None


# app = FastAPI()


@app.post("/items3/")
async def create_item(item: Item):
    return item.name



###############################声明路径参数的类型为str
# from fastapi import FastAPI

# app = FastAPI()

@app.get("/items/{item_name}")
def read_item(item_name: str):
    return {"item_id": item_name}




##############################声明路径参数的类型为int,并创建异步函数async def
# from fastapi import FastAPI

# app = FastAPI()

@app.get("/items/{item_id}")
async def read_item(item_id: int):
    return {"item_id": item_id}


###############################声明路径参数
# from fastapi import FastAPI

# app = FastAPI()

@app.get("/items/{item_id}") 
def read_item(item_id):
    return {"item_id": item_id}



##############################了解FastAPI程序结构
# from fastapi import FastAPI

# app = FastAPI()

@app.get("/data/bsy/")
async def root():
    return {"message": "Hello World"}

(2)使用终端开启uvicorn服务

uvicorn main:app --reload

或者在main的代码后面加上

if __name__ == "__main__":
    import uvicorn

    uvicorn.run(app, host="127.0.0.1", port=8000)

(3)运行成功会显示:

INFO:     Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
INFO:     Started reloader process [8438] using statreload
INFO:     Started server process [8440]
INFO:     Waiting for application startup.
INFO:     Application startup complete.

(4)测试:

可以输入一些网址看看是不是对应输出:

127.0.0.1:8000/items/hkhje3342

{
    "item_id": "hkhje3342"
}

127.0.0.1:8000/items2/32124?q=8

{
    "item_id": 32124,
    "q": "8"
}
实现能上传文件并保存到本地:

文件类型辨析

UploadFilebytes 相比有更多优势:

  • 使用 spooled 文件:
    • 存储在内存的文件超出最大上限时,FastAPI 会把文件存入磁盘;
  • 这种方式更适于处理图像、视频、二进制文件等大型文件,好处是不会占用所有内存;
  • 可获取上传文件的元数据;
  • 自带 file-like async 接口;
  • 暴露的 Python SpooledTemporaryFile 对象,可直接传递给其他预期「file-like」对象的库。

UploadFile 的属性如下:

  • filename: 上传文件名字符串(str),例如, myimage.jpg
  • content_type: 内容类型(MIME 类型 / 媒体类型)字符串(str),例如,image/jpeg
  • fileSpooledTemporaryFile( file-like 对象)。 其实就是 Python文件,可直接传递给其他预期 file-like 对象的函数或支持库。

UploadFile 支持以下 async 方法,(使用内部 SpooledTemporaryFile)可调用相应的文件方法。

  • write(data): 把 datastrbytes)写入文件;
  • read(size): 按指定数量的字节或字符(size (int))读取文件内容;
  • seek(offset): 移动至文件 offsetint)字节处的位置;
    • 例如,await myfile.seek(0) 移动到文件开头;
    • 执行 await myfile.read() 后,需再次读取已读取内容时,这种方法特别好用;
  • close(): 关闭文件。

因为上述方法都是 async 方法,要搭配「await」使用。

例如,在 async 路径操作函数 内,要用以下方式读取文件内容:

contents = await myfile.read()

代码:

from fastapi import FastAPI, File, UploadFile

app = FastAPI()

@app.post("/uploadfile/")
async def create_upload_file(file: UploadFile = File(...)):
    # 保存文件到本地  
    with open("xx23.png", "wb") as f:  
        f.write(file) 
    contents = await file.read()
    return {"filename": file.filename, "contents": contents}


# 路由操作函数上传一个文件并读取文件名称
@app.post("/files/")
async def create_file(file: bytes = File(...)):
    k=file
    # 保存文件到本地  
    with open("xx.png", "wb") as f:  
        f.write(file) 
    return {"16_num": k[0],
           "file_size": len(file)}
#k.hex()是bytes类型k的16进制数,可以使用索引和切片来访问bytes对象,就像字符串和列表一样。

测试:在http://127.0.0.1:8000/docs网页找到接口

点击右下角,然后上传文件cope.png(随便一个)

运行,之后本地绝对路径下就有了:

利用FunASR和fastapi创建一个语音识别的接口
from fastapi import FastAPI, File, UploadFile
from fastapi.responses import HTMLResponse
from funasr import AutoModel
app = FastAPI()
@app.get("/", response_class=HTMLResponse)
async def server():
    return """
    <html>
        <head>
    <title>File Upload</title>
        </head>
    <body>
    <form action="http://localhost:8000/upload" method="post" enctype="multipart/form-data">
        <input type="file" name="file" />
        <input type="submit" value="Upload" />
    </form>
    </body>
    </html>
    """
# # <body>
#             <h1>Fast api</h1>
            
#             <button onclick="alert('您点击了按钮')">点击我</button>
#         </body>
@app.post("/upload")
async def upload_file(file: UploadFile = File(...)):
    file_location = f"uploaded_files/{file.filename}"
    
    with open(file_location, "wb+") as file_object:
        file_object.write(await file.read())

       
    model = AutoModel(model="paraformer-zh",  vad_model="fsmn-vad", punc_model="ct-punc")
               # spk_model="cam++" 
    res = model.generate(input=file_location, batch_size_s=300, hotword='魔搭')
# print(res)

    
    return {"filename": file.filename, "message": "File successfully uploaded","results":res}

然后登录http://localhost:8000/上传文件:来源:好心分手(30秒版)(翻自 卢巧音) -王小帅-mp3免费在线下载播放-歌曲宝-找歌就用歌曲宝-MP3音乐高品质在线免费下载 (gequbao.com)

等一段时间,输出结果:

{
    "filename": "song.mp3",
    "message": "File successfully uploaded",
    "results": [
        {
            "key": "song",
            "text": "回头吧,不要走,不要这样离开我太多,结果往事中一失折磨,沮丧,挥去那一把愈发热两发搭不要伤一转头,好身人重过过,全都要飞扬光空通奔都唱着,这首歌会让他们分手,你是否原谅我?",
            "timestamp": [
                [
                    790,
                    1030
                ],
                [
                    1070,
                    1310
                ],等等。。

笑死,感觉识别得还不错,一般般。

原文:回头吧,不要走,不要这样离开我,恨太多,没结果往事重提是折磨,下半生,陪着你,怀疑快乐也不多,没有心,别在拖,心一早放开我,从头努力也坎坷,统统不要好过,为何唱着这首歌,为怨恨而分手,问你是否原谅我

识别结果:回头吧,不要走,不要这样离开我太多,结果往事中一失折磨,沮丧,挥去那一把愈发热两发搭不要伤一转头,好身人重过过,全都要飞扬光空通奔都唱着,这首歌会让他们分手,你是否原谅我?

正确字符数:大约 70-80(这需要手动或程序来确定,由于文本差异较大,这里只给出一个估计)

现在,我们可以计算正确率:

正确率 = (正确字符数 / 原始文本的字符总数) * 100%

正确率 = (75 / 135) * 100% ≈ 55.56%

估计是因为粤语,我听得也是识别出来的那种音哈哈。

但是不能识别.m4a文件会报错:Internal Server Error

中文识别正确率大概98%左右,主要是”的“和”地“分辨不出来,就把”和“识别成”个“,绕口令也能识别出来,正确率99%,英文识别率75%左右,有些音相同的容易识别错。

千问1.5代码生成微调

modelscope/swift: ms-swift: Use PEFT or Full-parameter to finetune 300+ LLMs or 50+ MLLMs. (Qwen2, GLM4v, Internlm2.5, Yi, Llama3.1, Llava-Video, Internvl2, MiniCPM-V, Deepseek, Baichuan2, Gemma2, Phi3-Vision, ...) (github.com)

参考这一篇,在linux上运行

# Experimental Environment: A100
# GPU Memory Requirement: 20GB
# Runtime: 3.1 hours
CUDA_VISIBLE_DEVICES=0 \
swift sft \
    --model_type qwen1half-7b-chat \
    --dataset blossom-math-zh \
    --num_train_epochs 5 \
    --sft_type lora \
    --output_dir output \
    --eval_steps 200 \

感觉数据集是魔搭平台的blossom-math-v2,但是跟上述的名称不太一样,难道是只是里面的中文包?,那个数据集有10004条,主要是一些数学问题

要跑好久,目前进度:

大模型微调包含以下四个核心步骤:
数据准备:

选择与任务相关的数据集。

对数据进行预处理,包括清洗、分词、编码等。

选择基础模型:

选择一个预训练好的大语言模型,如BERT、GPT-3等。

设置微调参数:

设定学习率、训练轮次(epochs)、批处理大小(batch size)等超参数。

根据需要设定其他超参数,如权重衰减、梯度剪切等。

微调流程:

加载预训练的模型和权重。

根据任务需求对模型进行必要的修改,如更改输出层。

选择合适的损失函数和优化器。

使用选定的数据集进行微调训练,包括前向传播、损失计算、反向传播和权重更新。
                        
原文链接:https://blog.csdn.net/qq_39172059/article/details/136693607

每天一些linux操作小知识

查看文件安装路径:

由于软件安装的地方不止一个地方,所有先说查看文件安装的所有路径(地址)。

这里以hbase为例。比如说我安装了Oracle,但是不知道文件都安装在哪些地方、放在哪些文件夹里,可 以用下面的命令查看所有的文件路径

在终端输入:

whereis hbase

回车,如果你安装好了hbase,就会显示文件安装的地址,例如我的显示(安装地址可能会不同)

hbase: /usr/bin/hbase /etc/hbase

可以看出来,hbase安装在是个目录里。

如果你没有安装hbase或者hbase安装没成功,则不会显示文件路径出来。只提示:

hbase:

二、查询运行文件所在路径:

如果你只要查询文件的运行文件所在地址,直接用下面的命令就可以了(还是以Oracle为例):

which oracle

结果会显示:

/usr/bin/oracle

来源:Linux新手入门如何知道程序安装在了哪里_linux查看安装程序根-CSDN博客

零散记录:

mobaxterm内拖动文件夹就可以实现windows本地上传文件到linux

huggingface网页可以搜到很多数据集是NLP学习者的一个必备平台

豆包(抖音登录就行)大模型很好用,就是图片生成可能复杂一点就不是我们想要的

Snipaste很好用还免费,可以按F1截图,然后F3提取出来,放在界面之首,方便查看

  • 21
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值