大模型微调利器LLaMA-Factory深度解析:一个集成可视化训练、多模型适配、高效PEFT算法与端到端评估的语言模型微调框架。

分享我的Colab文件:

https://colab.research.google.com/drive/1XIi1E_L0dod2CoJIz9QVEYCjQKTKAuhT?usp=sharing

把它另存到你的本地Colab笔记本(详细步骤见2025-08-11文章)

点击左侧上传你的数据集文件.json格式。

一定要修改第二个单元格代码filepath = ” “(你上传的数据集的名称)

免费 T4 申请教程:https://zhuanlan.zhihu.com/p/642542618

点击Run all一键运行所有代码格

点击Running on public URL的链接: https://b1b7e1e391675e8e31.gradio.live

GitHub提供文档有详细介绍:https://github.com/hiyouga/LLaMA-Factory/blob/main/README_zh.md

提供的视频非常详细,一看就会。

LangExtract第二期代码文件

请先在.env文件中设置好 OPENAI_API_KEY
1.extract_tool.py :
“””
通用信息提取工具
使用方法: python extract_tool.py <配置名称> <输入文件>
“””

import langextract as lx
import os
import sys
import argparse
from datetime import datetime
from pathlib import Path
from dotenv import load_dotenv
from collections import Counter

# 导入配置
from config import EXTRACTION_CONFIGS

# 自动加载 .env 文件,同时加载 OPENAI_API_KEY 和 LANGEXTRACT_API_KEY
load_dotenv()

