飞书API(8):MySQL 入库定制版本

news2024/11/30 6:32:22

一、引入

通用版能解决百分之八九十的任务,剩下的部分任务需要进行定制。

先说明通用版本和定制版本有什么不同,通用版本就是只管大的数据类型,将数据处理为对应的类型入库,而定制版本会考虑局部列的数据类型,。举个简单的例子,比如说飞书编号为 2 的数据类型,它实际上包含了整数和小数,在通用版本,会把它处理为 double 或 float 类型以便保留小数的精度,但是定制版本可能会把整数列单独处理,入库为 int 数据类型类型。

二、常见场景及处理方法

针对定制列,本文提供的处理思想是在原有的基础上叠加一层处理,具体来讲,就是新增一个函数,将extract_key_fields()generate_create_ddl()这两个函数分别返回的值df_returncre_ddl作为参数传递给新的函数,然后在新函数中对需要定制的列进行处理,并将处理结果返回。
下面列举 4 个常用的场景来做演示。

  • 场景一:把数字列入库为 int 类型
  • 场景二:把日期列入库为 date 类型
  • 场景三:日期列给定默认最大值
  • 场景四:公式列保留具体值

2.1 场景一:把数字列入库为 int 类型

需求:将数字列(field_number)入库为 int 类型
前面在extract_key_fields()中已经对数字列的值提取出来,只不过统一存为 float 数据类型,这里只是将入库数据类型进行修改,所以修改建表的 DDL 即可。
根据前面generate_create_ddl()函数生成建表语句的规则,直接识别field_number float,然后替换为field_number int即可,参考代码如下:

def custom_field(df_return, cre_ddl):
    # 2.1 场景一:把数字列入库为 int 类型
    # 修改 SQL 即可
    cre_ddl = cre_ddl.replace('field_number float','field_number int')
    
    print('定制函数打印数据和建表语句')
    print('----------------------------------------------\n', df_return[['field_number']].head(5))
    print('----------------------------------------------\n', cre_ddl)
    return df_return, cre_ddl

2.2 场景二:把日期列入库为 date 类型

需求:将创建时间列(field_createdtime)入库为 date 类型。
这个需求也是直接修改 SQL 即可,虽然创建时间列带有时间,入库的时候会被截掉。当然想将时间截掉再入库也可以。参考代码如下:

def custom_field(df_return, cre_ddl):  
    # 2.2 场景二:把日期列入库为 date 类型
    # 修改 df,使用 datetime 试试行不行,不行再使用 date,随便一个 datetime 是否直接截断?
    # 修改 SQL
    cre_ddl = cre_ddl.replace('field_createdtime datetime','field_createdtime date')
    
    print('定制函数打印数据和建表语句')
    print('----------------------------------------------\n', df_return[['field_number','field_createdtime','field_date','field_numformula']].head(5))
    print('----------------------------------------------\n', cre_ddl)
    return df_return, cre_ddl

2.3 场景三:日期列给定默认最大值

需求:将日期列(field_date)为空的值替换为“2222-01-01 00:00:00”。
这个需求的处理方式跟前面反过来,入库数据类型不变,只处理 pandas 的 DataFrame 列即可。因为在extract_key_fields()中已经对日期列的空值做了填充,所以此处需要通过掩码识别填充值,然后再对填充值进行替换。参考代码如下:


def custom_field(df_return, cre_ddl):
    # 2.3 场景三:日期列给定默认最大值
    # 修改 df 即可
    #默认值改为 2222-01-01 00:00:00
    mask = df_return['field_date'] == pd.Timestamp('1970-01-01 08:00:01')
    df_return.loc[mask, 'field_date'] = pd.Timestamp('2222-01-01 00:00:00')

    print('定制函数打印数据和建表语句')
    print('----------------------------------------------\n', df_return[['field_number','field_createdtime','field_date','field_numformula']].head(5))
    print('----------------------------------------------\n', cre_ddl)
    return df_return, cre_ddl

2.4 场景四:公式列保留具体值

