Skip to content

Commit 0ad2207

Browse files
authored
Merge pull request #98 from run-llama/feat/construct-resource-url-from-backend
feat: construct resource url from backend
2 parents b7e0072 + bfde30d commit 0ad2207

File tree

8 files changed

+68
-64
lines changed

8 files changed

+68
-64
lines changed

templates/components/engines/typescript/agent/tools/interpreter.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ export type InterpreterToolParams = {
1515
fileServerURLPrefix?: string;
1616
};
1717

18-
export type InterpreterToolOuput = {
18+
export type InterpreterToolOutput = {
1919
isError: boolean;
2020
logs: Logs;
2121
extraResult: InterpreterExtraResult[];
@@ -88,23 +88,23 @@ export class InterpreterTool implements BaseTool<InterpreterParameter> {
8888
return this.codeInterpreter;
8989
}
9090

91-
public async codeInterpret(code: string): Promise<InterpreterToolOuput> {
91+
public async codeInterpret(code: string): Promise<InterpreterToolOutput> {
9292
console.log(
9393
`\n${"=".repeat(50)}\n> Running following AI-generated code:\n${code}\n${"=".repeat(50)}`,
9494
);
9595
const interpreter = await this.initInterpreter();
9696
const exec = await interpreter.notebook.execCell(code);
9797
if (exec.error) console.error("[Code Interpreter error]", exec.error);
9898
const extraResult = await this.getExtraResult(exec.results[0]);
99-
const result: InterpreterToolOuput = {
99+
const result: InterpreterToolOutput = {
100100
isError: !!exec.error,
101101
logs: exec.logs,
102102
extraResult,
103103
};
104104
return result;
105105
}
106106

107-
async call(input: InterpreterParameter): Promise<InterpreterToolOuput> {
107+
async call(input: InterpreterParameter): Promise<InterpreterToolOutput> {
108108
const result = await this.codeInterpret(input.code);
109109
await this.codeInterpreter?.close();
110110
return result;

templates/types/streaming/express/src/controllers/stream-helper.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,22 @@ export function appendImageData(data: StreamData, imageUrl?: string) {
1717
});
1818
}
1919

20+
function getNodeUrl(metadata: Metadata) {
21+
const url = metadata["URL"];
22+
if (url) return url;
23+
const fileName = metadata["file_name"];
24+
if (!process.env.FILESERVER_URL_PREFIX) {
25+
console.warn(
26+
"FILESERVER_URL_PREFIX is not set. File URLs will not be generated.",
27+
);
28+
return undefined;
29+
}
30+
if (fileName) {
31+
return `${process.env.FILESERVER_URL_PREFIX}/data/${fileName}`;
32+
}
33+
return undefined;
34+
}
35+
2036
export function appendSourceData(
2137
data: StreamData,
2238
sourceNodes?: NodeWithScore<Metadata>[],
@@ -29,6 +45,7 @@ export function appendSourceData(
2945
...node.node.toMutableJSON(),
3046
id: node.node.id_,
3147
score: node.score ?? null,
48+
url: getNodeUrl(node.node.metadata),
3249
})),
3350
},
3451
});

templates/types/streaming/fastapi/app/api/routers/chat.py

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import os
2+
import logging
13
from pydantic import BaseModel
24
from typing import List, Any, Optional, Dict, Tuple
35
from fastapi import APIRouter, Depends, HTTPException, Request, status
@@ -11,6 +13,7 @@
1113

1214
chat_router = r = APIRouter()
1315

16+
logger = logging.getLogger("uvicorn")
1417

1518
class _Message(BaseModel):
1619
role: MessageRole
@@ -38,14 +41,27 @@ class _SourceNodes(BaseModel):
3841
metadata: Dict[str, Any]
3942
score: Optional[float]
4043
text: str
44+
url: Optional[str]
4145

