LLM导购生成:如何让AI不说谎、不编造、不乱推荐

LLM导购生成:如何让AI不说谎、不编造、不乱推荐

受控生成:给AI戴上紧箍咒

AI"胡说八道"的一天

用户问:"有没有适合敏感肌的洗面奶?"

AI回答

"为您推荐以下商品:

  1. 资生堂温和氨基酸洗面奶

    • 采用日本进口氨基酸配方
    • 富含玻尿酸和神经酰胺
    • 原价¥299,现在限时¥199!
    • 库存充足,下单即发货
  2. 兰蔻敏感肌修护洁面乳

    • 添加独家专利成分X-PRO
    • 获得美国FDA认证
    • 特价¥399,买二送一!"

问题来了:

  1. ❌ 系统里根本没有资生堂这款商品(AI编造的)
  2. ❌ "神经酰胺"、"X-PRO"都是AI瞎编的成分
  3. ❌ 价格完全是臆造的,实际价格是¥259
  4. ❌ "买二送一"促销活动并不存在
  5. ❌ 库存其实只剩2件了

这就是典型的LLM幻觉(Hallucination)问题:AI会自信满满地编造事实。

在电商场景,这是致命的:

  • 推荐不存在的商品 → 用户投诉
  • 编造价格信息 → 法律风险
  • 虚假库存 → 客服爆炸

那么,如何让AI只基于真实数据回答,不编造、不胡说?

这就是"受控生成"(Controlled Generation)要解决的问题。

受控生成的核心思路

传统LLM生成(无约束)

ini 复制代码
prompt = f"用户查询:{query}"
response = llm.invoke(prompt)
# AI自由发挥,天马行空

问题:

  • ❌ AI会调用训练数据中的"常识"(但可能过时或错误)
  • ❌ AI会"脑补"细节(编造成分、功效)
  • ❌ AI会生成看起来合理但完全虚假的信息

受控生成(强约束)

ini 复制代码
prompt = f"""
用户查询:{query}

【你只能使用以下商品信息】:
- 商品A:标题、描述、价格、库存
- 商品B:标题、描述、价格、库存

【严格规则】:
1. 只能推荐给定的商品
2. 不得编造任何信息
3. 价格必须使用提供的数据
4. 库存状态必须准确
"""
response = llm.invoke(prompt)
# AI被"约束"在给定的信息范围内

关键区别:

维度 无约束生成 受控生成
信息来源 LLM训练数据 + 想象 提供的上下文数据
准确性 不可控 可验证
幻觉率 高(20-40%) 低(<5%)
法律风险
用户信任

五层防护机制

我们设计了五层防护,确保AI不会乱说话。

第一层:严格的System Prompt

这是AI的"行为准则":

ini 复制代码
system_prompt = """
你是一个专业的电商商品导购助手。

【严格遵守的约束】:
1. 只能推荐给定的商品,不得编造或提及未提供的商品
2. 不得编造商品功效、成分或特性
3. 价格、库存、促销信息必须严格使用提供的实时数据,不得猜测
4. 推荐理由必须可回溯到商品的具体字段(标题、描述、标签等)
5. 如果某商品缺货,必须明确告知用户

【回答格式】:
1. 简短理解用户需求
2. 推荐2-3款最合适的商品,每款商品包含:
   - 商品名称
   - 推荐理由(基于商品特性)
   - 价格和促销信息
   - 库存状态
3. 给出选择建议

保持专业、友好的语气,回答简洁明了。
"""

关键点:

  • ✅ 明确禁止编造
  • ✅ 强制使用提供的数据
  • ✅ 要求可追溯性
  • ✅ 规定具体格式

第二层:结构化上下文

不是简单地把商品信息扔给AI,而是精心格式化:

python 复制代码
def _format_product_info(
    self,
    product_context: List[ProductContext],
    real_time_data: Dict[str, ProductRealTimeData]
) -> str:
    """格式化商品信息"""
    info_list = []
    
    for ctx in product_context:
        sku_id = ctx.sku_id
        rt_data = real_time_data.get(sku_id)
        
        # 清晰标注每个字段
        info = f"【{ctx.title}】\n"
        info += f"SKU: {sku_id}\n"
        info += f"商品描述: {ctx.description}\n"
        info += f"产品亮点: {', '.join(ctx.highlights)}\n"
        
        if ctx.instructions:
            info += f"使用说明: {ctx.instructions}\n"
        
        # 实时数据(价格、库存)单独标注
        if rt_data:
            info += f"当前价格: ¥{rt_data.price}\n"
            info += f"库存状态: {'有货' if rt_data.stock > 0 else '缺货'}({rt_data.stock}件)\n"
            if rt_data.promotion:
                info += f"促销活动: {rt_data.promotion}\n"
        
        info_list.append(info)
    
    return "\n---\n".join(info_list)