需求:将公式列(field_numformula)的数字提取出来,入库为 int 类型。
该需求相对复杂一些,需要处理 DataFrame 列和修改建表语句。在提取公式列的数据时,有一个关键的步骤就是将列值从 json 类型转回字典和列表嵌套的结构,使用json.loads()来实现。转换之后,再根据返回值的结构,将“value”取出再取第 0 个索引。修改建表语句则和前面 2.1 和 2.2 类似,参考代码如下:


def custom_field(df_return, cre_ddl): 
    # 2.4 场景四:公式列保留具体值
    # 修改 df
    # 修改 SQL
    df_return['field_numformula'] = df_return['field_numformula'].apply(lambda x:json.loads(x)['value'][0])
    cre_ddl = cre_ddl.replace('field_numformula varchar(256)','field_numformula int')
    
    print('定制函数打印数据和建表语句')
    print('----------------------------------------------\n', df_return[['field_number','field_createdtime','field_date','field_numformula']].head(5))
    print('----------------------------------------------\n', cre_ddl)
    return df_return, cre_ddl

注意:公式列返回值如果是数字,定制化入库为 int 类型时,要注意公式正确,把可能导致公式出错的情况先处理掉,避免出来公式错误导致入库失败。举个例子:0 不能作为除数,所以在写数字公式时,先判断除数列是不是 0,为 0 的时候给一个正常的返回值,比如 0,而不是 0 的之后才正常相除。

三、最终效果展示

将四种场景的代码进行整合,看看最终效果是什么样。
整合代码:

def custom_field(df_return, cre_ddl):
    # 2.1 场景一:把数字入库为 int 类型
    # 修改 SQL 即可
    cre_ddl = cre_ddl.replace('field_number float','field_number int')
    
    # 2.2 场景二:把日期入库为 date 类型
    # 修改 df,使用 datetime 试试行不行,不行再使用 date,随便一个 datetime 是否直接截断?
    # 修改 SQL
    cre_ddl = cre_ddl.replace('field_createdtime datetime','field_createdtime date')
    
    # 2.3 场景三:日期给定默认最大值
    # 修改 df 即可
    #默认值(未离组)改为 2222-01-01 00:00:00
    mask = df_return['field_date'] == pd.Timestamp('1970-01-01 08:00:01')
    df_return.loc[mask, 'field_date'] = pd.Timestamp('2222-01-01 00:00:00')
    
    # 2.4 场景四:公式保留具体值
    # 修改 df
    # 修改 SQL
    df_return['field_numformula'] = df_return['field_numformula'].apply(lambda x:json.loads(x)['value'][0])
    cre_ddl = cre_ddl.replace('field_numformula varchar(256)','field_numformula int')
    
    print('定制函数打印数据和建表语句')
    print('----------------------------------------------\n', df_return[['field_number','field_createdtime','field_date','field_numformula']].head(5))
    print('----------------------------------------------\n', cre_ddl)
    return df_return, cre_ddl

然后将上面代码放入上小结最终的代码中,放置方法如下:
image.png

最终代码执行结果如下:
image.png

登录 MySQL 再查查入库的数据的数据类型(如下),结果符合预期。
image.png

再看看入库的数据(如下),也符合定制化需求。
image.png

最终完整代码如下:

import requests
import json
import datetime
import pandas as pd
from sqlalchemy import create_engine, text
from urllib.parse import urlparse, parse_qs

def get_table_params(bitable_url):
    # bitable_url = "https://feishu.cn/base/aaaaaaaa?table=tblccc&view=vewddd"
    parsed_url = urlparse(bitable_url)              #解析url:(ParseResult(scheme='https', netloc='feishu.cn', path='/base/aaaaaaaa', params='', query='table=tblccc&view=vewddd', fragment='')
    query_params = parse_qs(parsed_url.query)       #解析url参数:{'table': ['tblccc'], 'view': ['vewddd']}
    app_token = parsed_url.path.split('/')[-1]
    table_id = query_params.get('table', [None])[0]
    view_id = query_params.get('view', [None])[0]
    print(f'成功解析链接,app_token:{app_token},table_id:{table_id},view_id:{view_id}。关联方法:get_table_params。')
    return app_token, table_id, view_id

