This commit is contained in:
@@ -1,7 +1,16 @@
|
|||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
from django.contrib.admin import ModelAdmin
|
|
||||||
from unfold.admin import ModelAdmin as UnfoldModelAdmin
|
from unfold.admin import ModelAdmin as UnfoldModelAdmin
|
||||||
from .models import TranscriptionTask
|
from unfold.admin import StackedInline as UnfoldStackedInline
|
||||||
|
from .models import TranscriptionTask, AIEvaluation
|
||||||
|
|
||||||
|
class AIEvaluationInline(UnfoldStackedInline):
|
||||||
|
model = AIEvaluation
|
||||||
|
extra = 0
|
||||||
|
can_delete = False
|
||||||
|
verbose_name = "AI评估"
|
||||||
|
verbose_name_plural = "AI评估"
|
||||||
|
readonly_fields = ['created_at', 'updated_at', 'raw_response', 'reasoning']
|
||||||
|
fields = ('score', 'evaluation', 'model_selection', 'prompt', 'reasoning', 'status', 'error_message')
|
||||||
|
|
||||||
@admin.register(TranscriptionTask)
|
@admin.register(TranscriptionTask)
|
||||||
class TranscriptionTaskAdmin(UnfoldModelAdmin):
|
class TranscriptionTaskAdmin(UnfoldModelAdmin):
|
||||||
@@ -9,3 +18,24 @@ class TranscriptionTaskAdmin(UnfoldModelAdmin):
|
|||||||
list_filter = ['status', 'created_at']
|
list_filter = ['status', 'created_at']
|
||||||
search_fields = ['id', 'task_id', 'transcription', 'summary']
|
search_fields = ['id', 'task_id', 'transcription', 'summary']
|
||||||
readonly_fields = ['id', 'created_at', 'updated_at', 'task_id']
|
readonly_fields = ['id', 'created_at', 'updated_at', 'task_id']
|
||||||
|
inlines = [AIEvaluationInline]
|
||||||
|
|
||||||
|
@admin.register(AIEvaluation)
|
||||||
|
class AIEvaluationAdmin(UnfoldModelAdmin):
|
||||||
|
list_display = ['id', 'task', 'score', 'status', 'model_selection', 'created_at']
|
||||||
|
list_filter = ['status', 'model_selection', 'created_at']
|
||||||
|
search_fields = ['task__id', 'evaluation', 'reasoning']
|
||||||
|
readonly_fields = ['id', 'created_at', 'updated_at', 'raw_response']
|
||||||
|
fieldsets = (
|
||||||
|
(None, {
|
||||||
|
'fields': ('task', 'status', 'score', 'evaluation')
|
||||||
|
}),
|
||||||
|
('配置', {
|
||||||
|
'fields': ('model_selection', 'prompt'),
|
||||||
|
'classes': ('collapse',),
|
||||||
|
}),
|
||||||
|
('调试信息', {
|
||||||
|
'fields': ('raw_response', 'reasoning', 'error_message'),
|
||||||
|
'classes': ('collapse',),
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
|||||||
98
backend/ai_services/bailian_service.py
Normal file
98
backend/ai_services/bailian_service.py
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
import logging
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
from django.conf import settings
|
||||||
|
from openai import OpenAI
|
||||||
|
from .models import AIEvaluation
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
class BailianService:
|
||||||
|
def __init__(self):
|
||||||
|
self.api_key = getattr(settings, 'DASHSCOPE_API_KEY', None)
|
||||||
|
if not self.api_key:
|
||||||
|
self.api_key = os.environ.get("DASHSCOPE_API_KEY")
|
||||||
|
|
||||||
|
if self.api_key:
|
||||||
|
self.client = OpenAI(
|
||||||
|
api_key=self.api_key,
|
||||||
|
base_url="https://dashscope.aliyuncs.com/compatible-mode/v1"
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
self.client = None
|
||||||
|
logger.warning("DASHSCOPE_API_KEY not configured.")
|
||||||
|
|
||||||
|
def evaluate_task(self, evaluation: AIEvaluation):
|
||||||
|
"""
|
||||||
|
执行AI评估
|
||||||
|
"""
|
||||||
|
if not self.client:
|
||||||
|
evaluation.status = AIEvaluation.Status.FAILED
|
||||||
|
evaluation.error_message = "服务未配置 (DASHSCOPE_API_KEY missing)"
|
||||||
|
evaluation.save()
|
||||||
|
return
|
||||||
|
|
||||||
|
task = evaluation.task
|
||||||
|
if not task.transcription:
|
||||||
|
evaluation.status = AIEvaluation.Status.FAILED
|
||||||
|
evaluation.error_message = "关联任务无逐字稿内容"
|
||||||
|
evaluation.save()
|
||||||
|
return
|
||||||
|
|
||||||
|
evaluation.status = AIEvaluation.Status.PROCESSING
|
||||||
|
evaluation.save()
|
||||||
|
|
||||||
|
try:
|
||||||
|
prompt = evaluation.prompt
|
||||||
|
content = task.transcription
|
||||||
|
|
||||||
|
# 截断过长的内容以防止超出Token限制 (简单处理,取前10000字)
|
||||||
|
if len(content) > 10000:
|
||||||
|
content = content[:10000] + "...(内容过长已截断)"
|
||||||
|
|
||||||
|
# Construct messages
|
||||||
|
messages = [
|
||||||
|
{'role': 'system', 'content': 'You are a helpful assistant designed to output JSON.'},
|
||||||
|
{'role': 'user', 'content': f"{prompt}\n\n以下是需要评估的内容:\n{content}"}
|
||||||
|
]
|
||||||
|
|
||||||
|
completion = self.client.chat.completions.create(
|
||||||
|
model=evaluation.model_selection,
|
||||||
|
messages=messages,
|
||||||
|
response_format={"type": "json_object"}
|
||||||
|
)
|
||||||
|
|
||||||
|
response_content = completion.choices[0].message.content
|
||||||
|
# Convert to dict for storage
|
||||||
|
raw_response = completion.model_dump()
|
||||||
|
|
||||||
|
evaluation.raw_response = raw_response
|
||||||
|
|
||||||
|
# Parse JSON
|
||||||
|
try:
|
||||||
|
result = json.loads(response_content)
|
||||||
|
evaluation.score = result.get('score')
|
||||||
|
evaluation.evaluation = result.get('evaluation') or result.get('comment')
|
||||||
|
|
||||||
|
# 尝试获取推理过程(如果模型返回了)
|
||||||
|
evaluation.reasoning = result.get('reasoning') or result.get('analysis')
|
||||||
|
|
||||||
|
if not evaluation.reasoning:
|
||||||
|
# 如果JSON里没有,把整个JSON作为推理参考
|
||||||
|
evaluation.reasoning = json.dumps(result, ensure_ascii=False, indent=2)
|
||||||
|
|
||||||
|
evaluation.status = AIEvaluation.Status.COMPLETED
|
||||||
|
except json.JSONDecodeError:
|
||||||
|
evaluation.status = AIEvaluation.Status.FAILED
|
||||||
|
evaluation.error_message = f"无法解析JSON响应: {response_content}"
|
||||||
|
evaluation.reasoning = response_content
|
||||||
|
|
||||||
|
evaluation.save()
|
||||||
|
return evaluation
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"AI Evaluation failed: {e}")
|
||||||
|
evaluation.status = AIEvaluation.Status.FAILED
|
||||||
|
evaluation.error_message = str(e)
|
||||||
|
evaluation.save()
|
||||||
|
return evaluation
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
# Generated by Django 6.0.1 on 2026-03-11 12:44
|
||||||
|
|
||||||
|
import django.db.models.deletion
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('ai_services', '0003_transcriptiontask_auto_chapters_data_and_more'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='transcriptiontask',
|
||||||
|
name='evaluation',
|
||||||
|
),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='transcriptiontask',
|
||||||
|
name='score',
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='AIEvaluation',
|
||||||
|
fields=[
|
||||||
|
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('score', models.IntegerField(blank=True, help_text='0-100分', null=True, verbose_name='AI评分')),
|
||||||
|
('evaluation', models.TextField(blank=True, null=True, verbose_name='AI评语')),
|
||||||
|
('model_selection', models.CharField(default='qwen-plus', help_text='例如: qwen-plus, qwen-turbo, qwen-max', max_length=50, verbose_name='模型选择')),
|
||||||
|
('prompt', models.TextField(default='你是一个专业的评分助手。请根据提供的转写内容,对内容质量、逻辑清晰度、语言表达等方面进行综合评分(0-100分),并给出详细的评语。请以JSON格式返回,包含"score"和"evaluation"字段。', help_text='用于指导AI评分的提示词', verbose_name='评分提示词')),
|
||||||
|
('raw_response', models.JSONField(blank=True, help_text='大模型返回的完整JSON', null=True, verbose_name='原始响应')),
|
||||||
|
('reasoning', models.TextField(blank=True, help_text='AI的推理过程(如果有)', null=True, verbose_name='推理过程')),
|
||||||
|
('status', models.CharField(choices=[('PENDING', '等待中'), ('PROCESSING', '生成中'), ('COMPLETED', '已完成'), ('FAILED', '失败')], default='PENDING', max_length=20, verbose_name='评估状态')),
|
||||||
|
('error_message', models.TextField(blank=True, null=True, verbose_name='错误信息')),
|
||||||
|
('created_at', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')),
|
||||||
|
('updated_at', models.DateTimeField(auto_now=True, verbose_name='更新时间')),
|
||||||
|
('task', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='ai_evaluation', to='ai_services.transcriptiontask', verbose_name='关联任务')),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'verbose_name': 'AI智能评估',
|
||||||
|
'verbose_name_plural': 'AI智能评估',
|
||||||
|
'ordering': ['-created_at'],
|
||||||
|
},
|
||||||
|
),
|
||||||
|
]
|
||||||
@@ -25,8 +25,11 @@ class TranscriptionTask(models.Model):
|
|||||||
|
|
||||||
transcription = models.TextField(verbose_name=_('逐字稿'), blank=True, null=True)
|
transcription = models.TextField(verbose_name=_('逐字稿'), blank=True, null=True)
|
||||||
summary = models.TextField(verbose_name=_('AI总结'), blank=True, null=True)
|
summary = models.TextField(verbose_name=_('AI总结'), blank=True, null=True)
|
||||||
score = models.IntegerField(verbose_name=_('AI评分'), blank=True, null=True, help_text=_('基于转写内容的评分'))
|
|
||||||
evaluation = models.TextField(verbose_name=_('AI评语'), blank=True, null=True)
|
# 已解耦到 AIEvaluation 模型
|
||||||
|
# score = models.IntegerField(verbose_name=_('AI评分'), blank=True, null=True, help_text=_('基于转写内容的评分'))
|
||||||
|
# evaluation = models.TextField(verbose_name=_('AI评语'), blank=True, null=True)
|
||||||
|
|
||||||
error_message = models.TextField(verbose_name=_('错误信息'), blank=True, null=True)
|
error_message = models.TextField(verbose_name=_('错误信息'), blank=True, null=True)
|
||||||
created_at = models.DateTimeField(verbose_name=_('创建时间'), auto_now_add=True)
|
created_at = models.DateTimeField(verbose_name=_('创建时间'), auto_now_add=True)
|
||||||
updated_at = models.DateTimeField(verbose_name=_('更新时间'), auto_now=True)
|
updated_at = models.DateTimeField(verbose_name=_('更新时间'), auto_now=True)
|
||||||
@@ -38,3 +41,58 @@ class TranscriptionTask(models.Model):
|
|||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return f"{self.id} - {self.get_status_display()}"
|
return f"{self.id} - {self.get_status_display()}"
|
||||||
|
|
||||||
|
|
||||||
|
class AIEvaluation(models.Model):
|
||||||
|
class Status(models.TextChoices):
|
||||||
|
PENDING = 'PENDING', _('等待中')
|
||||||
|
PROCESSING = 'PROCESSING', _('生成中')
|
||||||
|
COMPLETED = 'COMPLETED', _('已完成')
|
||||||
|
FAILED = 'FAILED', _('失败')
|
||||||
|
|
||||||
|
task = models.OneToOneField(
|
||||||
|
TranscriptionTask,
|
||||||
|
on_delete=models.CASCADE,
|
||||||
|
related_name='ai_evaluation',
|
||||||
|
verbose_name=_('关联任务')
|
||||||
|
)
|
||||||
|
|
||||||
|
# 评分与评语
|
||||||
|
score = models.IntegerField(verbose_name=_('AI评分'), blank=True, null=True, help_text=_('0-100分'))
|
||||||
|
evaluation = models.TextField(verbose_name=_('AI评语'), blank=True, null=True)
|
||||||
|
|
||||||
|
# 配置选项 (可在Admin中设置)
|
||||||
|
model_selection = models.CharField(
|
||||||
|
verbose_name=_('模型选择'),
|
||||||
|
max_length=50,
|
||||||
|
default='qwen-plus',
|
||||||
|
help_text=_('例如: qwen-plus, qwen-turbo, qwen-max')
|
||||||
|
)
|
||||||
|
prompt = models.TextField(
|
||||||
|
verbose_name=_('评分提示词'),
|
||||||
|
default='你是一个专业的评分助手。请根据提供的转写内容,对内容质量、逻辑清晰度、语言表达等方面进行综合评分(0-100分),并给出详细的评语。请以JSON格式返回,包含"score"和"evaluation"字段。',
|
||||||
|
help_text=_('用于指导AI评分的提示词')
|
||||||
|
)
|
||||||
|
|
||||||
|
# 原始数据与推理
|
||||||
|
raw_response = models.JSONField(verbose_name=_('原始响应'), blank=True, null=True, help_text=_('大模型返回的完整JSON'))
|
||||||
|
reasoning = models.TextField(verbose_name=_('推理过程'), blank=True, null=True, help_text=_('AI的推理过程(如果有)'))
|
||||||
|
|
||||||
|
status = models.CharField(
|
||||||
|
verbose_name=_('评估状态'),
|
||||||
|
max_length=20,
|
||||||
|
choices=Status.choices,
|
||||||
|
default=Status.PENDING
|
||||||
|
)
|
||||||
|
error_message = models.TextField(verbose_name=_('错误信息'), blank=True, null=True)
|
||||||
|
|
||||||
|
created_at = models.DateTimeField(verbose_name=_('创建时间'), auto_now_add=True)
|
||||||
|
updated_at = models.DateTimeField(verbose_name=_('更新时间'), auto_now=True)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
verbose_name = _('AI智能评估')
|
||||||
|
verbose_name_plural = _('AI智能评估')
|
||||||
|
ordering = ['-created_at']
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return f"Evaluation for Task {self.task.id}"
|
||||||
|
|||||||
@@ -1,11 +1,18 @@
|
|||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
from .models import TranscriptionTask
|
from .models import TranscriptionTask, AIEvaluation
|
||||||
|
|
||||||
|
class AIEvaluationSerializer(serializers.ModelSerializer):
|
||||||
|
class Meta:
|
||||||
|
model = AIEvaluation
|
||||||
|
fields = ['id', 'score', 'evaluation', 'model_selection', 'prompt', 'reasoning', 'status', 'error_message', 'created_at', 'updated_at']
|
||||||
|
|
||||||
class TranscriptionTaskSerializer(serializers.ModelSerializer):
|
class TranscriptionTaskSerializer(serializers.ModelSerializer):
|
||||||
|
ai_evaluation = AIEvaluationSerializer(read_only=True)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = TranscriptionTask
|
model = TranscriptionTask
|
||||||
fields = ['id', 'file_url', 'task_id', 'status', 'transcription', 'summary', 'error_message', 'created_at', 'updated_at', 'score', 'evaluation', 'transcription_data', 'summary_data', 'auto_chapters_data']
|
fields = ['id', 'file_url', 'task_id', 'status', 'transcription', 'summary', 'error_message', 'created_at', 'updated_at', 'transcription_data', 'summary_data', 'auto_chapters_data', 'ai_evaluation']
|
||||||
read_only_fields = ['id', 'file_url', 'task_id', 'status', 'transcription', 'summary', 'error_message', 'created_at', 'updated_at', 'score', 'evaluation', 'transcription_data', 'summary_data', 'auto_chapters_data']
|
read_only_fields = ['id', 'file_url', 'task_id', 'status', 'transcription', 'summary', 'error_message', 'created_at', 'updated_at', 'transcription_data', 'summary_data', 'auto_chapters_data', 'ai_evaluation']
|
||||||
|
|
||||||
class TranscriptionUploadSerializer(serializers.Serializer):
|
class TranscriptionUploadSerializer(serializers.Serializer):
|
||||||
file = serializers.FileField(help_text="上传的音频文件")
|
file = serializers.FileField(help_text="上传的音频文件")
|
||||||
|
|||||||
@@ -291,7 +291,30 @@ class AliyunTingwuService:
|
|||||||
# 保存原始数据
|
# 保存原始数据
|
||||||
task.auto_chapters_data = auto_chapters
|
task.auto_chapters_data = auto_chapters
|
||||||
|
|
||||||
# (可选) 将章节信息追加到 summary 或 evaluation 中,或者仅保存 raw data
|
# 将章节信息追加到 summary
|
||||||
# 根据用户需求,这里主要保存到 model 的 auto_chapters_data 字段 (已在 models.py 定义)
|
if auto_chapters and isinstance(auto_chapters, list):
|
||||||
|
if summary_text:
|
||||||
|
summary_text.append("\n\n### 章节速览")
|
||||||
|
else:
|
||||||
|
summary_text.append("### 章节速览")
|
||||||
|
|
||||||
|
for chapter in auto_chapters:
|
||||||
|
headline = chapter.get('Headline', '')
|
||||||
|
summary = chapter.get('Summary', '')
|
||||||
|
start_time = chapter.get('Start', 0)
|
||||||
|
|
||||||
|
# 格式化时间戳 (毫秒 -> HH:MM:SS)
|
||||||
|
seconds = int(start_time / 1000)
|
||||||
|
m, s = divmod(seconds, 60)
|
||||||
|
h, m = divmod(m, 60)
|
||||||
|
time_str = f"{h:02d}:{m:02d}:{s:02d}"
|
||||||
|
|
||||||
|
chapter_text = f"- [{time_str}] {headline}"
|
||||||
|
if summary:
|
||||||
|
chapter_text += f"\n {summary}"
|
||||||
|
summary_text.append(chapter_text)
|
||||||
|
|
||||||
|
if summary_text:
|
||||||
|
task.summary = "\n".join(summary_text)
|
||||||
|
|
||||||
task.save()
|
task.save()
|
||||||
|
|||||||
@@ -7,8 +7,8 @@ from rest_framework.parsers import MultiPartParser, FormParser, JSONParser
|
|||||||
from rest_framework.permissions import AllowAny
|
from rest_framework.permissions import AllowAny
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from drf_spectacular.utils import extend_schema, OpenApiParameter, OpenApiTypes
|
from drf_spectacular.utils import extend_schema, OpenApiParameter, OpenApiTypes
|
||||||
from .models import TranscriptionTask
|
from .models import TranscriptionTask, AIEvaluation
|
||||||
from .serializers import TranscriptionTaskSerializer, TranscriptionUploadSerializer
|
from .serializers import TranscriptionTaskSerializer, TranscriptionUploadSerializer, AIEvaluationSerializer
|
||||||
from .services import AliyunTingwuService
|
from .services import AliyunTingwuService
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
@@ -143,6 +143,51 @@ class TranscriptionTaskViewSet(viewsets.ModelViewSet):
|
|||||||
logger.error(f"处理上传请求失败: {e}")
|
logger.error(f"处理上传请求失败: {e}")
|
||||||
return Response({'error': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
|
return Response({'error': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
|
||||||
|
|
||||||
|
@action(detail=True, methods=['post'])
|
||||||
|
@extend_schema(
|
||||||
|
request={
|
||||||
|
'application/json': {
|
||||||
|
'type': 'object',
|
||||||
|
'properties': {
|
||||||
|
'model_selection': {'type': 'string', 'description': '模型选择'},
|
||||||
|
'prompt': {'type': 'string', 'description': '评分提示词'},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
responses={200: AIEvaluationSerializer}
|
||||||
|
)
|
||||||
|
def evaluate(self, request, pk=None):
|
||||||
|
"""
|
||||||
|
触发AI评估
|
||||||
|
"""
|
||||||
|
task = self.get_object()
|
||||||
|
|
||||||
|
# 1. 检查或创建 Evaluation 对象
|
||||||
|
evaluation, created = AIEvaluation.objects.get_or_create(task=task)
|
||||||
|
|
||||||
|
# 2. 如果请求中有配置,更新配置
|
||||||
|
model_selection = request.data.get('model_selection')
|
||||||
|
prompt = request.data.get('prompt')
|
||||||
|
|
||||||
|
updated = False
|
||||||
|
if model_selection:
|
||||||
|
evaluation.model_selection = model_selection
|
||||||
|
updated = True
|
||||||
|
if prompt:
|
||||||
|
evaluation.prompt = prompt
|
||||||
|
updated = True
|
||||||
|
|
||||||
|
if updated:
|
||||||
|
evaluation.save()
|
||||||
|
|
||||||
|
# 3. 调用 Service 执行评估
|
||||||
|
from .bailian_service import BailianService
|
||||||
|
service = BailianService()
|
||||||
|
service.evaluate_task(evaluation)
|
||||||
|
|
||||||
|
serializer = AIEvaluationSerializer(evaluation)
|
||||||
|
return Response(serializer.data)
|
||||||
|
|
||||||
@action(detail=True, methods=['get'])
|
@action(detail=True, methods=['get'])
|
||||||
@extend_schema(
|
@extend_schema(
|
||||||
parameters=[
|
parameters=[
|
||||||
|
|||||||
@@ -414,3 +414,5 @@ ALIYUN_OSS_BUCKET_NAME = os.environ.get('ALIYUN_OSS_BUCKET_NAME', '')
|
|||||||
ALIYUN_OSS_ENDPOINT = os.environ.get('ALIYUN_OSS_ENDPOINT', 'oss-cn-shanghai.aliyuncs.com')
|
ALIYUN_OSS_ENDPOINT = os.environ.get('ALIYUN_OSS_ENDPOINT', 'oss-cn-shanghai.aliyuncs.com')
|
||||||
ALIYUN_OSS_INTERNAL_ENDPOINT = os.environ.get('ALIYUN_OSS_INTERNAL_ENDPOINT', '')
|
ALIYUN_OSS_INTERNAL_ENDPOINT = os.environ.get('ALIYUN_OSS_INTERNAL_ENDPOINT', '')
|
||||||
ALIYUN_TINGWU_APP_KEY = os.environ.get('ALIYUN_TINGWU_APP_KEY', '') # 听悟AppKey
|
ALIYUN_TINGWU_APP_KEY = os.environ.get('ALIYUN_TINGWU_APP_KEY', '') # 听悟AppKey
|
||||||
|
|
||||||
|
DASHSCOPE_API_KEY = os.environ.get('DASHSCOPE_API_KEY', '')
|
||||||
|
|||||||
@@ -28,3 +28,4 @@ aliyun-python-sdk-core==2.16.0
|
|||||||
aliyun-python-sdk-tingwu==1.0.7
|
aliyun-python-sdk-tingwu==1.0.7
|
||||||
oss2==2.19.1
|
oss2==2.19.1
|
||||||
python-dotenv
|
python-dotenv
|
||||||
|
openai
|
||||||
|
|||||||
Reference in New Issue
Block a user