4246
@classmethod
4347
def from_source_node(cls, source_node: NodeWithScore):
48+
metadata = source_node.node.metadata
49+
url = metadata.get("URL")
50+
51+
if not url:
52+
file_name = metadata.get("file_name")
53+
url_prefix = os.getenv("FILESERVER_URL_PREFIX")
54+
if not url_prefix:
55+
logger.warning("Warning: FILESERVER_URL_PREFIX not set in environment variables")
56+
if file_name and url_prefix:
57+
url = f"{url_prefix}/data/{file_name}"
58+
4459
return cls(
4560
id=source_node.node.node_id,
46-
metadata=source_node.node.metadata,
61+
metadata=metadata,
4762
score=source_node.score,
4863
text=source_node.node.text, # type: ignore
64+
url=url
4965
)
5066

5167
@classmethod

templates/types/streaming/nextjs/app/api/chat/stream-helper.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,22 @@ export function appendImageData(data: StreamData, imageUrl?: string) {
1717
});
1818
}
1919

20+
function getNodeUrl(metadata: Metadata) {
21+
const url = metadata["URL"];
22+
if (url) return url;
23+
const fileName = metadata["file_name"];
24+
if (!process.env.FILESERVER_URL_PREFIX) {
25+
console.warn(
26+
"FILESERVER_URL_PREFIX is not set. File URLs will not be generated.",
27+
);
28+
return undefined;
29+
}
30+
if (fileName) {
31+
return `${process.env.FILESERVER_URL_PREFIX}/data/${fileName}`;
32+
}
33+
return undefined;
34+
}
35+
2036
export function appendSourceData(
2137
data: StreamData,
2238
sourceNodes?: NodeWithScore<Metadata>[],
@@ -29,6 +45,7 @@ export function appendSourceData(
2945
...node.node.toMutableJSON(),
3046
id: node.node.id_,
3147
score: node.score ?? null,
48+
url: getNodeUrl(node.node.metadata),
3249
})),
3350
},
3451
});

templates/types/streaming/nextjs/app/components/ui/chat/chat-sources.tsx

Lines changed: 10 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,10 @@ import { Check, Copy } from "lucide-react";
22
import { useMemo } from "react";
33
import { Button } from "../button";
44
import { HoverCard, HoverCardContent, HoverCardTrigger } from "../hover-card";
5-
import { getStaticFileDataUrl } from "../lib/url";
6-
import { SourceData, SourceNode } from "./index";
5+
import { SourceData } from "./index";
76
import { useCopyToClipboard } from "./use-copy-to-clipboard";
87
import PdfDialog from "./widgets/PdfDialog";
98

10-
const DATA_SOURCE_FOLDER = "data";
119
const SCORE_THRESHOLD = 0.3;
1210

1311
function SourceNumberButton({ index }: { index: number }) {
@@ -18,46 +16,11 @@ function SourceNumberButton({ index }: { index: number }) {
1816
);
1917
}
2018

21-
enum NODE_TYPE {
22-
URL,
23-
FILE,
24-
UNKNOWN,
25-
}
26-
2719
type NodeInfo = {
2820
id: string;
29-
type: NODE_TYPE;
30-
path?: string;
3121
url?: string;
3222
};
3323