def get_tenant_access_token(app_id, app_secret):
    url = "https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal"
    payload = json.dumps({
        "app_id": app_id,
        "app_secret": app_secret
    })
    headers = {'Content-Type': 'application/json'}
    response = requests.request("POST", url, headers=headers, data=payload)
    tenant_access_token = response.json()['tenant_access_token']
    print(f'成功获取tenant_access_token:{tenant_access_token}。关联函数:get_table_params。')
    return tenant_access_token

def get_bitable_datas(tenant_access_token, app_token, table_id, view_id, page_token='', page_size=20):
    url = f"https://open.feishu.cn/open-apis/bitable/v1/apps/{app_token}/tables/{table_id}/records/search?page_size={page_size}&page_token={page_token}&user_id_type=user_id"
    payload = json.dumps({"view_id": view_id})
    headers = {
        'Content-Type': 'application/json',
        'Authorization': f'Bearer {tenant_access_token}'
    }
    response = requests.request("POST", url, headers=headers, data=payload)
    print(f'成功获取page_token为【{page_token}】的数据。关联函数:get_bitable_datas。')
    return response.json()


def get_all_bitable_datas(tenant_access_token, app_token, table_id, view_id, page_token='', page_size=20):
    has_more = True
    feishu_datas = []
    while has_more:
        response = get_bitable_datas(tenant_access_token, app_token, table_id, view_id, page_token, page_size)
        if response['code'] == 0:
            page_token = response['data'].get('page_token')
            has_more = response['data'].get('has_more')
            # print(response['data'].get('items'))
            # print('\n--------------------------------------------------------------------\n')
            feishu_datas.extend(response['data'].get('items'))
        else:
            raise Exception(response['msg'])
    print(f'成功获取飞书多维表所有数据,返回 feishu_datas。关联函数:get_all_bitable_datas。')
    return feishu_datas

def get_bitable_fields(tenant_access_token, app_token, table_id, page_size=500):
    url = f"https://open.feishu.cn/open-apis/bitable/v1/apps/{app_token}/tables/{table_id}/fields?page_size={page_size}"
    payload = ''
    headers = {'Authorization': f'Bearer {tenant_access_token}'}
    
    response = requests.request("GET", url, headers=headers, data=payload)
    field_infos = response.json().get('data').get('items')
    print('成功获取飞书字段信息,关联函数:get_bitable_fields。')
    return field_infos

def merge_list(ls_from, ls_join, on=None, left_on=None, right_on=None):
    """将两个[{},{}]结构的数据合并"""
    df_from = pd.DataFrame(ls_from)
    df_join = pd.DataFrame(ls_join)
    if on is not None:
        df_merge = df_from.merge(df_join, how='left', on=on)
    else:
        df_merge = df_from.merge(df_join, how='left', left_on=left_on, right_on=right_on) # , suffixes=('', '_y')
    print(f'成功合并列表或DataFrame。关联方法:merge_list。')
    return df_merge