def process_document(config_name, input_file):
“””
根据配置处理文件 (已整合所有成功秘诀)
“””
# — 1. 配置和文件检查 —
if config_name not in EXTRACTION_CONFIGS:
print(f”❌ 错误: 未找到配置 ‘{config_name}'”)
sys.exit(1)

if not Path(input_file).exists():
print(f”❌ 错误: 文件不存在 ‘{input_file}'”)
sys.exit(1)

config = EXTRACTION_CONFIGS[config_name]

print(“-” * 50)
print(f”📁 处理文件: {input_file} | ⚙️ 配置: {config_name}”)
print(f”📝 任务描述: {config.get(‘description’, ‘无描述’)}”)

with open(input_file, ‘r’, encoding=’utf-8′) as f:
text = f.read()
print(f”📄 文件长度: {len(text):,} 字符”)

# — 2. 构建提取参数 —
model_id = config.get(“model”, “gpt-4o-mini”)

extract_params = {
“text_or_documents”: text,
“prompt_description”: config[“prompt”],
“examples”: config[“examples”],
“model_id”: model_id,
“extraction_passes”: config.get(“extraction_passes”, 1),
“max_workers”: config.get(“max_workers”, 10),
“max_char_buffer”: config.get(“max_char_buffer”, 2000)
}

# — 3. 针对不同模型应用特殊配置 (核心秘诀) —
if ‘gpt’ in model_id.lower():
print(f”🔧 检测到 OpenAI 模型 ({model_id}),应用特殊配置…”)
from langextract.inference import OpenAILanguageModel

api_key = os.environ.get(“OPENAI_API_KEY”)
if not api_key:
print(“\n❌ 致命错误: 未在 .env 文件中找到 ‘OPENAI_API_KEY’。”)
print(” 请在 .env 文件中添加一行: OPENAI_API_KEY=sk-…”)
sys.exit(1)

extract_params.update({
“language_model_type”: OpenAILanguageModel,
“api_key”: api_key,
“fence_output”: True,
“use_schema_constraints”: False
})
else:
# 默认使用 Gemini 或其他模型,langextract 会自动寻找 LANGEXTRACT_API_KEY
print(f”🔧 使用默认或 Gemini 模型 ({model_id}) 配置…”)
api_key = os.environ.get(“LANGEXTRACT_API_KEY”)
if not api_key:
print(f”\n❌ 致命错误: 未找到适用于 ‘{model_id}’ 的 API 密钥。”)
print(” 请在 .env 文件中添加: LANGEXTRACT_API_KEY=…”)
sys.exit(1)

# — 4. 执行提取 —
print(“🚀 开始提取,请耐心等待…”)
result = lx.extract(**extract_params)

if not result.extractions:
print(“\n⚠️ 警告:本次运行未能提取到任何实体。”)
print(” 请检查: 1. Prompt和示例是否清晰。 2. API密钥和账户额度。 3. 源文件内容是否匹配任务。”)
return

# — 5. 保存和可视化 (使用最新、正确的方式) —
output_dir = Path(“extraction_results”)
output_dir.mkdir(exist_ok=True)
timestamp = datetime.now().strftime(“%Y%m%d_%H%M%S”)
output_base_name = f”{config_name}_{Path(input_file).stem}_{timestamp}”

jsonl_path = output_dir / f”{output_base_name}.jsonl”
lx.io.save_annotated_documents([result], output_name=str(jsonl_path.name), output_dir=str(output_dir))

html_path = output_dir / f”{output_base_name}.html”
html_content = lx.visualize(str(jsonl_path))
with open(html_path, “w”, encoding=”utf-8″) as f:
f.write(html_content)

print(“\n✅ 提取完成!”)
print(f” • 数据文件: {jsonl_path}”)
print(f” • 可视化报告: {html_path}”)

# — 6. 结果统计 —
class_counts = Counter(e.extraction_class for e in result.extractions)
print(“\n📊 提取统计:”)
print(f” 总实体数: {len(result.extractions)}”)
for class_name, count in sorted(class_counts.items()):
print(f” – {class_name}: {count} 个”)

def main():
parser = argparse.ArgumentParser(description=”通用信息提取工具 (最终增强版)”)
parser.add_argument(“config_name”, help=”配置名称 (如 medical, fable 等)”)
parser.add_argument(“input_file”, help=”输入文件路径”)
args = parser.parse_args()
process_document(args.config_name, args.input_file)

if __name__ == “__main__”:
main()


2.config.py :
“””
信息提取配置文件
在这里定义不同类型文档的提取规则
“””

import langextract as lx

# 提取配置字典
EXTRACTION_CONFIGS = {

# ========== 医疗记录配置 ==========
“medical”: {
“description”: “提取医疗记录中的药物、诊断和治疗信息”,
“model”: “gpt-4o-mini”, # 可选: gpt-4o, gpt-4, gpt-3.5-turbo
“extraction_passes”: 2, # 多轮提取提高准确率
“max_workers”: 10,
“max_char_buffer”: 1500,
“prompt”: “””
提取以下医疗信息:
1. 药物名称、剂量、用药频率、用药途径
2. 诊断结果
3. 症状描述
4. 治疗方案
使用原文精确提取,不要改写或总结。
为每个实体提供相关属性。
“””,
“examples”: [
lx.data.ExampleData(
text=”患者主诉头痛3天,诊断为偏头痛。处方:布洛芬400mg,口服,每日3次,饭后服用。”,
extractions=[
lx.data.Extraction(
extraction_class=”症状”,
extraction_text=”头痛3天”,
attributes={“持续时间”: “3天”}
),
lx.data.Extraction(
extraction_class=”诊断”,
extraction_text=”偏头痛”,
attributes={“类型”: “神经系统疾病”}
),
lx.data.Extraction(
extraction_class=”药物”,
extraction_text=”布洛芬”,
attributes={
“剂量”: “400mg”,
“途径”: “口服”,
“频率”: “每日3次”,
“注意事项”: “饭后服用”
}
),
]
)
]
},

# ========== 合同文件配置 ==========
“contract”: {
“description”: “提取合同中的关键条款和信息”,
“model”: “gpt-4o-mini”, # 合同一般比较规范,可以用便宜的模型
“extraction_passes”: 1,
“max_workers”: 5,
“max_char_buffer”: 2000,
“prompt”: “””
提取合同中的以下信息:
1. 甲方和乙方信息(公司名称、代表人)
2. 合同金额和支付条款
3. 合同期限和重要日期
4. 主要权利和义务
5. 违约条款
保持原文的准确性,提取完整条款。
“””,
“examples”: [
lx.data.ExampleData(
text=”甲方:北京科技有限公司(法定代表人:张明),乙方:上海贸易有限公司,合同总金额:人民币100万元整,合同期限:2024年1月1日至2024年12月31日。”,
extractions=[
lx.data.Extraction(
extraction_class=”甲方”,
extraction_text=”北京科技有限公司”,
attributes={“法定代表人”: “张明”}
),
lx.data.Extraction(
extraction_class=”乙方”,
extraction_text=”上海贸易有限公司”,
attributes={}
),
lx.data.Extraction(
extraction_class=”金额”,
extraction_text=”人民币100万元整”,
attributes={“币种”: “人民币”, “数额”: “100万元”}
),
lx.data.Extraction(
extraction_class=”期限”,
extraction_text=”2024年1月1日至2024年12月31日”,
attributes={“开始日期”: “2024年1月1日”, “结束日期”: “2024年12月31日”}
),
]
)
]
},

# ========== 新闻文章配置 ==========
“news”: {
“description”: “提取新闻文章的关键要素”,
“model”: “gpt-4o-mini”,
“extraction_passes”: 1,
“max_workers”: 15,
“max_char_buffer”: 2500,
“prompt”: “””
提取新闻文章中的:
1. 人物(姓名、职位、所属机构)
2. 地点
3. 时间
4. 事件(发生了什么)
5. 引用的言论
标注每个事件的重要性(高/中/低)。
“””,
“examples”: [
lx.data.ExampleData(
text=”昨天下午,苹果公司CEO库克在加州总部宣布,公司将投资50亿美元开发AI技术。他表示:’这是苹果历史上最重要的战略转型。'”,
extractions=[
lx.data.Extraction(
extraction_class=”时间”,
extraction_text=”昨天下午”,
attributes={“精确度”: “相对时间”}
),
lx.data.Extraction(
extraction_class=”人物”,
extraction_text=”库克”,
attributes={“职位”: “CEO”, “公司”: “苹果公司”}
),
lx.data.Extraction(
extraction_class=”地点”,
extraction_text=”加州总部”,
attributes={“类型”: “公司总部”}
),
lx.data.Extraction(
extraction_class=”事件”,
extraction_text=”投资50亿美元开发AI技术”,
attributes={“重要性”: “高”, “金额”: “50亿美元”, “领域”: “AI技术”}
),
lx.data.Extraction(
extraction_class=”言论”,
extraction_text=”这是苹果历史上最重要的战略转型”,
attributes={“发言人”: “库克”, “态度”: “积极”}
),
]
)
]
},

# ========== 学术论文配置 ==========
“academic”: {
“description”: “提取学术论文的关键信息”,
“model”: “gpt-4o-mini”,
“extraction_passes”: 2,
“max_workers”: 10,
“max_char_buffer”: 3000,
“prompt”: “””
提取学术论文中的:
1. 研究问题和假设
2. 研究方法
3. 主要发现和结论
4. 引用的重要文献
5. 数据和统计结果
保持学术术语的准确性。
“””,
“examples”: [
lx.data.ExampleData(
text=”本研究采用随机对照试验(RCT)方法,样本量n=500,结果显示治疗组相比对照组症状改善率提高了35% (p<0.001)。",
extractions=[
lx.data.Extraction(
extraction_class=”方法”,
extraction_text=”随机对照试验(RCT)”,
attributes={“类型”: “实验研究”}
),
lx.data.Extraction(
extraction_class=”样本”,
extraction_text=”n=500″,
attributes={“样本量”: “500”}
),
lx.data.Extraction(
extraction_class=”结果”,
extraction_text=”症状改善率提高了35%”,
attributes={“改善幅度”: “35%”, “统计显著性”: “p<0.001"}
),
]
)
]
},

# ========== 客户反馈配置 ==========
“feedback”: {
“description”: “提取客户反馈中的情感和问题”,
“model”: “gpt-3.5-turbo”,
“extraction_passes”: 1,
“max_workers”: 20,
“max_char_buffer”: 1000,
“prompt”: “””
提取客户反馈中的:
1. 情感倾向(正面/负面/中性)
2. 产品或服务名称
3. 具体问题或建议
4. 客户需求
为每个提取内容标注情感强度(1-5分)。
“””,
“examples”: [
lx.data.ExampleData(
text=”你们的客服态度太差了!我打了3次电话都没解决问题,产品质量倒是不错,就是售后服务需要改进。”,
extractions=[
lx.data.Extraction(
extraction_class=”负面情感”,
extraction_text=”客服态度太差了”,
attributes={“对象”: “客服”, “强度”: “5”}
),
lx.data.Extraction(
extraction_class=”问题”,
extraction_text=”打了3次电话都没解决问题”,
attributes={“频次”: “3次”, “状态”: “未解决”}
),
lx.data.Extraction(
extraction_class=”正面情感”,
extraction_text=”产品质量倒是不错”,
attributes={“对象”: “产品质量”, “强度”: “3”}
),
lx.data.Extraction(
extraction_class=”建议”,
extraction_text=”售后服务需要改进”,
attributes={“改进点”: “售后服务”}
),
]
)
]
},

# ========== 文学作品配置 ==========
“literary”: {
“description”: “提取文学作品(如小说、诗歌、戏剧)中的核心元素”,
“model”: “gpt-4o-mini”, # 文学分析需要更强的理解能力
“extraction_passes”: 2, # 多轮提取以捕捉深层含义
“max_workers”: 10,
“max_char_buffer”: 3000,
“prompt”: “””
提取文学作品中的以下要素:
1. 主要人物 (姓名、角色、性格特点)
2. 场景和氛围 (地点、时间、环境描述、情感基调)
3. 关键情节 (发生了什么,转折点)
4. 主题思想 (作品探讨的核心议题,如爱、死亡、成长、社会批判等)
5. 象征或意象 (具有特殊含义的物品或概念,如“红灯笼”象征压抑)
6. 修辞手法 (如比喻、拟人、排比等)
请精确引用原文,并为每个提取项提供相关属性。
“””,
“examples”: [
lx.data.ExampleData(
text=”我冒着严寒,回到相隔二千余里,别了二十余年的故乡去。时候既然是深冬,渐近故乡时,天气又阴晦了,冷风吹进船舱中,呜呜的响,从篷隙向外一望,苍黄的天底下,远近横着几个萧索的荒村,没有一些活气。”,
extractions=[
lx.data.Extraction(
extraction_class=”关键情节”,
extraction_text=”回到…故乡去”,
attributes={“事件类型”: “返乡”, “人物”: “我”}
),
lx.data.Extraction(
extraction_class=”场景”,
extraction_text=”相隔二千余里,别了二十余年的故乡”,
attributes={“地点”: “故乡”, “时间跨度”: “二十余年”, “距离”: “二千余里”}
),
lx.data.Extraction(
extraction_class=”氛围”,
extraction_text=”萧索的荒村,没有一些活气”,
attributes={“情感基调”: “荒凉、衰败”, “天气”: “严寒, 阴晦”}
),
lx.data.Extraction(
extraction_class=”意象”,
extraction_text=”苍黄的天”,
attributes={“色彩”: “苍黄”, “暗示”: “压抑、沉闷”}
),
lx.data.Extraction(
extraction_class=”修辞手法”,
extraction_text=”冷风吹进船舱中,呜呜的响”,
attributes={“类型”: “拟声/拟人”, “对象”: “冷风”}
),
]
)
]
},
}

# ========== 添加你自己的配置 ==========
# 复制上面的模板,修改为你需要的提取规则
# “your_config”: {
# “description”: “你的配置描述”,
# “model”: “gpt-4o-mini”,
# “prompt”: “你的提取指令…”,
# “examples”: […]
# }

详细教程:用Unsloth快速微调OpenAI首个开源大模型gpt-oss!低配显卡也能拥有专属GPT

分享我的Colab文件:

https://colab.research.google.com/drive/11jEpOECqYKEWh_75Bc3hSw2CmWqE4oF3?usp=sharing

点开链接会进入Colab界面,在这所做的修改不会保存,需要将它复制保存到Drive中。

上传文件

在这个单元格data_files=填入你的数据集名称;如果是别的数据集格式需要修改代码

修改微调细节:

最后一个单元格是测试微调效果,在原项目上是没有的,如果不需要可以直接删除:

如果使用T4 GPU会有概率超出可使用显存,导致失败;推荐选择L4 GPU性价比最高;A100 GPU速度更快,收费更高,具体看你需求。

点击Restart session and run all即可一键运行:

Mineru的api调用

import requests
import time
import os

class PDFProcessor:
    def __init__(self, token):
        self.token = token
        self.headers = {
            'Authorization': f'Bearer {token}'
        }
    
    def upload_file(self, file_path):
        """上传本地文件到临时存储"""
        print(f"📤 正在上传文件: {os.path.basename(file_path)}")
        
        # 使用 tmpfiles.org
        try:
            with open(file_path, 'rb') as f:
                response = requests.post(
                    'https://tmpfiles.org/api/v1/upload',
                    files={'file': f}
                )
                if response.status_code == 200:
                    result = response.json()
                    # 获取直接下载链接
                    url = result['data']['url']
                    direct_url = url.replace('tmpfiles.org/', 'tmpfiles.org/dl/')
                    print(f"✅ 上传成功: {direct_url}")
                    return direct_url
        except Exception as e:
            print(f"❌ 上传失败: {e}")
        
        return None
    
    def process_pdf(self, file_path):
        """处理本地PDF文件"""
        # 1. 上传文件
        pdf_url = self.upload_file(file_path)
        if not pdf_url:
            return None
        
        # 2. 创建MinerU任务
        print("📄 创建解析任务...")
        task_url = 'https://mineru.net/api/v4/extract/task'
        headers = {
            'Content-Type': 'application/json',
            'Authorization': f'Bearer {self.token}'
        }
        data = {
            'url': pdf_url,
            'is_ocr': True,
            'enable_formula': True,
            'enable_table': True,
            'language': 'auto'  # 中文文档
        }
        
        response = requests.post(task_url, headers=headers, json=data)
        result = response.json()
        
        if result['code'] != 0:
            print(f"❌ 创建任务失败: {result['msg']}")
            return None
        
        task_id = result['data']['task_id']
        print(f"✅ 任务ID: {task_id}")
        
        # 3. 等待处理完成
        print("⏳ 等待处理...")
        while True:
            time.sleep(5)
            status_url = f'https://mineru.net/api/v4/extract/task/{task_id}'
            status_response = requests.get(status_url, headers=headers)
            status_data = status_response.json()
            
            state = status_data['data']['state']
            
            if state == 'done':
                zip_url = status_data['data']['full_zip_url']
                print(f"✅ 处理完成!")
                print(f"📦 下载地址: {zip_url}")
                
                # 下载结果
                self.download_result(zip_url, task_id)
                return status_data
                
            elif state == 'failed':
                print(f"❌ 处理失败: {status_data['data']['err_msg']}")
                return None
                
            elif state == 'running':
                progress = status_data['data'].get('extract_progress', {})
                extracted = progress.get('extracted_pages', 0)
                total = progress.get('total_pages', 0)
                print(f"⏳ 正在处理... {extracted}/{total} 页")
            
            else:
                print(f"📊 状态: {state}")
    
    def download_result(self, zip_url, task_id):
        """下载结果文件"""
        save_path = f"mineru_result_{task_id}.zip"
        
        try:
            response = requests.get(zip_url, stream=True)
            with open(save_path, 'wb') as f:
                for chunk in response.iter_content(chunk_size=8192):
                    f.write(chunk)
            print(f"✅ 结果已保存到: {save_path}")
        except Exception as e:
            print(f"❌ 下载失败: {e}")

# 使用您的Token和文件
TOKEN = "eyJ0eXBlIjoiSldUIiwiYWxnIjoiSFM1MTIifQ.eyJqdGkiOiIyOTkwMzQ1NiIsInJvbCI6IlJPTEVfUkVHSVNURVIiLCJpc3MiOiJPcGVuWExhYiIsImlhdCI6MTc1MTM3NDYyOCwiY2xpZW50SWQiOiJsa3pkeDU3bnZ5MjJqa3BxOXgydyIsInBob25lIjoiMTg5NTIxNTUyNTAiLCJvcGVuSWQiOm51bGwsInV1aWQiOiI1YTA0YmUxMC1kMTJkLTQ3NzktYjYyYi1mM2U4NTRmZWI0YTQiLCJlbWFpbCI6IiIsImV4cCI6MTc1MjU4NDIyOH0.kKzBBW2Jp2sVh3HXRVRlz-Df8WMHcDB7PM1pZbrmn3_QEt39bw3OrNAf8OkrmgY9Kign1fpTxPRzxopOenqO7Q"

# 处理您的PDF文件
processor = PDFProcessor(TOKEN)
local_pdf = "/home/wang/1_time/00bjfei/宁德时代宁德时代新能源科技股份有限公司2024年半年度报告174页(1).pdf"

# 检查文件是否存在
if os.path.exists(local_pdf):
    processor.process_pdf(local_pdf)
else:
    print(f"❌ 文件不存在: {local_pdf}")

FastAPI-MCP

微信:adoresever

我的开源项目:

https://github.com/adoresever/DataGraphX_Learn

https://github.com/adoresever/Pretuning

  • fastapi-mcp安装部署
    • sudo snap install astral-uv (如果已经安装了uv,执行第二步)
      • 如果失败,出现Command ‘uv’ not found之类
        • sudo snap install astral-uv –classic
        • 用上面的命令可以无视风险继续安装uv
    • uv pip install fastapi-mcp “uvicorn[standard]”
    • 使用uv安装mcp-proxy
      • uv tool install mcp-proxy
      • 如果出现warning: /home/a/.local/bin is not on your PATH.
        • uv tool update-shell
        • 关闭并重新打开终端
        • 执行 which mcp-proxy
        • 如果 PATH 设置正确,它应该会输出 /home/a/.local/bin/mcp-proxy)
    • 创建 .py文件 和.env文件
    • python 文件名.py
      • 点击网址,在后面加上/.doc,回车进入

代码

import os
import httpx
from fastapi import FastAPI, HTTPException, Query
from fastapi_mcp import FastApiMCP
from pydantic import BaseModel, Field
from dotenv import load_dotenv
import logging
import json

# --- 配置与设置 ---

load_dotenv()
API_KEY = os.getenv("TAVILY_API_KEY")
if not API_KEY:
    raise ValueError("在环境变量或 .env 文件中未找到 TAVILY_API_KEY")

logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)

TAVILY_API_URL = "https://api.tavily.com/search"

# --- Pydantic 模型 (目前保持不变) ---

class NewsResponse(BaseModel):
    """描述 Tavily 搜索工具返回的新闻摘要。"""
    query: str = Field(..., description="用于搜索新闻的原始查询。")
    news_summary: str = Field(..., description="由 Tavily AI 基于查询找到的近期新闻的更详细摘要,合并了多个来源。")

# --- FastAPI 应用 ---

app = FastAPI(
    title="通过 MCP 使用 Tavily 搜索详细新闻", # 更新标题
    description="使用 Tavily AI 搜索查找并合并近期新闻细节,基于查询,并通过 MCP 暴露。",
    version="1.0.0",
)

# --- 新闻获取逻辑 (修改以获取更多细节) ---

async def fetch_detailed_news_from_tavily(news_query: str) -> str:
    """使用 Tavily AI 搜索新闻并合并结果以获取更多细节。"""
    payload = json.dumps({
        "api_key": API_KEY,
        "query": news_query,
        "search_depth": "advanced", # 使用高级搜索以获取可能更多的细节
        "include_answer": False,   # 如果你只想依赖结果内容,设为 False
        "max_results": 7          # 增加考虑的结果数量
        # "include_raw_content": True # 可选:可能获取更多原始内容,但需要仔细解析
    })
    headers = {'Content-Type': 'application/json'}

    async with httpx.AsyncClient(timeout=30.0) as client: # 为高级搜索增加超时时间
        response_data = None
        try:
            logger.info(f"正在向 Tavily AI 请求关于查询 '{news_query}' 的详细新闻摘要...")
            response = await client.post(TAVILY_API_URL, headers=headers, content=payload)
            response.raise_for_status()
            response_data = response.json()
            logger.debug(f"Tavily 对于查询 '{news_query}' 的原始响应: {response_data}")

            # --- 重点在于合并结果 ---
            combined_summary = ""
            if response_data.get("results"):
                summaries = []
                for i, res in enumerate(response_data["results"]):
                    title = res.get('title', f"来源 {i+1}")
                    content = res.get('content', '').strip() # 获取内容并去除首尾空格
                    # url = res.get('url', '#') # 如果需要,可以包含 URL
                    if content: # 仅当有内容时才包含
                        #清晰地格式化每个结果
                        summaries.append(f"--- 结果 {i+1}: {title} ---\n{content}")

                if summaries:
                    # 使用两个换行符连接所有摘要
                    combined_summary = "\n\n".join(summaries)
                    # 如果需要,可以限制总长度
                    # max_len = 2000 # 示例长度限制
                    # if len(combined_summary) > max_len:
                    #    combined_summary = combined_summary[:max_len] + "..."
                    logger.info(f"已合并来自 Tavily 对于查询 '{news_query}' 的 {len(summaries)} 条结果。")
                    return combined_summary
                else:
                    logger.warning(f"Tavily 对于查询 '{news_query}' 的结果没有可用的内容进行合并。")

            # 如果根本没有找到可用的结果
            logger.warning(f"Tavily 对于查询 '{news_query}' 没有返回可用的结果。")
            raise HTTPException(status_code=404, detail=f"无法使用 Tavily AI 找到与查询 '{news_query}' 匹配的近期新闻细节。")

        # --- 异常处理 (与天气示例大部分相同) ---
        except httpx.HTTPStatusError as exc:
            error_detail = "与 Tavily AI 服务通信时出错。"
            try: error_body = exc.response.json(); error_detail = error_body.get("error", error_detail)
            except ValueError: error_detail = exc.response.text or error_detail
            logger.error(f"从 Tavily 获取查询 '{news_query}' 的新闻时发生 HTTP 错误: {exc.response.status_code} - 详情: {error_detail}")
            if exc.response.status_code in [401, 403]: raise HTTPException(status_code=exc.response.status_code, detail=f"Tavily API 密钥错误: {error_detail}") from exc
            raise HTTPException(status_code=exc.response.status_code, detail=error_detail) from exc
        except httpx.RequestError as exc:
            logger.error(f"从 Tavily 获取查询 '{news_query}' 的新闻时发生网络错误: {exc}")
            raise HTTPException(status_code=503, detail="无法连接到 Tavily AI 服务。") from exc
        except ValueError as exc:
             logger.error(f"解码来自 Tavily 对查询 '{news_query}' 的 JSON 响应时出错: {exc}")
             raise HTTPException(status_code=500, detail="从 Tavily AI 服务收到无效的数据格式。") from exc
        except Exception as exc:
             logger.exception(f"获取查询 '{news_query}' 的 Tavily 新闻时发生意外错误: {exc}")
             raise HTTPException(status_code=500, detail="获取新闻摘要时发生意外的内部错误。") from exc

# --- FastAPI 端点 (调用新的获取函数) ---

@app.get(
    "/news/search",
    response_model=NewsResponse,
    operation_id="search_detailed_recent_news_tavily", # 更新 operation_id
    summary="搜索详细近期新闻 (通过 Tavily AI)", # 更新摘要
    tags=["News Tools", "Tavily AI"]
)
async def search_news(
    q: str = Query(..., min_length=3, description="用于搜索近期新闻的主题或查询。")
):
    """
    使用 Tavily AI 的高级搜索查找并合并来自近期新闻的细节,基于用户查询。
    返回一个合并了多个来源的更长的文本摘要。
    """
    logger.info(f"收到关于查询的详细新闻搜索请求: {q}")
    # 调用修改后的获取函数
    news_summary_text = await fetch_detailed_news_from_tavily(q)

    response_data = NewsResponse(
        query=q,
        news_summary=news_summary_text
    )
    logger.info(f"已通过 Tavily 成功检索到查询 '{q}' 的详细新闻摘要。")
    return response_data

# --- FastAPI-MCP 集成 ---

logger.info("正在初始化 FastAPI-MCP...")
mcp = FastApiMCP(app)
mcp.mount()
logger.info("FastAPI-MCP 服务器已挂载到 /mcp")

# --- 运行服务器 ---

if __name__ == "__main__":
    import uvicorn
    logger.info("正在启动用于 Tavily 详细新闻的 Uvicorn 服务器...")
    uvicorn.run(
        "news_mcp:app", # 确保文件名匹配
        host="127.0.0.1",
        port=8000, # 如果天气服务也在运行,可以更改端口,例如 8001
        reload=True
    )

基于模型Gemini 2.5 Pro Experimental 03-25的基准性测试

测试的环境:Goodle AI Studio
测试的模型:选择Gemini 2.5 Pro Experimental 03-25
测试形式:通过向模型发送指令(prompt)

测试一:让此模型使用HTML CSS和JavaScript构建一个响应式Web应用程序,使用户能够跟踪他们的每月收入和支出。(评估模型的数学能力)

将此模型输出的三个文件放入Vs Code,注意三个文件要在同一个文件下。

完成后我们打开HTML文件可以看到

操作结果:操作通过。用户可以自由添加支出收入金额,添加相应描述,同时系统会统计总支出,总收入和余额。

测试二:创建一个生命游戏(Conway The Game Of Life)(评估模型的逻辑能力)

康威生命游戏是什么:

操作过程:向模型发出指令,但这次我们选择在python脚本中运行。

操作结果:测试通过,生成康威生命游戏

测试三:发送一个任何模型都难以解决的问题——利用SVG语法创建一个对称翅膀和简单造型的蝴蝶。(评估模型输出SVG代码的能力)

操作过程:向模型发出指令,并将SVG 代码输入在线工具中来查看。

操作结果:测试通过,利用svg语法生成蝴蝶。

测试四:一个农民有一块三角形的天地,它的边不同,有三种不同的长度。13米,14米,15米。他想用一条通过其中一个顶点的线将它分成两个面积相等的区域,求出分界线的长度。(测试数学几何)

测试结果:通过。

测试五:一列火车在早上8点从A市出发以每小时70公里的恒定速度驶向500公里外的B市,火车B于上午9点从B市出发以每小时80公里的恒定速度驶向A市,火车A 在出发两小时后每隔15分钟停靠一次,火车B不间断行驶。两列火车在什么时间相遇?火车在离A市多远的地方实际相遇?(测试模型的代数和速率)

测试结果:通过。

模型进行了这几个步骤:分析初始阶段 (8:00 AM – 9:00 AM)——分析第二阶段 (9:00 AM – 10:00 AM)——分析第三阶段 (10:00 AM 之后)——计算相遇时间——计算相遇地点 (距离A市)

测试六:识别修复pythonPython 函数中的逻辑错误和潜在的运行时错误。该函数旨在返回所有正数的乘积。如果列表不包含正数,则应返回 1。该函数还应通过忽略非数字类型的列表来妥善处理它们。(三处错误)

测试结果:通过

测试七:图书馆需要购买总计正好 250 美元的教学材料。他们可以以每本 12 美元的价格购买练习册,以每本 35 美元的价格购买教育应用程序许可证,以每本 55 美元的价格购买科学套件。他们必须购买每种类型的物品中的至少一个。找出满足这些条件的所有可能组合(练习册、应用程序、套件的数量)。(测试离散数学中的数论,线性方程)

测试结果:通过

测试八:一个城镇有两种人:说真话的人(总是说真话)和撒谎的人(总是撒谎)。你遇到了三个人:A、B 和 C。A 说:“B 是个撒谎者。”B 说:“C 是个说真话的人。”C 说:“A 和 B 属于不同类型。”确定谁是说真话的人,谁是撒谎者,并逐步解释你的推理(测试模型逻辑)

测试结果:

关于测试八Gemini 2.5和DeepseekV3的对比

操作过程:使用OpenRouter同时选择这两个模型并提问测试八的问题

操作结果:内容一致,Gemini2.5速度更快。

下一步操作,在更多测试内容上通过结果和速度将Gemini2.5与其它模型做对比。

Archon: AI代理构建AI!

Archon是一个创新的AI元代理系统,其核心理念是通过抓取各种框架的文档,来构建能够使用这些框架的AI代理。作为世界上第一个”Agenteer”(代理工程师),它能够自主构建、改进和优化其他AI代理。

Archon的核心是通过抓取各种框架的文档,用来构建能够使用这些框架的AI代理。

https://github.com/coleam00/Archon

优势

  • 多种部署选项:Docker容器或本地Python安装
  • 向量数据库支持:使用Supabase存储文档向量
  • 多种LLM支持:OpenAI/Anthropic/OpenRouter API或本地LLM(Ollama)

核心解读:Supabase

Supabase是一个开源的后端即服务(BaaS)平台,旨在简化应用程序开发过程。在Archon中,它主要用于存储和检索向量化的框架文档,为代理提供知识基础。

本地部署

Docker方式

git clone https://github.com/coleam00/archon.git
cd archon
python run_docker.py

部署完成后访问 http://localhost:8501

Python方式

git clone https://github.com/coleam00/archon.git
cd archon
python -m venv venv
source venv/bin/activate # Windows: venv\Scripts\activate
pip install -r requirements.txt
streamlit run streamlit_ui.py

核心解读:IDE

AI IDE是集成了人工智能功能的开发环境,比如Windsurf、Cursor和Cline,可以提供代码补全、生成代码建议等智能功能。

部署环境

完成安装后,需要在Streamlit UI配置以下环境:

  1. 环境配置:设置API密钥和模型选择
  2. 数据库设置:配置Supabase向量数据库
  3. 文档抓取:爬取Pydantic AI文档,建立知识库
  4. 代理服务:启动生成代理的服务

核心解读:MCP

MCP是”Model Context Protocol”(模型上下文协议),这是一种允许AI IDE与外部AI服务通信的标准化协议。通过MCP配置,可以:

  • 在你喜欢的AI编辑器中工作
  • 直接从编辑器调用Archon功能
  • 让Archon为你生成代理代码,并直接集成到项目中

使用方法

完成所有配置后,可以:

  1. 转到聊天选项卡
  2. 描述你想要构建的代理
  3. Archon会规划并生成必要的代码

如果配置了MCP,还可以直接在AI IDE中使用Archon的功能,让Archon为你生成代理代码,并将其集成到你的项目中。

总结

Archon通过创新的文档抓取和向量化方法,展示了元学习在AI系统构建中的潜力。它不仅是一个实用的开发工具,也是一个展示智能代理系统演化的教育框架。随着其不断迭代完善,Archon有望成为AI代理开发生态系统的重要组成部分。

Coagents

微信:adoresever

qa的差异部分

# 修正 pyproject.toml 文件(如果需要) # 删除 [project] 部分,确保正确的配置

[tool.poetry]
name = "my_agent"
version = "0.1.0"
description = "Starter"
authors = ["Ariel Weinberger <weinberger.ariel@gmail.com>"]
license = "MIT"
packages = [
    { include = "my_agent" }
]

[tool.poetry.dependencies]
python = "^3.12"
langchain-openai = "^0.2.1"
langchain-anthropic = "^0.2.1"
langchain = "^0.3.1"
openai = "^1.51.0"
langchain-community = "^0.3.1"
copilotkit = "0.1.33"
uvicorn = "^0.31.0"
python-dotenv = "^1.0.1"
langchain-core = "^0.3.25"
langgraph-cli = {extras = ["inmem"], version = "^0.1.64"}

[tool.poetry.scripts]
demo = "my_agent.demo:main"

[build-system]
requires = ["poetry-core>=1.0.0"]
build-backend = "poetry.core.masonry.api"

然后运行:

poetry lock

poetry install

其他一样!

coagents-research-canvas安装过程

源码克隆

git clone https://github.com/CopilotKit/CopilotKit.git

cd 该目录

虚拟环境

conda create -n coagents-re python=3.12

conda activate coagents-re

cd agent

poetry install

.env添加OPENAI_API_KEY= TAVILY_API_KEY=

api获取:https://tavily.com/ https://platform.openai.com/api-keys

poetry run demo运行

cd ui

pnpm add @copilotkit/react-ui@1.4.8-coagents-v0-3.1 @copilotkit/react-core@1.4.8-coagents-v0-3.1

pnpm i

.env

pnpm run dev运行

若端口报错视频里有解决方法!