34-
function getNodeInfo(node: SourceNode): NodeInfo {
35-
if (typeof node.metadata["URL"] === "string") {
36-
const url = node.metadata["URL"];
37-
return {
38-
id: node.id,
39-
type: NODE_TYPE.URL,
40-
path: url,
41-
url,
42-
};
43-
}
44-
if (typeof node.metadata["file_path"] === "string") {
45-
const fileName = node.metadata["file_name"] as string;
46-
const filePath = `${DATA_SOURCE_FOLDER}/${fileName}`;
47-
return {
48-
id: node.id,
49-
type: NODE_TYPE.FILE,
50-
path: node.metadata["file_path"],
51-
url: getStaticFileDataUrl(filePath),
52-
};
53-
}
54-
55-
return {
56-
id: node.id,
57-
type: NODE_TYPE.UNKNOWN,
58-
};
59-
}
60-
6124
export function ChatSources({ data }: { data: SourceData }) {
6225
const sources: NodeInfo[] = useMemo(() => {
6326
// aggregate nodes by url or file_path (get the highest one by score)
@@ -67,8 +30,11 @@ export function ChatSources({ data }: { data: SourceData }) {
6730
.filter((node) => (node.score ?? 1) > SCORE_THRESHOLD)
6831
.sort((a, b) => (b.score ?? 1) - (a.score ?? 1))
6932
.forEach((node) => {
70-
const nodeInfo = getNodeInfo(node);
71-
const key = nodeInfo.path ?? nodeInfo.id; // use id as key for UNKNOWN type
33+
const nodeInfo = {
34+
id: node.id,
35+
url: node.url,
36+
};
37+
const key = nodeInfo.url ?? nodeInfo.id; // use id as key for UNKNOWN type
7238
if (!nodesByPath[key]) {
7339
nodesByPath[key] = nodeInfo;
7440
}
@@ -84,13 +50,12 @@ export function ChatSources({ data }: { data: SourceData }) {
8450
<span className="font-semibold">Sources:</span>
8551
<div className="inline-flex gap-1 items-center">
8652
{sources.map((nodeInfo: NodeInfo, index: number) => {
87-
if (nodeInfo.path?.endsWith(".pdf")) {
53+
if (nodeInfo.url?.endsWith(".pdf")) {
8854
return (
8955
<PdfDialog
9056
key={nodeInfo.id}
9157
documentId={nodeInfo.id}
9258
url={nodeInfo.url!}
93-
path={nodeInfo.path}
9459
trigger={<SourceNumberButton index={index} />}
9560
/>
9661
);
@@ -116,16 +81,16 @@ export function ChatSources({ data }: { data: SourceData }) {
11681
function NodeInfo({ nodeInfo }: { nodeInfo: NodeInfo }) {
11782
const { isCopied, copyToClipboard } = useCopyToClipboard({ timeout: 1000 });
11883

119-
if (nodeInfo.type !== NODE_TYPE.UNKNOWN) {
84+
if (nodeInfo.url) {
12085
// this is a node generated by the web loader or file loader,
12186
// add a link to view its URL and a button to copy the URL to the clipboard
12287
return (
12388
<div className="flex items-center my-2">
12489
<a className="hover:text-blue-900" href={nodeInfo.url} target="_blank">
125-
<span>{nodeInfo.path}</span>
90+
<span>{nodeInfo.url}</span>
12691
</a>
12792
<Button
128-
onClick={() => copyToClipboard(nodeInfo.path!)}
93+
onClick={() => copyToClipboard(nodeInfo.url!)}
12994
size="icon"
13095
variant="ghost"
13196
className="h-12 w-12 shrink-0"

templates/types/streaming/nextjs/app/components/ui/chat/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ export type SourceNode = {
2121
metadata: Record<string, unknown>;
2222
score?: number;
2323
text: string;
24+
url?: string;
2425
};
2526

2627
export type SourceData = {

templates/types/streaming/nextjs/app/components/ui/chat/widgets/PdfDialog.tsx

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ import {
1212

1313
export interface PdfDialogProps {
1414
documentId: string;
15-
path: string;
1615
url: string;
1716
trigger: React.ReactNode;
1817
}
@@ -26,13 +25,13 @@ export default function PdfDialog(props: PdfDialogProps) {
2625
<div className="space-y-2">
2726
<DrawerTitle>PDF Content</DrawerTitle>
2827
<DrawerDescription>
29-
File path:{" "}
28+
File URL:{" "}
3029
<a
3130
className="hover:text-blue-900"
3231
href={props.url}
3332
target="_blank"
3433
>
35-
{props.path}
34+
{props.url}
3635
</a>
3736
</DrawerDescription>
3837
</div>

templates/types/streaming/nextjs/app/components/ui/lib/url.ts

Lines changed: 0 additions & 11 deletions
This file was deleted.

0 commit comments

Comments
 (0)