def extract_key_fields(feishu_datas, store_fields_info_df):
    """处理飞书数据类型编号的数据"""
    print('开始处理飞书多维表关键字段数据...')
    # 需要record_id 和 订单号,用于和数据库数据匹配
    df_feishu = pd.DataFrame(feishu_datas)
    df_return = pd.DataFrame()
    
    #根据列的数据类型,分别处理对应的数据。注意:仅返回以下列举的数据类型,如果fields_map的内容包含按钮、流程等数据类型的飞书列,忽略。
    for index, row in store_fields_info_df.iterrows():
        if row['type'] == 1:       #文本
            df_return[row['tb_field_name']] = df_feishu['fields'].apply(lambda x:x.get(row['field_name'],[{}])[0].get('text'))
        
        elif row['type'] in (2, 3, 7, 13, 1005):  #数字、单选、复选框、手机号、自动编号
            df_return[row['tb_field_name']] = df_feishu['fields'].apply(lambda x:x.get(row['field_name']))
        
        elif row['type'] in (5, 1001, 1002):         #日期(包含创建和更新),需要加 8 小时,即 8*60*60*1000=28800 秒
            df_return[row['tb_field_name']] = pd.to_datetime(df_feishu['fields'].apply(lambda x:28800 + int(x.get(row['field_name'],1000)/1000)), unit='s')
        
        elif row['type'] in(11, 23, 1003, 1004):       #人员、群组、创建人、修改人,遍历取name
            df_return[row['tb_field_name']] = df_feishu['fields'].apply(lambda x: ','.join([i.get('name') for i in x.get(row['field_name'],[{"name":""}])]))  # 需要遍历

        elif row['type'] == 15:    #链接
            df_return[row['tb_field_name']] = df_feishu['fields'].apply(lambda x:x.get(row['field_name'],{}).get('link'))
        
        elif row['type'] == 17:    #附件,遍历取url
            df_return[row['tb_field_name']] = df_feishu['fields'].apply(lambda x:json.dumps([i.get('url') for i in x.get(row['field_name'],[{}])])) #需要遍历
    
        elif row['type'] in(18, 21):    #单向关联、双向关联,取link_record_ids
            df_return[row['tb_field_name']] = df_feishu['fields'].apply(lambda x:json.dumps(x.get(row['field_name'],{}).get('link_record_ids')))
    
        elif row['type'] in(4, 19, 20):    #多选、查找引用和公式
            df_return[row['tb_field_name']] = df_feishu['fields'].apply(lambda x:json.dumps(x.get(row['field_name'])))
    
        elif row['type'] == 22:    #地理位置
            df_return[row['tb_field_name']] = df_feishu['fields'].apply(lambda x:x.get(row['field_name'],{}).get('location'))
            
    #加上record_id
    df_return['record_id'] = df_feishu.record_id
    #加上表更新字段
    df_return['last_modified_time'] = datetime.datetime.now()
    print(f'成功提取入库字段的数据。关联方法:extract_key_fields。')
    return df_return

def generate_create_ddl(db_table_name, store_fields_info_df):
    """"""
    # 代码一:生成DDL语句
    cre_ddl = f"CREATE TABLE if not exists {db_table_name} (\n"
    for index, row in store_fields_info_df.iterrows():
      cre_ddl += f"    {row['tb_field_name']} {row['mysql_type']} comment '{row['feishu_field_name']}',\n"
    default_fields = "record_id varchar(20) comment '行record_id',\nlast_modified_time datetime comment '数据更新时间' \n);"
    # cre_ddl = cre_ddl[:-2] + "\n);"
    cre_ddl = cre_ddl + default_fields
    print(f'成功生成 mysql 建表 DDL。关联方法:generate_create_ddl。')
    return cre_ddl

def cre_mysql_table(create_table_sql, connection_conf_info):
    """注意:该函数支持执行任意SQL,而不仅仅是建表 SQL。"""
    # from sqlalchemy import create_engine, text
    # 创建 SQLAlchemy engine 对象,这里以 MySQL 为例
    # engine = create_engine('mysql://username:password@host:port/dbname')
#     engine = create_engine('mysql://root:password@127.0.0.1:3306/test')
    engine = create_engine(connection_conf_info)
    
    # 定义一个建表的 SQL 语句
    # create_table_sql = ''''''
    
    # 使用 execute() 方法执行 SQL 语句
    with engine.connect() as connection:
        connection.execute(text(create_table_sql))
        print(f'成功执行 mysql 建表语句。关联方法:cre_mysql_table。')

def insert_mysql_table(feishu_df, table_name, connection_conf_info):
    # from sqlalchemy import create_engine
    
    # 创建 SQLAlchemy engine 对象,这里以 MySQL 为例
    # engine = create_engine('mysql://username:password@host:port/dbname')