示例输出:

makefile 复制代码
【美赞臣安儿宝A+婴幼儿配方奶粉3段】
SKU: SKU_1001
商品描述: 美国原装进口,添加DHA和ARA,支持宝宝智力发育
产品亮点: 进口奶源, DHA配方, 易消化
使用说明: 每次30ml温水加一勺奶粉,摇匀后喂养
当前价格: ¥259.0
库存状态: 有货(45件)
促销活动: 限时8折

---

【惠氏启赋蓝钻婴幼儿奶粉3段】
SKU: SKU_1002
商品描述: 爱尔兰原装进口,添加OPO结构脂,亲和人体更易吸收
产品亮点: 进口奶源, OPO结构脂, 促进吸收
当前价格: ¥368.0
库存状态: 有货(12件)

为什么要这样格式化?

  1. 字段明确标注:AI知道哪些是标题、哪些是价格
  2. 实时数据突出:价格和库存单独标注,避免AI猜测
  3. 结构清晰 :用分隔符---区分不同商品
  4. 信息完整:所有必要信息都提供,AI不需要"脑补"

第三层:结构化输出(Structured Output)

传统方式的问题:

ini 复制代码
# AI可能返回任意格式
response = """
我推荐美赞臣奶粉!它有DHA配方,价格才199元,超划算!
还有惠氏的也不错,促销价299。
"""
# 怎么提取SKU?怎么验证价格?

结构化输出方案:

python 复制代码
from pydantic import BaseModel, Field

class LLMGenerateResponse(BaseModel):
    """强制LLM返回特定结构"""
    response: str = Field(description="生成的导购回答")
    recommended_skus: List[str] = Field(description="推荐的SKU ID列表")

# LangChain 1.1.0新特性
structured_llm = llm.with_structured_output(LLMGenerateResponse)

# AI必须返回这个结构
result: LLMGenerateResponse = structured_llm.invoke(messages)

# 类型安全,直接访问
print(result.response)
print(result.recommended_skus)  # ['SKU_1001', 'SKU_1002']

优势:

  • ✅ 强制AI返回特定格式
  • ✅ 类型安全,避免解析错误
  • ✅ 便于后续验证(知道AI推荐了哪些SKU)

第四层:多维度校验

即使有了约束,AI仍可能"打擦边球"。所以需要机器校验:

python 复制代码
def _validate_response(
    self,
    response_text: str,
    recommended_skus: List[str],
    valid_skus: Set[str],
    real_time_data: Dict[str, ProductRealTimeData]
) -> None:
    """多维度校验生成内容"""
    
    # 1️⃣ 校验SKU合法性
    invalid_skus = set(recommended_skus) - valid_skus
    if invalid_skus:
        raise ValidationError(f"LLM推荐了未提供的商品: {invalid_skus}")
    
    # 2️⃣ 校验价格信息
    price_pattern = r'¥\s*([\d,]+(?:.\d+)?)'
    found_prices = re.findall(price_pattern, response_text)
    
    for price_str in found_prices:
        price = float(price_str.replace(',', ''))
        valid_prices = [rt.price for rt in real_time_data.values()]
        
        if price not in valid_prices:
            raise ValidationError(f"发现未授权的价格: ¥{price}")
    
    # 3️⃣ 校验库存状态
    if '有货' in response_text or '缺货' in response_text:
        for sku, rt_data in real_time_data.items():
            if sku in response_text:
                expected_status = '有货' if rt_data.stock > 0 else '缺货'
                # 验证库存描述是否匹配
                if expected_status == '缺货' and '有货' in response_text:
                    raise ValidationError(f"商品{sku}已缺货,但生成文本说有货")
    
    # 4️⃣ 可扩展:校验成分、功效等
    # ...

校验流程:

markdown 复制代码
AI生成回答
    ↓
提取推荐的SKU → 验证是否在给定范围
    ↓
提取价格 → 验证是否匹配实时数据
    ↓
提取库存描述 → 验证是否准确
    ↓
全部通过 → 返回给用户
    ↓
任何失败 → 触发Fallback

第五层:Fallback降级机制

如果AI生成失败或校验不通过,使用模板生成:

python 复制代码
def _generate_fallback_response(
    self,
    query: str,
    product_context: List[ProductContext],
    real_time_data: Dict[str, ProductRealTimeData]
) -> str:
    """基于模板的安全降级方案"""
    
    response = f"根据您查询"{query}",为您推荐以下商品:\n\n"
    
    for i, ctx in enumerate(product_context[:3], 1):
        rt_data = real_time_data.get(ctx.sku_id)
        
        response += f"{i}. {ctx.title}\n"
        response += f"   特点: {', '.join(ctx.highlights[:3])}\n"
        
        if rt_data:
            response += f"   价格: ¥{rt_data.price}"
            if rt_data.promotion:
                response += f" ({rt_data.promotion})"
            response += "\n"
            
            if rt_data.stock > 0:
                response += f"   库存充足\n"
            else:
                response += f"   暂时缺货\n"
        
        response += "\n"
    
    return response.strip()

Fallback的特点:

  • ✅ 完全基于模板,零幻觉风险
  • ✅ 格式固定,质量稳定
  • ✅ 所有信息都可追溯
  • ❌ 缺乏个性化和灵活性

何时触发Fallback?

python 复制代码
try:
    # AI生成
    llm_response = structured_llm.invoke(messages)
    
    # 校验
    self._validate_response(...)
    
    return llm_response
    
except (Exception, ValidationError) as e:
    print(f"LLM生成失败: {e},使用Fallback")
    return self._generate_fallback_response(...)

实际生成效果

来看一个完整的生成案例。

输入数据

用户查询: "不上火的奶粉,适合6个月宝宝"

商品上下文:

ini 复制代码
product_context = [
    ProductContext(
        sku_id="SKU_1001",
        title="美赞臣安儿宝A+婴幼儿配方奶粉3段",
        description="美国原装进口,添加DHA和ARA,支持宝宝智力发育",
        highlights=["进口奶源", "DHA配方", "易消化", "温和配方"],
        instructions="每次30ml温水加一勺奶粉,摇匀后喂养"
    ),
    ProductContext(
        sku_id="SKU_1002",
        title="惠氏启赋蓝钻婴幼儿奶粉3段",
        description="爱尔兰原装进口,添加OPO结构脂,亲和人体更易吸收",
        highlights=["进口奶源", "OPO结构脂", "促进吸收", "低乳糖"],
        instructions="温水冲调,避免过热破坏营养"
    )
]

real_time_data = {
    "SKU_1001": ProductRealTimeData(
        price=259.0,
        stock=45,
        promotion="限时8折"
    ),
    "SKU_1002": ProductRealTimeData(
        price=368.0,
        stock=12,
        promotion=None
    )
}

AI生成的回答

markdown 复制代码
根据您的需求,为您推荐以下适合6个月宝宝的温和配方奶粉:

1. **美赞臣安儿宝A+婴幼儿配方奶粉3段**
   推荐理由:这款奶粉采用温和配方,添加DHA和ARA支持宝宝智力发育,
   进口奶源品质有保障,易消化的特点特别适合宝宝娇嫩的肠胃。
   
   当前价格:¥259(限时8折优惠)
   库存状态:库存充足(45件)
   
2. **惠氏启赋蓝钻婴幼儿奶粉3段**
   推荐理由:爱尔兰进口奶源,添加OPO结构脂,更亲和人体,促进营养吸收。
   低乳糖配方温和不刺激,适合敏感宝宝。
   
   当前价格:¥368
   库存状态:库存有限(12件)

选择建议:如果您更看重性价比,美赞臣A+正在限时8折,是不错的选择。
如果希望更温和、更易吸收,惠氏启赋的OPO配方值得考虑。

校验通过:

  • ✅ 推荐的SKU都在给定范围内
  • ✅ 价格信息准确(259和368)
  • ✅ 库存描述准确(45件=库存充足,12件=库存有限)
  • ✅ 促销信息准确(8折)
  • ✅ 推荐理由可追溯到商品特性

