@@ -1458,3 +1458,88 @@ def test_accuracy_reglu(shape, dtype):
14581458 res_out = flag_gems .reglu (input_tensor )
14591459
14601460 gems_assert_close (res_out , ref_out , dtype )
1461+
1462+
1463+ def _init_vllm ():
1464+ if not torch .cuda .is_available ():
1465+ return None , False
1466+ try :
1467+ from vllm ._custom_ops import apply_repetition_penalties as fn
1468+
1469+ t , m = torch .randn (2 , 1024 , device = "cuda" ), torch .zeros (
1470+ 2 , 1024 , dtype = torch .bool , device = "cuda"
1471+ )
1472+ fn (t , m , m , torch .full ((2 ,), 1.2 , device = "cuda" ))
1473+ return fn , True
1474+ except (ImportError , RuntimeError ):
1475+
1476+ def fallback (logits , pm , om , pens ):
1477+ for i in range (logits .shape [0 ]):
1478+ m = pm [i ] | om [i ]
1479+ logits [i ][m ] = torch .where (
1480+ logits [i ][m ] > 0 , logits [i ][m ] / pens [i ], logits [i ][m ] * pens [i ]
1481+ )
1482+
1483+ return fallback , True
1484+
1485+
1486+ _vllm_fn , _VLLM_OK = _init_vllm ()
1487+
1488+ _REP_PENALTY_CFG = {
1489+ "shapes" : [
1490+ (1 , 1024 ),
1491+ (1 , 4096 ),
1492+ (1 , 8192 ),
1493+ (8 , 4096 ),
1494+ (16 , 4096 ),
1495+ (32 , 1024 ),
1496+ (8 , 8192 ),
1497+ ],
1498+ "penalties" : [1.0 , 1.2 , 1.5 ],
1499+ "device" : torch .device ("cuda:0" ),
1500+ }
1501+
1502+
1503+ @pytest .mark .apply_repetition_penalties
1504+ @pytest .mark .skipif (
1505+ not _VLLM_OK or not torch .cuda .is_available (), reason = "need VLLM+CUDA"
1506+ )
1507+ @pytest .mark .parametrize ("shape" , _REP_PENALTY_CFG ["shapes" ])
1508+ @pytest .mark .parametrize ("penalty" , _REP_PENALTY_CFG ["penalties" ])
1509+ @pytest .mark .parametrize ("dtype" , FLOAT_DTYPES )
1510+ @pytest .mark .parametrize ("mask_mode" , ["random" , "empty" ])
1511+ def test_repetition_penalty (shape , penalty , dtype , mask_mode ):
1512+ device = _REP_PENALTY_CFG ["device" ]
1513+
1514+ logits = torch .randn (shape , dtype = dtype , device = device ).contiguous ()
1515+ logits_ori = logits .clone ()
1516+
1517+ if mask_mode == "random" :
1518+ prompt_mask = torch .randint (0 , 2 , shape , dtype = torch .bool , device = device )
1519+ output_mask = torch .randint (0 , 2 , shape , dtype = torch .bool , device = device )
1520+ else :
1521+ prompt_mask = torch .zeros (shape , dtype = torch .bool , device = device )
1522+ output_mask = torch .zeros (shape , dtype = torch .bool , device = device )
1523+
1524+ penalties = torch .full ((shape [0 ],), penalty , dtype = dtype , device = device )
1525+
1526+ logits_vllm = logits .clone ()
1527+ _vllm_fn (logits_vllm , prompt_mask .clone (), output_mask .clone (), penalties .clone ())
1528+ ref = to_reference (logits_vllm , True ).to (dtype )
1529+
1530+ with flag_gems .use_gems ():
1531+ flag_gems .apply_repetition_penalties (
1532+ logits , prompt_mask , output_mask , penalties
1533+ )
1534+ res = to_reference (logits , True ).to (dtype )
1535+
1536+ gems_assert_close (res , ref , dtype )
1537+
1538+ has_mask = (prompt_mask | output_mask ).any ().item ()
1539+ should_modify = has_mask and penalty != 1.0
1540+ if should_modify :
1541+ assert not torch .equal (
1542+ to_reference (logits , True ), to_reference (logits_ori , True )
1543+ ), "In-place未生效"
1544+ elif mask_mode == "empty" :
1545+ gems_assert_close (res , to_reference (logits_ori , True ).to (dtype ), dtype )
0 commit comments