#     engine = create_engine('mysql://root:password@127.0.0.1:3306/test')
    engine = create_engine(connection_conf_info)
    
    # 将 DataFrame 直接写入 MySQL 数据库
    feishu_df.to_sql(name=table_name, con=engine, if_exists='append', index=False)
    print(f'成功将飞书数据写入 mysql 数据表。关联方法:insert_mysql_table。')

def custom_field(df_return, cre_ddl):
    # 2.1 场景一:把数字入库为 int 类型
    # 修改 SQL 即可
    cre_ddl = cre_ddl.replace('field_number float','field_number int')
    
    # 2.2 场景二:把日期入库为 date 类型
    # 修改 df,使用 datetime 试试行不行,不行再使用 date,随便一个 datetime 是否直接截断?
    # 修改 SQL
    cre_ddl = cre_ddl.replace('field_createdtime datetime','field_createdtime date')
    
    # 2.3 场景三:日期给定默认最大值
    # 修改 df 即可
    #默认值(未离组)改为 2222-01-01 00:00:00
    mask = df_return['field_date'] == pd.Timestamp('1970-01-01 08:00:01')
    df_return.loc[mask, 'field_date'] = pd.Timestamp('2222-01-01 00:00:00')
    
    # 2.4 场景四:公式保留具体值
    # 修改 df
    # 修改 SQL
    df_return['field_numformula'] = df_return['field_numformula'].apply(lambda x:json.loads(x)['value'][0])
    cre_ddl = cre_ddl.replace('field_numformula varchar(256)','field_numformula int')
    
    print('定制函数打印数据和建表语句')
    print('----------------------------------------------\n', df_return[['field_number','field_createdtime','field_date','field_numformula']].head(5))
    print('----------------------------------------------\n', cre_ddl)
    return df_return, cre_ddl

def main(connection_conf_info, mysql_table_name, bitable_url, fields_map):
    # 基本配置
    app_token, table_id, view_id = get_table_params(bitable_url)
    app_id = 'your_app_id'
    app_secret = 'your_app_secret'
    tenant_access_token = get_tenant_access_token(app_id, app_secret)
    page_size = 50
    
    # 获取飞书多维表所有数据
    feishu_datas = get_all_bitable_datas(tenant_access_token, app_token, table_id, view_id, page_size=page_size)

    #获取飞书字段信息
    feishu_fields = get_bitable_fields(tenant_access_token, app_token, table_id)

    # 以 fields_map 为准关联数据
    store_fields_info_df = merge_list(fields_map, feishu_fields, left_on='feishu_field_name', right_on='field_name')

    # 处理入库字段数据
    feishu_df = extract_key_fields(feishu_datas, store_fields_info_df)

    # 关联入库数据类型
    data_type_map = [{"feishu_type": 1   ,"mysql_type": "varchar(256)"   }
                ,{"feishu_type": 2   ,"mysql_type": "float"          }
                ,{"feishu_type": 3   ,"mysql_type": "varchar(256)"   }
                ,{"feishu_type": 4   ,"mysql_type": "json"           }
                ,{"feishu_type": 5   ,"mysql_type": "datetime"       }
                ,{"feishu_type": 7   ,"mysql_type": "bool"           }
                ,{"feishu_type": 11  ,"mysql_type": "varchar(256)"   }
                ,{"feishu_type": 13  ,"mysql_type": "varchar(256)"   }
                ,{"feishu_type": 15  ,"mysql_type": "varchar(256)"   }
                ,{"feishu_type": 17  ,"mysql_type": "varchar(256)"   }
                ,{"feishu_type": 18  ,"mysql_type": "json"           }
                ,{"feishu_type": 19  ,"mysql_type": "varchar(256)"   }
                ,{"feishu_type": 20  ,"mysql_type": "varchar(256)"   }
                ,{"feishu_type": 21  ,"mysql_type": "json"           }
                ,{"feishu_type": 22  ,"mysql_type": "varchar(256)"   }
                ,{"feishu_type": 23  ,"mysql_type": "varchar(256)"   }
                ,{"feishu_type": 1001,"mysql_type": "datetime"       }
                ,{"feishu_type": 1002,"mysql_type": "datetime"       }
                ,{"feishu_type": 1003,"mysql_type": "varchar(256)"   }
                ,{"feishu_type": 1004,"mysql_type": "varchar(256)"   }
                ,{"feishu_type": 1005,"mysql_type": "varchar(256)"   }]

    store_fields_info_df = merge_list(store_fields_info_df, data_type_map, left_on='type', right_on='feishu_type')

    # 生成 MySQL 建表 DDL
    create_table_sql = generate_create_ddl(mysql_table_name, store_fields_info_df)
    
    # 定制化
    feishu_df, create_table_sql = custom_field(feishu_df, create_table_sql)
    
    # 建 mysql 数据表
    cre_mysql_table(create_table_sql, connection_conf_info)
    # MySQL 表插入数据
    insert_mysql_table(feishu_df, mysql_table_name, connection_conf_info)
    db_name = connection_conf_info.split('/')[-1]
    print(f'成功将飞书多维表({bitable_url})的数据入库到 mysql 数据表:{db_name}.{mysql_table_name}。')