对比:无约束生成

如果没有约束,AI可能这样回答:

markdown 复制代码
为您推荐以下不上火的奶粉:

1. **美赞臣安儿宝A+**
   含有独家专利的益生元配方,能有效防止宝宝上火便秘。❌ 编造"益生元"
   临床研究表明,92%的宝宝使用后排便顺畅。❌ 编造数据
   
   特价¥199!❌ 价格错误(实际259)
   全国包邮,48小时送达!❌ 编造服务

2. **惠氏启赋**
   添加天然乳脂球膜,模拟母乳成分。❌ 夸大功效
   荣获2023年度最佳婴儿奶粉奖。❌ 编造奖项
   
   原价¥499,现价¥299!❌ 价格错误(实际368)

3. **雀巢能恩** ❌ 系统里根本没有这款商品!
   瑞士原装进口,100%有机奶源...

看到区别了吗?无约束的AI会:

  • 编造成分和功效
  • 瞎编价格和促销
  • 推荐不存在的商品
  • 制造虚假数据

核心代码实现

完整的生成服务实现:

python 复制代码
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
from pydantic import BaseModel, Field

class LLMGenerateResponse(BaseModel):
    """结构化输出"""
    response: str = Field(description="导购回答")
    recommended_skus: List[str] = Field(description="推荐的SKU列表")

class LLMGenerateService:
    def __init__(self, llm: ChatOpenAI):
        self.llm = llm
        
        # System Prompt(约束)
        self.prompt = ChatPromptTemplate.from_messages([
            ("system", """你是专业的电商导购助手。
            
【严格约束】:
1. 只能推荐给定的商品
2. 不得编造信息
3. 价格、库存必须使用提供的数据
4. 推荐理由必须可追溯
5. 缺货商品必须明确告知

【回答格式】:
1. 理解用户需求
2. 推荐2-3款商品(名称、理由、价格、库存)
3. 给出选择建议"""),
            ("human", "用户查询: {query}\n\n商品信息:\n{product_info}")
        ])
    
    def generate(self, input_data):
        # 1. 格式化商品信息
        product_info = self._format_product_info(
            input_data.product_context,
            input_data.real_time_data
        )
        
        # 2. 调用LLM(结构化输出)
        messages = self.prompt.invoke({
            "query": input_data.query,
            "product_info": product_info
        })
        
        try:
            # 使用结构化输出
            structured_llm = self.llm.with_structured_output(
                LLMGenerateResponse
            )
            llm_response = structured_llm.invoke(messages)
            
            # 3. 校验
            valid_skus = {ctx.sku_id for ctx in input_data.product_context}
            self._validate_response(
                llm_response.response,
                llm_response.recommended_skus,
                valid_skus,
                input_data.real_time_data
            )
            
            # 4. 提取实际引用
            actual_refs = self._extract_actual_references(
                llm_response.response,
                valid_skus
            )
            
            return LLMGenerateOutput(
                response=llm_response.response,
                referenced_skus=actual_refs,
                recommended_skus=llm_response.recommended_skus,
                generation_type="llm"
            )
            
        except Exception as e:
            print(f"LLM生成失败: {e},使用Fallback")
            # 5. Fallback
            fallback_response = self._generate_fallback_response(
                input_data.query,
                input_data.product_context,
                input_data.real_time_data
            )
            return LLMGenerateOutput(
                response=fallback_response,
                generation_type="fallback"
            )

性能优化技巧

1. 控制上下文长度

商品信息可能很长,需要精简:

python 复制代码
def _format_product_info(self, product_context, real_time_data):
    """精简格式化"""
    info_list = []
    
    for ctx in product_context[:5]:  # 🔥 只取前5个商品
        # 限制描述长度
        desc = ctx.description[:200]  # 🔥 最多200字
        
        # 限制亮点数量
        highlights = ', '.join(ctx.highlights[:5])  # 🔥 最多5个
        
        info = f"【{ctx.title}】\n"
        info += f"SKU: {ctx.sku_id}\n"
        info += f"描述: {desc}\n"
        info += f"亮点: {highlights}\n"
        # ...
    
    return "\n---\n".join(info_list)

Token节省:

makefile 复制代码
优化前: 10个商品 × 500字 = 5000 tokens
优化后: 5个商品 × 250字 = 1250 tokens
节省75%

2. 缓存商品数据

避免每次生成都查数据库:

python 复制代码
# 模块级缓存
_cached_product_map = None

def _get_product_map():
    global _cached_product_map
    if _cached_product_map is None:
        db = ProductDatabase()
        _cached_product_map = {p["sku_id"]: p for p in db.products}
    return _cached_product_map

class LLMGenerateService:
    def __init__(self, llm):
        self.llm = llm
        self.product_map = _get_product_map()  # 使用缓存

3. 实际引用提取

结构化输出的recommended_skus是AI声称推荐的商品,但实际生成文本中可能没有提及。需要提取实际引用:

python 复制代码
def _extract_actual_references(self, response_text, available_skus):
    """从文本中提取实际引用的SKU"""
    referenced = []
    for sku in available_skus:
        if sku in response_text:
            referenced.append(sku)
    return referenced

# 使用
actual_refs = self._extract_actual_references(
    llm_response.response,
    valid_skus
)

# 这样可以知道AI真正推荐了哪些商品

为什么需要这个?

AI可能返回:

json 复制代码
{
  "recommended_skus": ["SKU_1001", "SKU_1002", "SKU_1003"],
  "response": "我推荐SKU_1001和SKU_1002..."
}

实际只提到了两个SKU,第三个没有在文本中出现。

效果对比

测试场景

100个真实用户查询,每个查询3-5个候选商品

指标 无约束生成 受控生成
幻觉率(编造商品) 18% 0% ✅
价格错误率 35% 2% ✅
库存错误率 28% 1% ✅
推荐准确率 72% 94% ✅
用户满意度 3.2/5 4.6/5 ✅
平均生成时间 1.2s 1.5s
每次成本 $0.0002 $0.00025

关键改进:

  • ✅ 幻觉率从18%降到0%
  • ✅ 价格准确率从65%提升到98%
  • ✅ 用户满意度从3.2提升到4.6

代价:

  • ❌ 生成时间略慢(增加了校验环节)
  • ❌ 成本略高(更详细的prompt)

但这个代价完全值得!

真实案例

Case 1:编造商品

arduino 复制代码
无约束:推荐了"SK-II神仙水洗面奶"(系统没有)
受控:只推荐给定的商品 ✅

Case 2:价格虚假

复制代码
无约束:实际¥259的商品说¥199
受控:严格使用实时价格数据 ✅

Case 3:夸大功效

arduino 复制代码
无约束:"临床证明可消除痘印"(编造)
受控:"温和配方,适合敏感肌"(基于商品描述) ✅

高级功能:动态调整回答风格

可以根据用户画像调整生成风格:

python 复制代码
def _build_system_prompt(self, user_profile=None):
    """根据用户画像调整prompt"""
    
    base_prompt = """你是专业的导购助手..."""
    
    if user_profile:
        # 价格敏感用户
        if user_profile.get("price_sensitive"):
            base_prompt += "\n特别注意:用户对价格敏感,优先推荐性价比高的商品。"
        
        # 品质追求用户
        if user_profile.get("quality_focused"):
            base_prompt += "\n特别注意:用户注重品质,优先推荐高端商品。"
        
        # 新手用户
        if user_profile.get("is_newbie"):
            base_prompt += "\n特别注意:用户是新手,解释要详细易懂。"
    
    return base_prompt

监控和告警

生产环境必须监控:

python 复制代码
import logging
from datetime import datetime

class GenerationMonitor:
    def __init__(self):
        self.logger = logging.getLogger(__name__)
        self.metrics = {
            "total_generations": 0,
            "llm_success": 0,
            "fallback_used": 0,
            "validation_failures": 0
        }
    
    def log_generation(self, result, input_data):
        """记录生成结果"""
        self.metrics["total_generations"] += 1
        
        if result.generation_type == "llm":
            self.metrics["llm_success"] += 1
        elif result.generation_type == "fallback":
            self.metrics["fallback_used"] += 1
            # 告警:Fallback使用率过高
            if self._fallback_rate() > 0.1:  # 超过10%
                self.logger.warning(f"Fallback rate high: {self._fallback_rate():.2%}")
        
        # 记录详细日志
        self.logger.info(f"""
        Generation Result:
        - Query: {input_data.query}
        - Type: {result.generation_type}
        - SKUs: {result.recommended_skus}
        - Timestamp: {datetime.now()}
        """)
    
    def _fallback_rate(self):
        total = self.metrics["total_generations"]
        return self.metrics["fallback_used"] / total if total > 0 else 0

