Spaces:
Sleeping
Sleeping
| from dataclasses import dataclass | |
| from openai import OpenAI | |
| from app.core.config import settings | |
| from app.core.models import SearchResult | |
| class ChatAnswer: | |
| answer: str | |
| reasoning: str | None | |
| context: list[SearchResult] | |
| class NvidiaChatClient: | |
| def __init__(self): | |
| if not settings.NVIDIA_API_KEY: | |
| raise ValueError("NVIDIA_API_KEY is required for NVIDIA chat completions.") | |
| self.client = OpenAI( | |
| base_url=settings.NVIDIA_API_URL, | |
| api_key=settings.NVIDIA_API_KEY, | |
| ) | |
| def answer_with_context(self, question: str, context: list[SearchResult]) -> ChatAnswer: | |
| context_text = "\n\n".join( | |
| [ | |
| ( | |
| f"[{index}] title={item.title}\n" | |
| f"source={item.source}\n" | |
| f"score={item.score:.4f}\n" | |
| f"text={item.text}" | |
| ) | |
| for index, item in enumerate(context, start=1) | |
| ] | |
| ) | |
| messages = [ | |
| { | |
| "role": "system", | |
| "content": ( | |
| "You are KnowledgeHub's retrieval assistant. Answer only from the " | |
| "provided context. If the context is insufficient, say what is missing. " | |
| "Cite sources using bracket numbers like [1], [2]." | |
| ), | |
| }, | |
| { | |
| "role": "user", | |
| "content": f"Question:\n{question}\n\nRetrieved context:\n{context_text}", | |
| }, | |
| ] | |
| completion = self.client.chat.completions.create( | |
| model=settings.NVIDIA_CHAT_MODEL, | |
| messages=messages, | |
| temperature=settings.CHAT_TEMPERATURE, | |
| top_p=settings.CHAT_TOP_P, | |
| max_tokens=settings.CHAT_MAX_TOKENS, | |
| frequency_penalty=0, | |
| presence_penalty=0, | |
| stream=False, | |
| extra_body={ | |
| "min_thinking_tokens": settings.MIN_THINKING_TOKENS, | |
| "max_thinking_tokens": settings.MAX_THINKING_TOKENS, | |
| }, | |
| ) | |
| message = completion.choices[0].message | |
| reasoning = getattr(message, "reasoning_content", None) | |
| return ChatAnswer(answer=message.content or "", reasoning=reasoning, context=context) | |