if __name__ == '__main__':
    connection_conf_info = 'mysql://root:password@127.0.0.1:3306/test'
    mysql_table_name = 'feishu_data_type_test'
    bitable_url = "https://xxxx.feishu.cn/base/PtRdbPjCFa5Og5sry0lcD1yPnKg?table=tblcc5oozF4EOBOE&view=vewVaEFMO6"
    fields_map = [{'tb_field_name': 'field_text','feishu_field_name': '文本'}
            ,{'tb_field_name': 'field_email','feishu_field_name': 'email'}
            ,{'tb_field_name': 'field_select','feishu_field_name': '单选'}
            ,{'tb_field_name': 'field_mobile','feishu_field_name': '电话号码'}
            ,{'tb_field_name': 'field_no','feishu_field_name': '自动编号'}
            ,{'tb_field_name': 'field_member1','feishu_field_name': '人员1'}
            ,{'tb_field_name': 'field_group1','feishu_field_name': '群组1'}
            ,{'tb_field_name': 'field_creator','feishu_field_name': '创建人'}
            ,{'tb_field_name': 'field_modifier','feishu_field_name': '修改人'}
            ,{'tb_field_name': 'field_member2','feishu_field_name': '人员2'}
            ,{'tb_field_name': 'field_group2','feishu_field_name': '群组2'}
            ,{'tb_field_name': 'field_url','feishu_field_name': '超链接'}
            ,{'tb_field_name': 'field_location','feishu_field_name': '地理位置'}
            ,{'tb_field_name': 'field_findnum','feishu_field_name': '查找引用数值'}
            ,{'tb_field_name': 'field_numformula','feishu_field_name': '数字公式'}
            ,{'tb_field_name': 'field_number','feishu_field_name': '数字'}
            ,{'tb_field_name': 'field_progress','feishu_field_name': '进度'}
            ,{'tb_field_name': 'field_money','feishu_field_name': '货币'}
            ,{'tb_field_name': 'field_Rating','feishu_field_name': '评分'}
            ,{'tb_field_name': 'field_bool','feishu_field_name': '复选框'}
            ,{'tb_field_name': 'field_date','feishu_field_name': '日期'}
            ,{'tb_field_name': 'field_createdtime','feishu_field_name': '创建时间'}
            ,{'tb_field_name': 'field_updatedtime','feishu_field_name': '更新时间'}
            ,{'tb_field_name': 'field_mulselect','feishu_field_name': '多选'}
            ,{'tb_field_name': 'field_singleunion','feishu_field_name': '单向关联'}
            ,{'tb_field_name': 'field_doubleunion','feishu_field_name': '双向关联'}
            ,{'tb_field_name': 'field_file','feishu_field_name': '附件'}
            ]
    main(connection_conf_info, mysql_table_name, bitable_url, fields_map)

四、小结

本文介绍了如何对上一小节的通用版本的代码进行定制化修改列的值和数据类型。
基本思想就是不动原来的结构,直接叠加一层(新增一个函数)来处理,通过一个函数对数据列的不同需求进行定制化修改。
四种常用的场景的处理方式小结如下:

场景处理方式
场景一:把数字列入库为 int 类型修改 DDL:指定列的 float 类型改为 int 类型
场景二:把日期列入库为 date 类型修改 DDL:指定列的 datetime 类型改为 date 类型
场景三:日期列给定默认最大值修改 DataFrame,将默认值改为指定值
场景四:公式列保留具体值修改 DataFrame,取出公式返回的具体值
修改 DDL:指定列的 string 类型改为 int 类型(根据需求修改,如果返回的时文本类型,可以不用修改,如果是时间类型,可改为 datetime 类型)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1667833.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Linux i2c工具——i2c_tools

1 简介 i2c-tools是一个用于处理I2C(Inter-Integrated Circuit)总线的工具集,它在Linux环境中广泛使用。这个工具集包含了一系列命令行工具,用于在I2C总线上执行各种操作,例如扫描设备、读取/写入寄存器、检测设备等。…

Copilot for Microsoft 365 扩充新增 16 种语言

最近,微软公司发布公告,进一步扩大 Copilot for Microsoft 365 语言支持,新增 16 种,支持的语言总数达到 25 种。 新支持的语言如下: 阿拉伯语 捷克语 丹麦语 荷兰语 芬兰语 希伯来语 匈牙利语 韩语 挪威语&am…

LLama3大模型本地部署 仅需6步完成对话模型本地安装部署。附赠ui配置、第三方微调模型、中文模型下载地址

本篇分为三部分 一:6步完成llama3大模型本地部署 二:8步完成llama3可视化对话界面安装 三:微调模型、中文模型下载资源分享 一、LLama3 大模型本地部署安装 首先去mata官网下载ollama客户端 Ollama 选择合适的操作系统平台后点击dowload按钮…

车规级低功耗汽车用晶振SG-9101CGA

车规级晶振SG-9101CGA属于爱普生9101系列,是一款可编程晶振。SG-9101CGA车规级晶振采用2.5x2.0mm封装,利用PLL技术生产,此款振荡器的频率范围从0.67M~170MHZ任一频点可选,步进1ppm,采用标准CMOS输出,最大输…

你知道C++多少——默认成员函数

🌈个人主页:小新_- 🎈个人座右铭:“成功者不是从不失败的人,而是从不放弃的人!”🎈 🎁欢迎各位→点赞👍 收藏⭐️ 留言📝 🏆所属专栏&#xff1…

临时邮箱API发送邮件的安全性?如何保障?

临时邮箱API发送邮件的步骤有哪些?设置邮箱API方法? 电子邮件作为一种重要的通信方式,而临时邮箱API作为一种新兴的邮件发送技术,其安全性更是成为大家关注的焦点。那么,临时邮箱API发送邮件的安全性究竟如何呢&#…

本地vite启动的vue项目使用nginx代理

前提: 必须在同一网段或者相同的局域网!!! nginx下载通道: https://nginx.org/en/download.html 步骤: 1、最好下载稳定版本: 2、下载后直接解压(注意:解压后不要放…

【代码随想录37期】 第一周总结

周末再写一遍 【代码随想录37期】Day01 二分查找 移除元素 【代码随想录37期】Day02 有序数组的平方、长度最小的子数组、螺旋矩阵Ⅱ 【代码随想录37期】Day03 移除链表元素、设计链表、反转链表 【代码随想录37期】Day04 两两交换链表中的节点、删除链表的倒数第N个节点、链…

Baidu Comate智能编码助手:AI编程时代提升效率的好帮手

目录 写在前面一、如何安装二、如何使用场景需求体验步骤 三、AI 编程实战指令功能插件功能知识库功能 四、问题建议五、体验总结🚀写在最后 写在前面 Baidu Comate 是基于文心大模型的 AI编程工具,它结合百度积累多年的编程现场大数据和外部优秀开源数据…

JavaWeb文件上传/下载(Servlet)