踩坑经验

1. System Prompt要简洁

错误示范:

ini 复制代码
system_prompt = """
你是一个专业的电商商品导购助手,需要帮助用户选择最合适的商品...
(省略1000字详细说明)
"""

Token消耗太大,而且AI可能抓不住重点。

正确做法:

ini 复制代码
system_prompt = """
你是电商导购助手。

【严格约束】:
1. 只推荐给定商品
2. 不得编造信息
3. 价格库存使用提供数据

【格式】:
1. 理解需求
2. 推荐商品
3. 给出建议
"""

简洁、结构化、重点突出。

2. 价格校验要考虑精度

python 复制代码
# ❌ 直接比较浮点数
if price == rt_data.price:
    pass

# ✅ 允许小误差
if abs(price - rt_data.price) < 0.01:
    pass

浮点数精度问题可能导致校验失败。

3. 结构化输出的兼容性

旧版LangChain不支持with_structured_output

python 复制代码
def _use_structured_output(self):
    """检查是否支持结构化输出"""
    return hasattr(self.llm, 'with_structured_output')

if self._use_structured_output():
    # 使用新API
    structured_llm = self.llm.with_structured_output(...)
else:
    # 降级到传统方式
    response = self.llm.invoke(...)
    # 手动解析JSON

4. Fallback要足够简单

Fallback是兜底方案,不要太复杂:

python 复制代码
# ❌ Fallback还调用其他AI服务
def fallback():
    summary = another_llm.summarize(...)
    return template.format(summary)

# ✅ 纯模板,零风险
def fallback():
    return f"推荐{product.title},价格¥{price}"

写在最后

受控生成的核心是约束和验证

  1. 约束输入:System Prompt、格式化上下文
  2. 约束输出:结构化输出、格式规范
  3. 验证结果:SKU校验、价格校验、库存校验
  4. 降级保障:Fallback机制
  5. 持续监控:告警、日志

技术选型建议:

  • 电商导购:必须受控生成(法律风险)
  • 内容创作:可以宽松一点(追求创意)
  • 客服问答:中等约束(平衡准确和体验)

关键原则:

在需要准确性的场景,永远不要完全信任LLM。 给它约束,验证它的输出,准备好降级方案。

希望这篇文章能帮到正在做LLM应用的同学。欢迎交流~


参考资源

技术栈

bash 复制代码
langchain-openai    # LLM集成
pydantic           # 结构化输出
regex              # 内容校验

本文基于真实生产环境的LLM导购系统,代码示例经过简化处理。受控生成是LLM应用的核心能力之一。

相关推荐
小小工匠4 小时前
AIGC - 使用 Nano Banana Pro 生成卡通信息图的完整指南
aigc
用户5191495848455 小时前
7-ZiProwler:CVE-2025-11001 漏洞利用工具
人工智能·aigc
Mintopia6 小时前
🪄 生成式应用的 **前端 orchestration 层(编排层)指南**
人工智能·llm·aigc
Mintopia7 小时前
🤖✨ 生成式应用架构师的修炼手册
人工智能·llm·aigc
安思派Anspire7 小时前
数据科学和ML领域的趋势是什么?为2026年做准备
aigc·openai·agent
艺术是真的秃头7 小时前
Trae:当编程从“编写”转向“对话”与“委派”
人工智能·python·ai·aigc
小霖家的混江龙10 小时前
不再费脑, 写给 AI 爱好者的矩阵 (Matrix) 入门指南
人工智能·llm·aigc
猫头虎11 小时前
猫头虎AI分享|可把GitHub代码库变成实时文档中心的一款实用型MCP工具:GitMCP,让AI随时访问最新文档代码,消除代码幻觉
人工智能·github·aigc·ai编程·ai写作·agi·ai-native
寻道码路11 小时前
【GitHub周榜】WrenAI:开源SQL AI代理,让Text-to-SQL轻松实现,开启自然语言与数据交互新时代
人工智能·sql·语言模型·开源·github·aigc·ai编程