效果 文件下载 文件上传 项目概述 Jakarta EE9&#xff0c;Web项目 项目文件结构 0 maven依赖&#xff0c;资源文件 <!-- lombok插件--> <dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId&g…

proteus示波器不弹出来

运行后示波器没有弹出来 点击调试&#xff08;Debug&#xff09;在点击Digital Oscilloscope 完成

[OpenGL高级光照] 阴影改善

目录 一 阴影失真 二 阴影改善 2.1 减小片段深度值 2.2 降低纹理 2.3 注意事项 三 消除Repeat的问题 3.1 让裁剪矩阵的立方体变大 ​3.2 利用采样范围重置 四 精度问题 本章节源码 点击此处 一 阴影失真 在上一篇中,实现了阴影效果之后,但是我们会发现阴影效果中地面…

Linux基础之进程的基本概念

目录 一、进程的基本概念 1.1 什么是进程 1.2 PCB的概念 1.3 进程的查看 1.3.1 查看进程方式一 1.3.2 查看进程的方式二 1.4 父进程与子进程 一、进程的基本概念 1.1 什么是进程 进程是什么&#xff1f; 课本概念&#xff1a;程序的一个执行实例&#xff0c;正在执行的…

GENRE

1、整体设计 该工作&#xff08;GENRE&#xff09;在新闻推荐的场景下&#xff0c;用 LLM 构造了三个不同的prompts&#xff0c;分别来进行新闻摘要的改写&#xff0c;用户画像的构建&#xff0c;还有样本增强。 2、分模块介绍 摘要改写&#xff1a;把新闻的title&#xff0c;…

Golang | Leetcode Golang题解之第84题柱状图中最大的矩形

题目&#xff1a; 题解&#xff1a; func largestRectangleArea(heights []int) int {n : len(heights)left, right : make([]int, n), make([]int, n)for i : 0; i < n; i {right[i] n}mono_stack : []int{}for i : 0; i < n; i {for len(mono_stack) > 0 &&am…

亚信安慧AntDB新篇章:数据库技术飞跃

随着大数据时代的到来&#xff0c;对数据库的需求愈发强烈。在这一背景下&#xff0c;国产数据库逐渐崭露头角&#xff0c;亚信安慧AntDB作为重要的代表产品之一正积极参与到激烈的市场竞争中。亚信安慧AntDB不仅追求技术的革新和突破&#xff0c;同时也致力于满足用户日益增长…

国内智能搜索工具实战教程

大家好,我是herosunly。985院校硕士毕业,现担任算法研究员一职,热衷于机器学习算法研究与应用。曾获得阿里云天池比赛第一名,CCF比赛第二名,科大讯飞比赛第三名。拥有多项发明专利。对机器学习和深度学习拥有自己独到的见解。曾经辅导过若干个非计算机专业的学生进入到算法…

数据与结构--堆

堆 堆的概念 堆&#xff1a;如果有一个关键码的集合K{k0,k1,k2,…,kn-1}&#xff0c;把它的所有元素按完全二叉树的顺序存储方式存储在一个一维数组中&#xff0c;并满足ki<k2i1且ki<k2i2&#xff08;或满足ki>k2i1且ki>k2i2&#xff09;&#xff0c;其中i0,1,2,…

综合性练习(验证码案例)

目录 一、需求 二、准备工作 三、约定前后端交互接口 1、需求分析 2、接口定义 四、Hutool工具介绍 1、引入依赖 2、测试使用Hutool生成验证码 五、实现服务器端代码 代码解读&#xff1a; 六、调整前端页面代码 七、运行测试 随着安全性的要求越来越高&#xff0c…

数据库 MySQL 四种事务隔离级别代码演示 -- 读未提交;读已提交;可重复读;串行化

前提 # 设置数据库隔离级别 SET SESSION TRANSACTION ISOLATION LEVEL 隔离级别;# 查询事务隔离级别 select transaction_isolation;事务处理的分离水平对应的数据整合情况&#xff1a; 隔离级别非提交读取&#xff08;脏读&#xff09;不可重复读取幻读READ UNCOMMITED√√√…